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