PageRenderTime 68ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 1ms

/extensions/activation/src/main/java/org/ops4j/peaberry/activation/internal/BundleActivation.java

https://github.com/sonatype/sonatype-peaberry
Java | 193 lines | 93 code | 24 blank | 76 comment | 12 complexity | fbefe64f58e1a5df21a4fe48f301960f MD5 | raw file
  1. /**
  2. * Copyright (C) 2009 Todor Boev
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.ops4j.peaberry.activation.internal;
  17. import java.lang.annotation.Annotation;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.ListIterator;
  21. import java.util.Map;
  22. import org.ops4j.peaberry.Export;
  23. import org.ops4j.peaberry.Peaberry;
  24. import org.ops4j.peaberry.activation.PeaberryActivationException;
  25. import org.osgi.framework.Bundle;
  26. import com.google.inject.Binding;
  27. import com.google.inject.Guice;
  28. import com.google.inject.Injector;
  29. import com.google.inject.Key;
  30. import com.google.inject.Module;
  31. import com.google.inject.Scope;
  32. import com.google.inject.Scopes;
  33. import com.google.inject.Singleton;
  34. import com.google.inject.spi.BindingScopingVisitor;
  35. /**
  36. * Handles the activation of a single bundle.
  37. *
  38. * @author rinsvind@gmail.com (Todor Boev)
  39. */
  40. public class BundleActivation {
  41. private static final BindingScopingVisitor<Boolean> SINGLETONS =
  42. new BindingScopingVisitor<Boolean>() {
  43. public Boolean visitEagerSingleton() {
  44. return true;
  45. }
  46. public Boolean visitScope(final Scope scope) {
  47. return Scopes.SINGLETON == scope;
  48. }
  49. public Boolean visitScopeAnnotation(final Class<? extends Annotation> tag) {
  50. return Singleton.class == tag;
  51. }
  52. public Boolean visitNoScoping() {
  53. return false;
  54. }
  55. };
  56. // private static final BindingTargetVisitor<Object, Boolean> INSTANCES =
  57. // new BindingTargetVisitor<Object, Boolean>() {
  58. // public Boolean visit(InstanceBinding<?> arg) {
  59. // return true;
  60. // }
  61. //
  62. // public Boolean visit(ProviderInstanceBinding<?> arg) {
  63. // return false;
  64. // }
  65. //
  66. // public Boolean visit(ProviderKeyBinding<?> arg) {
  67. // return false;
  68. // }
  69. //
  70. // public Boolean visit(LinkedKeyBinding<?> arg) {
  71. // return false;
  72. // }
  73. //
  74. // public Boolean visit(ExposedBinding<?> arg) {
  75. // return false;
  76. // }
  77. //
  78. // public Boolean visit(UntargettedBinding<?> arg) {
  79. // return false;
  80. // }
  81. //
  82. // public Boolean visit(ConstructorBinding<?> arg) {
  83. // return false;
  84. // }
  85. //
  86. // public Boolean visit(ConvertedConstantBinding<?> arg) {
  87. // return false;
  88. // }
  89. //
  90. // public Boolean visit(ProviderBinding<?> arg) {
  91. // return false;
  92. // }
  93. // };
  94. private final Bundle bundle;
  95. private final Class<? extends Module> moduleClass;
  96. private List<BundleRoot<?>> roots;
  97. private Injector injector;
  98. public BundleActivation(final Bundle bundle, final Class<? extends Module> moduleClass) {
  99. this.bundle = bundle;
  100. this.moduleClass = moduleClass;
  101. }
  102. public void activate() {
  103. if (isActive()) {
  104. throw new PeaberryActivationException(Bundles.toString(bundle) + " already activated");
  105. }
  106. createInjector();
  107. createRoots();
  108. for (final BundleRoot<?> root : roots) {
  109. root.activate(injector);
  110. }
  111. }
  112. public void deactivate() {
  113. if (!isActive()) {
  114. return;
  115. }
  116. /*
  117. * Deactivate in reverse order. This should bring down the services before
  118. * we stop the active roots.
  119. */
  120. for (final ListIterator<BundleRoot<?>> iter = roots.listIterator(roots.size()); iter
  121. .hasPrevious();) {
  122. try {
  123. iter.previous().deactivate();
  124. } catch (final Exception e) {
  125. /*
  126. * FIX Accumulate these into an error list and at the end of the
  127. * deactivation toss an exception containing the list like Guice does
  128. */
  129. e.printStackTrace();
  130. }
  131. }
  132. injector = null;
  133. roots = null;
  134. }
  135. private boolean isActive() {
  136. return injector != null;
  137. }
  138. private void createInjector() {
  139. injector =
  140. Guice.createInjector(Peaberry.osgiModule(bundle.getBundleContext()), Reflection
  141. .create(moduleClass));
  142. }
  143. @SuppressWarnings("unchecked")
  144. private void createRoots() {
  145. final List<BundleRoot<?>> singletons = new ArrayList<BundleRoot<?>>();
  146. final List<BundleRoot<?>> exports = new ArrayList<BundleRoot<?>>();
  147. /* Scan for singletons first */
  148. for (final Map.Entry<Key<?>, Binding<?>> e : injector.getBindings().entrySet()) {
  149. final Key<?> k = e.getKey();
  150. final Binding<?> b = e.getValue();
  151. /*
  152. * Exports are captured before singletons. In this way exports that have
  153. * been redundantly marked as singleton are treated correctly rather than
  154. * scanned for start/stop methods etc.
  155. */
  156. if (Export.class == k.getTypeLiteral().getRawType()) {
  157. exports.add(new ExportBundleRoot((Key<Export<?>>) k));
  158. } else if (b.acceptScopingVisitor(SINGLETONS) /*|| b.acceptTargetVisitor(INSTANCES)*/) {
  159. singletons.add(new SingletonBundleRoot((Key<Object>) k));
  160. }
  161. }
  162. /*
  163. * To get deterministic startup we activate the singletons before we export
  164. * some of them to control flow from other bundles.
  165. */
  166. singletons.addAll(exports);
  167. roots = singletons;
  168. }
  169. }