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