PageRenderTime 512ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/MOVED_TO_GITHUB/mycila-guice/tags/mycila-guice-1.4/src/main/java/com/mycila/guice/Injector.java

http://mycila.googlecode.com/
Java | 389 lines | 313 code | 52 blank | 24 comment | 66 complexity | f0421262a7b03f76897558430895993a MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Copyright (C) 2010 Mathieu Carbou <mathieu.carbou@gmail.com>
  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 com.mycila.guice;
  17. import com.google.inject.Binding;
  18. import com.google.inject.Guice;
  19. import com.google.inject.Key;
  20. import com.google.inject.MembersInjector;
  21. import com.google.inject.Module;
  22. import com.google.inject.Provider;
  23. import com.google.inject.Scope;
  24. import com.google.inject.Singleton;
  25. import com.google.inject.Stage;
  26. import com.google.inject.TypeLiteral;
  27. import com.google.inject.internal.BindingImpl;
  28. import com.google.inject.internal.Scoping;
  29. import com.google.inject.internal.Sets;
  30. import com.google.inject.matcher.Matcher;
  31. import com.google.inject.name.Names;
  32. import com.mycila.guice.annotation.LazySingleton;
  33. import com.mycila.guice.annotation.OnStartSingleton;
  34. import org.guiceyfruit.support.CloseErrors;
  35. import org.guiceyfruit.support.CloseFailedException;
  36. import org.guiceyfruit.support.Closer;
  37. import org.guiceyfruit.support.Closers;
  38. import org.guiceyfruit.support.CompositeCloser;
  39. import org.guiceyfruit.support.HasScopeAnnotation;
  40. import org.guiceyfruit.support.internal.CloseErrorsImpl;
  41. import java.lang.annotation.Annotation;
  42. import java.lang.reflect.Field;
  43. import java.lang.reflect.Type;
  44. import java.util.LinkedHashMap;
  45. import java.util.List;
  46. import java.util.Map;
  47. import java.util.Set;
  48. /**
  49. * @author Mathieu Carbou (mathieu.carbou@gmail.com)
  50. */
  51. public class Injector implements com.google.inject.Injector {
  52. private final com.google.inject.Injector injector;
  53. private Injector(com.google.inject.Injector injector) {
  54. this.injector = injector;
  55. }
  56. public void fireStarted() {
  57. for (Binding<?> binding : getAllBindings().values())
  58. if (OnStartSingleton.class.equals(getScopeAnnotation(binding)))
  59. binding.getProvider().get();
  60. }
  61. // From Guicey Injectors class
  62. public void close() throws CloseFailedException {
  63. close(new CloseErrorsImpl(Injector.class));
  64. }
  65. public void close(CloseErrors errors) throws CloseFailedException {
  66. close(Singleton.class, errors);
  67. close(LazySingleton.class, errors);
  68. close(OnStartSingleton.class, errors);
  69. }
  70. public void close(Class<? extends Annotation> scopeAnnotationToClose) throws CloseFailedException {
  71. close(scopeAnnotationToClose, new CloseErrorsImpl(Injector.class));
  72. }
  73. public void close(Class<? extends Annotation> scopeAnnotationToClose, CloseErrors errors) throws CloseFailedException {
  74. Set<Closer> closers = getInstancesOf(Closer.class);
  75. Closer closer = CompositeCloser.newInstance(closers);
  76. if (closer == null) return;
  77. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  78. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  79. Key<?> key = entry.getKey();
  80. Binding<?> binding = entry.getValue();
  81. closeBinding(key, binding, scopeAnnotationToClose, closer, errors);
  82. }
  83. tryCloseJitBindings(closer, scopeAnnotationToClose, errors);
  84. errors.throwIfNecessary();
  85. }
  86. @SuppressWarnings({"unchecked"})
  87. private void tryCloseJitBindings(Closer closer, Class<? extends Annotation> scopeAnnotationToClose, CloseErrors errors) {
  88. Class<? extends com.google.inject.Injector> type = injector.getClass();
  89. Field field;
  90. try {
  91. field = type.getDeclaredField("jitBindings");
  92. field.setAccessible(true);
  93. Object bindings = field.get(injector);
  94. if (bindings != null) {
  95. if (bindings instanceof Map) {
  96. Map<Key<?>, BindingImpl<?>> map = (Map<Key<?>, BindingImpl<?>>) bindings;
  97. Set<Map.Entry<Key<?>, BindingImpl<?>>> entries = map.entrySet();
  98. for (Map.Entry<Key<?>, BindingImpl<?>> entry : entries) {
  99. closeBinding(entry.getKey(), entry.getValue(), scopeAnnotationToClose, closer, errors);
  100. }
  101. }
  102. }
  103. }
  104. catch (NoSuchFieldException e) {
  105. // ignore - Guice has refactored so we can't access the jit bindings
  106. // System.out.println("No such field! " + e);
  107. }
  108. catch (IllegalAccessException e) {
  109. // ignore - Guice has refactored so we can't access the jit bindings
  110. //System.out.println("Failed to access field: " + field + ". Reason: " + e);
  111. }
  112. }
  113. private void closeBinding(Key<?> key, Binding<?> binding, Class<? extends Annotation> scopeAnnotationToClose, Closer closer, CloseErrors errors) {
  114. Provider<?> provider = binding.getProvider();
  115. Class<? extends Annotation> scopeAnnotation = getScopeAnnotation(binding);
  116. if (scopeAnnotation != null && scopeAnnotation.equals(scopeAnnotationToClose)) {
  117. Object value = provider.get();
  118. if (value != null) {
  119. Closers.close(key, value, closer, errors);
  120. }
  121. }
  122. }
  123. @SuppressWarnings({"unchecked"})
  124. public <T> Binding<T> getBinding(TypeLiteral<T> requiredType, String name) {
  125. return (Binding<T>) getAllBindings().get(Key.get(requiredType, Names.named(name)));
  126. }
  127. @SuppressWarnings({"unchecked"})
  128. public <T> Binding<T> getBinding(TypeLiteral<T> requiredType) {
  129. return (Binding<T>) getAllBindings().get(Key.get(requiredType));
  130. }
  131. public Set<Binding<?>> getBindingsAnnotatedwith(Annotation annotation) {
  132. Set<Binding<?>> answer = Sets.newHashSet();
  133. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  134. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  135. if (entry.getKey().getAnnotation() != null
  136. && entry.getKey().getAnnotation().equals(annotation))
  137. answer.add(entry.getValue());
  138. }
  139. return answer;
  140. }
  141. public Set<Binding<?>> getBindingsAnnotatedwith(Class<? extends Annotation> annotationType) {
  142. Set<Binding<?>> answer = Sets.newHashSet();
  143. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  144. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  145. if (entry.getKey().getAnnotationType() != null
  146. && entry.getKey().getAnnotationType().equals(annotationType))
  147. answer.add(entry.getValue());
  148. }
  149. return answer;
  150. }
  151. public Set<Binding<?>> getBindingsOf(Class<?> baseClass) {
  152. Set<Binding<?>> answer = Sets.newHashSet();
  153. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  154. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  155. Key<?> key = entry.getKey();
  156. Class<?> keyType = getKeyType(key);
  157. if (keyType != null && baseClass.isAssignableFrom(keyType))
  158. answer.add(entry.getValue());
  159. }
  160. return answer;
  161. }
  162. public Set<Binding<?>> getBindingsOf(Matcher<Class> matcher) {
  163. Set<Binding<?>> answer = Sets.newHashSet();
  164. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  165. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  166. Key<?> key = entry.getKey();
  167. Class<?> keyType = getKeyType(key);
  168. if (keyType != null && matcher.matches(keyType))
  169. answer.add(entry.getValue());
  170. }
  171. return answer;
  172. }
  173. public <T> T getInstance(Class<T> type, String name) {
  174. return injector.getInstance(Key.get(type, Names.named(name)));
  175. }
  176. public <T> Set<T> getInstancesOf(Class<T> baseClass) {
  177. Set<T> answer = Sets.newHashSet();
  178. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  179. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  180. Key<?> key = entry.getKey();
  181. Class<?> keyType = getKeyType(key);
  182. if (keyType != null && baseClass.isAssignableFrom(keyType)) {
  183. Binding<?> binding = entry.getValue();
  184. Object value = binding.getProvider().get();
  185. if (value != null) {
  186. T castValue = baseClass.cast(value);
  187. answer.add(castValue);
  188. }
  189. }
  190. }
  191. return answer;
  192. }
  193. @SuppressWarnings({"unchecked"})
  194. public <T> Set<T> getInstancesOf(Matcher<Class> matcher) {
  195. Set<T> answer = Sets.newHashSet();
  196. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  197. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  198. Key<?> key = entry.getKey();
  199. Class<?> keyType = getKeyType(key);
  200. if (keyType != null && matcher.matches(keyType)) {
  201. Binding<?> binding = entry.getValue();
  202. Object value = binding.getProvider().get();
  203. answer.add((T) value);
  204. }
  205. }
  206. return answer;
  207. }
  208. public Class<?> getKeyType(Key<?> key) {
  209. Class<?> keyType = null;
  210. TypeLiteral<?> typeLiteral = key.getTypeLiteral();
  211. Type type = typeLiteral.getType();
  212. if (type instanceof Class)
  213. keyType = (Class<?>) type;
  214. return keyType;
  215. }
  216. @SuppressWarnings({"unchecked"})
  217. public <T> Set<Provider<T>> getProvidersOf(Class<T> baseClass) {
  218. Set<Provider<T>> answer = Sets.newHashSet();
  219. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  220. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  221. Key<?> key = entry.getKey();
  222. Class<?> keyType = getKeyType(key);
  223. if (keyType != null && baseClass.isAssignableFrom(keyType)) {
  224. Binding<?> binding = entry.getValue();
  225. answer.add((Provider<T>) binding.getProvider());
  226. }
  227. }
  228. return answer;
  229. }
  230. @SuppressWarnings({"unchecked"})
  231. public <T> Set<Provider<T>> getProvidersOf(Matcher<Class> matcher) {
  232. Set<Provider<T>> answer = Sets.newHashSet();
  233. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  234. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  235. Key<?> key = entry.getKey();
  236. Class<?> keyType = getKeyType(key);
  237. if (keyType != null && matcher.matches(keyType)) {
  238. Binding<?> binding = entry.getValue();
  239. answer.add((Provider<T>) binding.getProvider());
  240. }
  241. }
  242. return answer;
  243. }
  244. public Class<? extends Annotation> getScopeAnnotation(Binding<?> binding) {
  245. Class<? extends Annotation> scopeAnnotation = null;
  246. if (binding instanceof BindingImpl) {
  247. BindingImpl bindingImpl = (BindingImpl) binding;
  248. Scoping scoping = bindingImpl.getScoping();
  249. if (scoping != null) {
  250. scopeAnnotation = scoping.getScopeAnnotation();
  251. if (scopeAnnotation == null) {
  252. Scope scope = scoping.getScopeInstance();
  253. if (scope instanceof HasScopeAnnotation) {
  254. HasScopeAnnotation hasScopeAnnotation = (HasScopeAnnotation) scope;
  255. scopeAnnotation = hasScopeAnnotation.getScopeAnnotation();
  256. }
  257. if (scopeAnnotation == null && (scoping == Scoping.EAGER_SINGLETON
  258. || scoping == Scoping.SINGLETON_ANNOTATION
  259. || scoping == Scoping.SINGLETON_INSTANCE)) {
  260. scopeAnnotation = Singleton.class;
  261. }
  262. }
  263. }
  264. }
  265. return scopeAnnotation;
  266. }
  267. public boolean hasBinding(Class<?> baseClass) {
  268. return !getBindingsOf(baseClass).isEmpty();
  269. }
  270. public boolean hasBinding(Key<?> key) {
  271. return getAllBindings().get(key) != null;
  272. }
  273. public boolean hasBinding(Matcher<Class> matcher) {
  274. return !getBindingsOf(matcher).isEmpty();
  275. }
  276. public Map<Key<?>, Binding<?>> getAllBindings() {
  277. Map<Key<?>, Binding<?>> all = new LinkedHashMap<Key<?>, Binding<?>>();
  278. com.google.inject.Injector i = injector;
  279. while (i != null) {
  280. all.putAll(i.getBindings());
  281. i = i.getParent();
  282. }
  283. return all;
  284. }
  285. // delegates of guice Injector
  286. public Injector createChildInjector(Iterable<? extends Module> modules) {
  287. return wrap(injector.createChildInjector(modules));
  288. }
  289. public Injector createChildInjector(Module... modules) {
  290. return wrap(injector.createChildInjector(modules));
  291. }
  292. public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
  293. return injector.findBindingsByType(type);
  294. }
  295. public <T> Binding<T> getBinding(Key<T> key) {
  296. return injector.getBinding(key);
  297. }
  298. public <T> Binding<T> getBinding(Class<T> type) {
  299. return injector.getBinding(type);
  300. }
  301. public Map<Key<?>, Binding<?>> getBindings() {
  302. return injector.getBindings();
  303. }
  304. public <T> T getInstance(Key<T> key) {
  305. return injector.getInstance(key);
  306. }
  307. public <T> T getInstance(Class<T> type) {
  308. return injector.getInstance(type);
  309. }
  310. public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
  311. return injector.getMembersInjector(type);
  312. }
  313. public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
  314. return injector.getMembersInjector(typeLiteral);
  315. }
  316. public Injector getParent() {
  317. return wrap(injector.getParent());
  318. }
  319. public <T> Provider<T> getProvider(Key<T> key) {
  320. return injector.getProvider(key);
  321. }
  322. public <T> Provider<T> getProvider(Class<T> type) {
  323. return injector.getProvider(type);
  324. }
  325. public void injectMembers(Object instance) {
  326. injector.injectMembers(instance);
  327. }
  328. public static Injector create(Stage stage, Module... modules) {
  329. return wrap(Guice.createInjector(stage, modules));
  330. }
  331. public static Injector create(Stage stage, Iterable<Module> modules) {
  332. return wrap(Guice.createInjector(stage, modules));
  333. }
  334. public static Injector wrap(com.google.inject.Injector injector) {
  335. return new Injector(injector);
  336. }
  337. }