PageRenderTime 486ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/spice-inject/guice-bean/guice-bean-containers/src/main/java/org/sonatype/guice/bean/containers/Activator.java

https://github.com/peterlynch/spice
Java | 244 lines | 137 code | 46 blank | 61 comment | 10 complexity | 84165d6d612b7985da9dea82cd706ef2 MD5 | raw file
  1. /**
  2. * Copyright (c) 2010 Sonatype, Inc. All rights reserved.
  3. *
  4. * This program is licensed to you under the Apache License Version 2.0,
  5. * and you may not use this file except in compliance with the Apache License Version 2.0.
  6. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
  7. *
  8. * Unless required by applicable law or agreed to in writing,
  9. * software distributed under the Apache License Version 2.0 is distributed on an
  10. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
  12. */
  13. package org.sonatype.guice.bean.containers;
  14. import java.util.Dictionary;
  15. import java.util.HashMap;
  16. import java.util.Hashtable;
  17. import java.util.Map;
  18. import org.osgi.framework.Bundle;
  19. import org.osgi.framework.BundleActivator;
  20. import org.osgi.framework.BundleContext;
  21. import org.osgi.framework.BundleEvent;
  22. import org.osgi.framework.Constants;
  23. import org.osgi.framework.ServiceReference;
  24. import org.osgi.util.tracker.BundleTracker;
  25. import org.osgi.util.tracker.BundleTrackerCustomizer;
  26. import org.osgi.util.tracker.ServiceTracker;
  27. import org.osgi.util.tracker.ServiceTrackerCustomizer;
  28. import org.sonatype.guice.bean.binders.ParameterKeys;
  29. import org.sonatype.guice.bean.binders.SpaceModule;
  30. import org.sonatype.guice.bean.binders.WireModule;
  31. import org.sonatype.guice.bean.locators.DefaultBeanLocator;
  32. import org.sonatype.guice.bean.locators.MutableBeanLocator;
  33. import org.sonatype.guice.bean.reflect.BundleClassSpace;
  34. import org.sonatype.guice.bean.reflect.ClassSpace;
  35. import com.google.inject.Binder;
  36. import com.google.inject.Guice;
  37. import com.google.inject.Injector;
  38. import com.google.inject.Module;
  39. /**
  40. * {@link BundleActivator} that maintains a dynamic {@link Injector} graph by scanning bundles as they come and go.
  41. */
  42. public final class Activator
  43. implements BundleActivator, BundleTrackerCustomizer, ServiceTrackerCustomizer
  44. {
  45. // ----------------------------------------------------------------------
  46. // Constants
  47. // ----------------------------------------------------------------------
  48. static final String BUNDLE_INJECTOR_CLASS_NAME = BundleInjector.class.getName();
  49. static final MutableBeanLocator LOCATOR = new DefaultBeanLocator();
  50. // ----------------------------------------------------------------------
  51. // Implementation fields
  52. // ----------------------------------------------------------------------
  53. private BundleContext bundleContext;
  54. private ServiceTracker serviceTracker;
  55. private BundleTracker bundleTracker;
  56. // ----------------------------------------------------------------------
  57. // Public methods
  58. // ----------------------------------------------------------------------
  59. public void start( final BundleContext context )
  60. {
  61. bundleContext = context;
  62. serviceTracker = new ServiceTracker( context, BUNDLE_INJECTOR_CLASS_NAME, this );
  63. serviceTracker.open();
  64. bundleTracker = new BundleTracker( context, Bundle.ACTIVE, this );
  65. bundleTracker.open();
  66. }
  67. public void stop( final BundleContext context )
  68. {
  69. bundleTracker.close();
  70. serviceTracker.close();
  71. LOCATOR.clear();
  72. }
  73. // ----------------------------------------------------------------------
  74. // Bundle tracking
  75. // ----------------------------------------------------------------------
  76. public Object addingBundle( final Bundle bundle, final BundleEvent event )
  77. {
  78. if ( "org.sonatype.inject".equals( bundle.getSymbolicName() ) )
  79. {
  80. return null; // don't bother scanning the primary infrastructure bundle
  81. }
  82. final String imports = (String) bundle.getHeaders().get( Constants.IMPORT_PACKAGE );
  83. if ( null == imports || !imports.contains( "javax.inject" ) )
  84. {
  85. return null; // bundle doesn't import @Inject, so won't have any beans
  86. }
  87. final ServiceReference[] serviceReferences = bundle.getRegisteredServices();
  88. if ( null != serviceReferences )
  89. {
  90. for ( final ServiceReference ref : serviceReferences )
  91. {
  92. for ( final String name : (String[]) ref.getProperty( Constants.OBJECTCLASS ) )
  93. {
  94. if ( BUNDLE_INJECTOR_CLASS_NAME.equals( name ) )
  95. {
  96. return null; // this bundle already has an injector registered
  97. }
  98. }
  99. }
  100. }
  101. // bootstrap new injector
  102. new BundleInjector( bundle );
  103. return null;
  104. }
  105. public void modifiedBundle( final Bundle bundle, final BundleEvent event, final Object object )
  106. {
  107. // nothing to do
  108. }
  109. public void removedBundle( final Bundle bundle, final BundleEvent event, final Object object )
  110. {
  111. // nothing to do
  112. }
  113. // ----------------------------------------------------------------------
  114. // Service tracking
  115. // ----------------------------------------------------------------------
  116. public Object addingService( final ServiceReference reference )
  117. {
  118. final Object service = bundleContext.getService( reference );
  119. LOCATOR.add( ( (BundleInjector) service ).getInjector() );
  120. return service;
  121. }
  122. public void modifiedService( final ServiceReference reference, final Object service )
  123. {
  124. // nothing to do
  125. }
  126. public void removedService( final ServiceReference reference, final Object service )
  127. {
  128. LOCATOR.remove( ( (BundleInjector) service ).getInjector() );
  129. }
  130. // ----------------------------------------------------------------------
  131. // Implementation types
  132. // ----------------------------------------------------------------------
  133. private static final class BundleInjector
  134. implements /* TODO:ManagedService, */Module
  135. {
  136. // ----------------------------------------------------------------------
  137. // Constants
  138. // ----------------------------------------------------------------------
  139. private static final String[] API = { BUNDLE_INJECTOR_CLASS_NAME /* TODO:, ManagedService.class.getName() */};
  140. // ----------------------------------------------------------------------
  141. // Implementation fields
  142. // ----------------------------------------------------------------------
  143. private final Map<String, String> properties;
  144. private final Injector injector;
  145. // ----------------------------------------------------------------------
  146. // Constructors
  147. // ----------------------------------------------------------------------
  148. BundleInjector( final Bundle bundle )
  149. {
  150. properties = new BundleProperties( bundle.getBundleContext() );
  151. final ClassSpace space = new BundleClassSpace( bundle );
  152. injector = Guice.createInjector( new WireModule( this, new SpaceModule( space ) ) );
  153. final Dictionary<Object, Object> metadata = new Hashtable<Object, Object>();
  154. metadata.put( Constants.SERVICE_PID, "org.sonatype.inject" );
  155. bundle.getBundleContext().registerService( API, this, metadata );
  156. }
  157. // ----------------------------------------------------------------------
  158. // Public methods
  159. // ----------------------------------------------------------------------
  160. public void configure( final Binder binder )
  161. {
  162. binder.bind( ParameterKeys.PROPERTIES ).toInstance( properties );
  163. binder.bind( MutableBeanLocator.class ).toInstance( LOCATOR );
  164. }
  165. public Injector getInjector()
  166. {
  167. return injector;
  168. }
  169. }
  170. private static final class BundleProperties
  171. extends HashMap<String, String>
  172. {
  173. // ----------------------------------------------------------------------
  174. // Constants
  175. // ----------------------------------------------------------------------
  176. private static final long serialVersionUID = 1L;
  177. // ----------------------------------------------------------------------
  178. // Implementation fields
  179. // ----------------------------------------------------------------------
  180. private transient final BundleContext context;
  181. // ----------------------------------------------------------------------
  182. // Constructors
  183. // ----------------------------------------------------------------------
  184. BundleProperties( final BundleContext context )
  185. {
  186. this.context = context;
  187. }
  188. // ----------------------------------------------------------------------
  189. // Public methods
  190. // ----------------------------------------------------------------------
  191. @Override
  192. public String get( final Object key )
  193. {
  194. final String value = super.get( key );
  195. return null != value ? value : context.getProperty( String.valueOf( key ) );
  196. }
  197. }
  198. }