PageRenderTime 1051ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/sisu-2.2.3/sisu-inject/containers/guice-bean/guice-bean-containers/src/main/java/org/sonatype/guice/bean/containers/SisuActivator.java

#
Java | 295 lines | 183 code | 50 blank | 62 comment | 15 complexity | f5096a77c66128d78bd59848baa717dc MD5 | raw file
Possible License(s): Apache-2.0, EPL-1.0
  1. /*******************************************************************************
  2. * Copyright (c) 2010-2011 Sonatype, Inc.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * and Apache License v2.0 which accompanies this distribution.
  6. * The Eclipse Public License is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. * The Apache License v2.0 is available at
  9. * http://www.apache.org/licenses/LICENSE-2.0.html
  10. * You may elect to redistribute this code under either of these licenses.
  11. *******************************************************************************/
  12. package org.sonatype.guice.bean.containers;
  13. import java.util.AbstractMap;
  14. import java.util.Collections;
  15. import java.util.Dictionary;
  16. import java.util.Hashtable;
  17. import java.util.Map;
  18. import java.util.Set;
  19. import org.osgi.framework.Bundle;
  20. import org.osgi.framework.BundleActivator;
  21. import org.osgi.framework.BundleContext;
  22. import org.osgi.framework.BundleEvent;
  23. import org.osgi.framework.Constants;
  24. import org.osgi.framework.ServiceReference;
  25. import org.osgi.util.tracker.BundleTracker;
  26. import org.osgi.util.tracker.BundleTrackerCustomizer;
  27. import org.osgi.util.tracker.ServiceTracker;
  28. import org.osgi.util.tracker.ServiceTrackerCustomizer;
  29. import org.sonatype.guice.bean.binders.ParameterKeys;
  30. import org.sonatype.guice.bean.binders.SpaceModule;
  31. import org.sonatype.guice.bean.binders.WireModule;
  32. import org.sonatype.guice.bean.locators.DefaultBeanLocator;
  33. import org.sonatype.guice.bean.locators.MutableBeanLocator;
  34. import org.sonatype.guice.bean.reflect.BundleClassSpace;
  35. import org.sonatype.guice.bean.reflect.ClassSpace;
  36. import org.sonatype.guice.bean.reflect.Logs;
  37. import org.sonatype.inject.BeanScanning;
  38. import com.google.inject.Binder;
  39. import com.google.inject.Guice;
  40. import com.google.inject.Injector;
  41. import com.google.inject.Module;
  42. /**
  43. * {@link BundleActivator} that maintains a dynamic {@link Injector} graph by scanning bundles as they come and go.
  44. */
  45. public final class SisuActivator
  46. implements BundleActivator, BundleTrackerCustomizer, ServiceTrackerCustomizer
  47. {
  48. // ----------------------------------------------------------------------
  49. // Constants
  50. // ----------------------------------------------------------------------
  51. static final String CONTAINER_SYMBOLIC_NAME = "org.sonatype.inject";
  52. static final String BUNDLE_INJECTOR_CLASS_NAME = BundleInjector.class.getName();
  53. // ----------------------------------------------------------------------
  54. // Implementation fields
  55. // ----------------------------------------------------------------------
  56. static final MutableBeanLocator locator = new DefaultBeanLocator();
  57. private BundleContext bundleContext;
  58. private ServiceTracker serviceTracker;
  59. private BundleTracker bundleTracker;
  60. // ----------------------------------------------------------------------
  61. // Public methods
  62. // ----------------------------------------------------------------------
  63. public void start( final BundleContext context )
  64. {
  65. bundleContext = context;
  66. serviceTracker = new ServiceTracker( context, BUNDLE_INJECTOR_CLASS_NAME, this );
  67. serviceTracker.open();
  68. bundleTracker = new BundleTracker( context, Bundle.STARTING | Bundle.ACTIVE, this );
  69. bundleTracker.open();
  70. }
  71. public void stop( final BundleContext context )
  72. {
  73. bundleTracker.close();
  74. serviceTracker.close();
  75. locator.clear();
  76. }
  77. // ----------------------------------------------------------------------
  78. // Bundle tracking
  79. // ----------------------------------------------------------------------
  80. public Object addingBundle( final Bundle bundle, final BundleEvent event )
  81. {
  82. if ( CONTAINER_SYMBOLIC_NAME.equals( bundle.getSymbolicName() ) )
  83. {
  84. return null; // this is our container, ignore it to avoid circularity errors
  85. }
  86. if ( needsScanning( bundle ) && getBundleInjectorService( bundle ) == null )
  87. {
  88. try
  89. {
  90. new BundleInjector( bundle );
  91. }
  92. catch ( final Throwable e )
  93. {
  94. Logs.warn( "Error starting {}", bundle, e );
  95. }
  96. }
  97. return null;
  98. }
  99. public void modifiedBundle( final Bundle bundle, final BundleEvent event, final Object object )
  100. {
  101. // nothing to do
  102. }
  103. public void removedBundle( final Bundle bundle, final BundleEvent event, final Object object )
  104. {
  105. // nothing to do
  106. }
  107. // ----------------------------------------------------------------------
  108. // Service tracking
  109. // ----------------------------------------------------------------------
  110. @SuppressWarnings( "deprecation" )
  111. public Object addingService( final ServiceReference reference )
  112. {
  113. final Object service = bundleContext.getService( reference );
  114. locator.add( ( (BundleInjector) service ).getInjector(), 0 );
  115. return service;
  116. }
  117. public void modifiedService( final ServiceReference reference, final Object service )
  118. {
  119. // nothing to do
  120. }
  121. public void removedService( final ServiceReference reference, final Object service )
  122. {
  123. locator.remove( ( (BundleInjector) service ).getInjector() );
  124. }
  125. // ----------------------------------------------------------------------
  126. // Implementation methods
  127. // ----------------------------------------------------------------------
  128. private static boolean needsScanning( final Bundle bundle )
  129. {
  130. final Dictionary<?, ?> headers = bundle.getHeaders();
  131. final String host = (String) headers.get( Constants.FRAGMENT_HOST );
  132. if ( null != host )
  133. {
  134. return false; // fragment, we'll scan it when we process the host
  135. }
  136. final String imports = (String) headers.get( Constants.IMPORT_PACKAGE );
  137. if ( null == imports )
  138. {
  139. return false; // doesn't import any interesting injection packages
  140. }
  141. return imports.contains( "javax.inject" ) || imports.contains( "com.google.inject" );
  142. }
  143. private static ServiceReference getBundleInjectorService( final Bundle bundle )
  144. {
  145. final ServiceReference[] serviceReferences = bundle.getRegisteredServices();
  146. if ( null != serviceReferences )
  147. {
  148. for ( final ServiceReference ref : serviceReferences )
  149. {
  150. for ( final String name : (String[]) ref.getProperty( Constants.OBJECTCLASS ) )
  151. {
  152. if ( BUNDLE_INJECTOR_CLASS_NAME.equals( name ) )
  153. {
  154. return ref;
  155. }
  156. }
  157. }
  158. }
  159. return null;
  160. }
  161. // ----------------------------------------------------------------------
  162. // Implementation types
  163. // ----------------------------------------------------------------------
  164. private static final class BundleInjector
  165. implements /* TODO:ManagedService, */Module
  166. {
  167. // ----------------------------------------------------------------------
  168. // Constants
  169. // ----------------------------------------------------------------------
  170. private static final String[] API = { BUNDLE_INJECTOR_CLASS_NAME /* TODO:, ManagedService.class.getName() */};
  171. // ----------------------------------------------------------------------
  172. // Implementation fields
  173. // ----------------------------------------------------------------------
  174. private final Map<?, ?> properties;
  175. private final Injector injector;
  176. // ----------------------------------------------------------------------
  177. // Constructors
  178. // ----------------------------------------------------------------------
  179. BundleInjector( final Bundle bundle )
  180. {
  181. properties = new BundleProperties( bundle.getBundleContext() );
  182. final ClassSpace space = new BundleClassSpace( bundle );
  183. final BeanScanning scanning = Main.selectScanning( properties );
  184. injector = Guice.createInjector( new WireModule( this, new SpaceModule( space, scanning ) ) );
  185. final Dictionary<Object, Object> metadata = new Hashtable<Object, Object>();
  186. metadata.put( Constants.SERVICE_PID, CONTAINER_SYMBOLIC_NAME );
  187. bundle.getBundleContext().registerService( API, this, metadata );
  188. }
  189. // ----------------------------------------------------------------------
  190. // Public methods
  191. // ----------------------------------------------------------------------
  192. public void configure( final Binder binder )
  193. {
  194. binder.requestStaticInjection( SisuGuice.class );
  195. binder.bind( ParameterKeys.PROPERTIES ).toInstance( properties );
  196. binder.bind( MutableBeanLocator.class ).toInstance( locator );
  197. }
  198. public Injector getInjector()
  199. {
  200. return injector;
  201. }
  202. }
  203. private static final class BundleProperties
  204. extends AbstractMap<Object, Object>
  205. {
  206. // ----------------------------------------------------------------------
  207. // Constants
  208. // ----------------------------------------------------------------------
  209. private static final long serialVersionUID = 1L;
  210. // ----------------------------------------------------------------------
  211. // Implementation fields
  212. // ----------------------------------------------------------------------
  213. private transient final BundleContext context;
  214. // ----------------------------------------------------------------------
  215. // Constructors
  216. // ----------------------------------------------------------------------
  217. BundleProperties( final BundleContext context )
  218. {
  219. this.context = context;
  220. }
  221. // ----------------------------------------------------------------------
  222. // Public methods
  223. // ----------------------------------------------------------------------
  224. @Override
  225. public Object get( final Object key )
  226. {
  227. return context.getProperty( String.valueOf( key ) );
  228. }
  229. @Override
  230. public boolean containsKey( final Object key )
  231. {
  232. return null != get( key );
  233. }
  234. @Override
  235. public Set<Entry<Object, Object>> entrySet()
  236. {
  237. return Collections.emptySet();
  238. }
  239. @Override
  240. public int size()
  241. {
  242. return 0;
  243. }
  244. }
  245. }