001package de.deepamehta.core.osgi;
002
003import de.deepamehta.core.impl.CoreServiceImpl;
004import de.deepamehta.core.impl.ModelFactoryImpl;
005import de.deepamehta.core.impl.PersistenceLayer;
006import de.deepamehta.core.service.CoreService;
007import de.deepamehta.core.service.ModelFactory;
008import de.deepamehta.core.storage.spi.DeepaMehtaStorage;
009
010import org.osgi.framework.BundleActivator;
011import org.osgi.framework.BundleContext;
012import org.osgi.framework.ServiceReference;
013import org.osgi.service.http.HttpService;
014import org.osgi.util.tracker.ServiceTracker;
015
016import java.util.logging.Level;
017import java.util.logging.Logger;
018
019
020
021public class CoreActivator implements BundleActivator {
022
023    // ---------------------------------------------------------------------------------------------- Instance Variables
024
025    private static BundleContext bundleContext;
026
027    // consumed services
028    private DeepaMehtaStorage storageService;
029    private static HttpService httpService;
030
031    private ServiceTracker storageServiceTracker;
032    private ServiceTracker httpServiceTracker;
033
034    private Logger logger = Logger.getLogger(getClass().getName());
035
036    // -------------------------------------------------------------------------------------------------- Public Methods
037
038
039
040    // **************************************
041    // *** BundleActivator Implementation ***
042    // **************************************
043
044
045
046    @Override
047    public void start(BundleContext bundleContext) {
048        try {
049            logger.info("========== Starting \"DeepaMehta 4 Core\" ==========");
050            this.bundleContext = bundleContext;
051            //
052            registerModelFactory();
053            //
054            (storageServiceTracker = createServiceTracker(DeepaMehtaStorage.class)).open();
055            (httpServiceTracker = createServiceTracker(HttpService.class)).open();
056        } catch (Throwable e) {
057            logger.log(Level.SEVERE, "An error occurred while starting \"DeepaMehta 4 Core\":", e);
058            // Note: here we catch anything, also errors (like NoClassDefFoundError).
059            // If thrown through the OSGi container it would not print out the stacktrace.
060            // File Install would retry to start the bundle endlessly.
061        }
062    }
063
064    @Override
065    public void stop(BundleContext bundleContext) {
066        try {
067            logger.info("========== Stopping \"DeepaMehta 4 Core\" ==========");
068            storageServiceTracker.close();
069            httpServiceTracker.close();
070            //
071            // Note: we do not shutdown the DB here.
072            // The DB shuts down itself through the storage bundle's stop() method.
073        } catch (Throwable e) {
074            logger.log(Level.SEVERE, "An error occurred while stopping \"DeepaMehta 4 Core\":", e);
075            // Note: here we catch anything, also errors (like NoClassDefFoundError).
076            // If thrown through the OSGi container it would not print out the stacktrace.
077        }
078    }
079
080    // ---
081
082    public static CoreService getCoreService() {
083        return getService(CoreService.class);
084    }
085
086    public static ModelFactory getModelFactory() {
087        return getService(ModelFactory.class);
088    }
089
090    public static HttpService getHttpService() {
091        return httpService;
092    }
093
094    // ---
095
096    public static <S> S getService(Class<S> clazz) {
097        S serviceObject = bundleContext.getService(bundleContext.getServiceReference(clazz));
098        if (serviceObject == null) {
099            throw new RuntimeException("Service \"" + clazz.getName() + "\" is not available");
100        }
101        return serviceObject;
102    }
103
104
105
106    // ------------------------------------------------------------------------------------------------- Private Methods
107
108    private void registerModelFactory() {
109        logger.info("Registering ModelFactory service at OSGi framework");
110        bundleContext.registerService(ModelFactory.class.getName(), new ModelFactoryImpl(), null);
111    }
112
113    // ---
114
115    private ServiceTracker createServiceTracker(final Class serviceInterface) {
116        //
117        return new ServiceTracker(bundleContext, serviceInterface.getName(), null) {
118
119            @Override
120            public Object addingService(ServiceReference serviceRef) {
121                Object service = null;
122                try {
123                    service = super.addingService(serviceRef);
124                    addService(service);
125                } catch (Throwable e) {
126                    logger.log(Level.SEVERE, "An error occurred while adding service " + serviceInterface.getName() +
127                        " to \"DeepaMehta 4 Core\":", e);
128                    // Note: here we catch anything, also errors (like NoClassDefFoundError).
129                    // If thrown through the OSGi container it would not print out the stacktrace.
130                }
131                return service;
132            }
133
134            @Override
135            public void removedService(ServiceReference ref, Object service) {
136                try {
137                    removeService(service);
138                    super.removedService(ref, service);
139                } catch (Throwable e) {
140                    logger.log(Level.SEVERE, "An error occurred while removing service " + serviceInterface.getName() +
141                        " from \"DeepaMehta 4 Core\":", e);
142                    // Note: here we catch anything, also errors (like NoClassDefFoundError).
143                    // If thrown through the OSGi container it would not print out the stacktrace.
144                }
145            }
146        };
147    }
148
149    // ---
150
151    private void addService(Object service) {
152        if (service instanceof DeepaMehtaStorage) {
153            logger.info("Adding storage service to DeepaMehta 4 Core");
154            storageService = (DeepaMehtaStorage) service;
155            checkRequirementsForActivation();
156        } else if (service instanceof HttpService) {
157            logger.info("Adding HTTP service to DeepaMehta 4 Core");
158            httpService = (HttpService) service;
159            checkRequirementsForActivation();
160        }
161    }
162
163    private void removeService(Object service) {
164        if (service == storageService) {
165            logger.info("Removing storage service from DeepaMehta 4 Core");
166            storageService = null;
167        } else if (service == httpService) {
168            logger.info("Removing HTTP service from DeepaMehta 4 Core");
169            httpService = null;
170        }
171    }
172
173    // ---
174
175    private void checkRequirementsForActivation() {
176        if (storageService != null && httpService != null) {
177            logger.info("Registering DeepaMehta 4 core service at OSGi framework");
178            bundleContext.registerService(CoreService.class.getName(),
179                new CoreServiceImpl(new PersistenceLayer(storageService), bundleContext),
180                null
181            );
182        }
183    }
184}