001package systems.dmx.storage.neo4j;
002
003import systems.dmx.core.service.ModelFactory;
004import systems.dmx.core.storage.spi.DMXStorage;
005
006import org.osgi.framework.BundleActivator;
007import org.osgi.framework.BundleContext;
008import org.osgi.framework.ServiceReference;
009import org.osgi.util.tracker.ServiceTracker;
010
011import java.util.logging.Level;
012import java.util.logging.Logger;
013
014
015
016public class Neo4jStorageActivator implements BundleActivator {
017
018    // ------------------------------------------------------------------------------------------------------- Constants
019
020    private static final String DATABASE_PATH = System.getProperty("dmx.database.path", "deepamehta-db");
021    // Note: the default value is required in case no config file is in effect. This applies when DM is started
022    // via feature:install from Karaf. The default value must match the value defined in project POM.
023
024    // ---------------------------------------------------------------------------------------------- Instance Variables
025
026    private static BundleContext bundleContext;
027
028    // consumed service
029    ModelFactory mf;
030
031    private ServiceTracker modelFactoryTracker;
032
033    // provided service
034    private DMXStorage storage;
035
036    private final Logger logger = Logger.getLogger(getClass().getName());
037
038    // -------------------------------------------------------------------------------------------------- Public Methods
039
040
041
042    // **************************************
043    // *** BundleActivator Implementation ***
044    // **************************************
045
046
047
048    @Override
049    public void start(BundleContext bundleContext) {
050        try {
051            logger.info("========== Starting \"DMX Storage - Neo4j\" ==========");
052            this.bundleContext = bundleContext;
053            //
054            (modelFactoryTracker = createServiceTracker(ModelFactory.class)).open();
055        } catch (Throwable e) {
056            logger.log(Level.SEVERE, "An error occurred while starting \"DMX Storage - Neo4j\":", e);
057            // Note: here we catch anything, also errors (like NoClassDefFoundError).
058            // If thrown through the OSGi container it would not print out the stacktrace.
059            // File Install would retry to start the bundle endlessly.
060        }
061    }
062
063    @Override
064    public void stop(BundleContext bundleContext) {
065        try {
066            logger.info("========== Stopping \"DMX Storage - Neo4j\" ==========");
067            modelFactoryTracker.close();
068            //
069            if (storage != null) {
070                storage.shutdown();
071            }
072        } catch (Throwable e) {
073            logger.log(Level.SEVERE, "An error occurred while stopping \"DMX Storage - Neo4j\":", e);
074            // Note: here we catch anything, also errors (like NoClassDefFoundError).
075            // If thrown through the OSGi container it would not print out the stacktrace.
076        }
077    }
078
079    // ------------------------------------------------------------------------------------------------- Private Methods
080
081    private ServiceTracker createServiceTracker(final Class serviceInterface) {
082        //
083        return new ServiceTracker(bundleContext, serviceInterface.getName(), null) {
084
085            @Override
086            public Object addingService(ServiceReference serviceRef) {
087                Object service = null;
088                try {
089                    service = super.addingService(serviceRef);
090                    addService(service);
091                } catch (Throwable e) {
092                    logger.log(Level.SEVERE, "An error occurred while adding service " + serviceInterface.getName() +
093                        " to \"DMX Storage - Neo4j\":", e);
094                    // Note: here we catch anything, also errors (like NoClassDefFoundError).
095                    // If thrown through the OSGi container it would not print out the stacktrace.
096                }
097                return service;
098            }
099
100            @Override
101            public void removedService(ServiceReference ref, Object service) {
102                try {
103                    removeService(service);
104                    super.removedService(ref, service);
105                } catch (Throwable e) {
106                    logger.log(Level.SEVERE, "An error occurred while removing service " + serviceInterface.getName() +
107                        " from \"DMX Storage - Neo4j\":", e);
108                    // Note: here we catch anything, also errors (like NoClassDefFoundError).
109                    // If thrown through the OSGi container it would not print out the stacktrace.
110                }
111            }
112        };
113    }
114
115    // ---
116
117    private void addService(Object service) {
118        if (service instanceof ModelFactory) {
119            logger.info("Adding ModelFactory service to DMX Storage - Neo4j");
120            mf = (ModelFactory) service;
121            checkRequirementsForActivation();
122        }
123    }
124
125    private void removeService(Object service) {
126        if (service == mf) {
127            logger.info("Removing ModelFactory service from DMX Storage - Neo4j");
128            mf = null;
129        }
130    }
131
132    // ---
133
134    private void checkRequirementsForActivation() {
135        if (mf != null) {
136            storage = new Neo4jStorage(DATABASE_PATH, mf);
137            //
138            logger.info("Registering DMX storage service - Neo4j - at OSGi framework");
139            bundleContext.registerService(DMXStorage.class.getName(), storage, null);
140        }
141    }
142}