PageRenderTime 859ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

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