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

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

http://mycila.googlecode.com/
Java | 363 lines | 293 code | 46 blank | 24 comment | 64 complexity | e5699c7652ade2992fdfd1f3e764bd46 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Copyright (C) 2009 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. public Set<Binding<?>> getBindingsAnnotatedwith(Annotation annotation) {
  115. Set<Binding<?>> answer = Sets.newHashSet();
  116. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  117. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  118. if (entry.getKey().getAnnotation() != null
  119. && entry.getKey().getAnnotation().equals(annotation))
  120. answer.add(entry.getValue());
  121. }
  122. return answer;
  123. }
  124. public Set<Binding<?>> getBindingsAnnotatedwith(Class<? extends Annotation> annotationType) {
  125. Set<Binding<?>> answer = Sets.newHashSet();
  126. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  127. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  128. if (entry.getKey().getAnnotationType() != null
  129. && entry.getKey().getAnnotationType().equals(annotationType))
  130. answer.add(entry.getValue());
  131. }
  132. return answer;
  133. }
  134. public Set<Binding<?>> getBindingsOf(Class<?> baseClass) {
  135. Set<Binding<?>> answer = Sets.newHashSet();
  136. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  137. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  138. Key<?> key = entry.getKey();
  139. Class<?> keyType = getKeyType(key);
  140. if (keyType != null && baseClass.isAssignableFrom(keyType))
  141. answer.add(entry.getValue());
  142. }
  143. return answer;
  144. }
  145. public Set<Binding<?>> getBindingsOf(Matcher<Class> matcher) {
  146. Set<Binding<?>> answer = Sets.newHashSet();
  147. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  148. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  149. Key<?> key = entry.getKey();
  150. Class<?> keyType = getKeyType(key);
  151. if (keyType != null && matcher.matches(keyType))
  152. answer.add(entry.getValue());
  153. }
  154. return answer;
  155. }
  156. public <T> T getInstance(Class<T> type, String name) {
  157. return injector.getInstance(Key.get(type, Names.named(name)));
  158. }
  159. public <T> Set<T> getInstancesOf(Class<T> baseClass) {
  160. Set<T> answer = Sets.newHashSet();
  161. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  162. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  163. Key<?> key = entry.getKey();
  164. Class<?> keyType = getKeyType(key);
  165. if (keyType != null && baseClass.isAssignableFrom(keyType)) {
  166. Binding<?> binding = entry.getValue();
  167. Object value = binding.getProvider().get();
  168. if (value != null) {
  169. T castValue = baseClass.cast(value);
  170. answer.add(castValue);
  171. }
  172. }
  173. }
  174. return answer;
  175. }
  176. @SuppressWarnings({"unchecked"})
  177. public <T> Set<T> getInstancesOf(Matcher<Class> matcher) {
  178. Set<T> answer = Sets.newHashSet();
  179. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  180. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  181. Key<?> key = entry.getKey();
  182. Class<?> keyType = getKeyType(key);
  183. if (keyType != null && matcher.matches(keyType)) {
  184. Binding<?> binding = entry.getValue();
  185. Object value = binding.getProvider().get();
  186. answer.add((T) value);
  187. }
  188. }
  189. return answer;
  190. }
  191. public Class<?> getKeyType(Key<?> key) {
  192. Class<?> keyType = null;
  193. TypeLiteral<?> typeLiteral = key.getTypeLiteral();
  194. Type type = typeLiteral.getType();
  195. if (type instanceof Class)
  196. keyType = (Class<?>) type;
  197. return keyType;
  198. }
  199. @SuppressWarnings({"unchecked"})
  200. public <T> Set<Provider<T>> getProvidersOf(Class<T> baseClass) {
  201. Set<Provider<T>> answer = Sets.newHashSet();
  202. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  203. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  204. Key<?> key = entry.getKey();
  205. Class<?> keyType = getKeyType(key);
  206. if (keyType != null && baseClass.isAssignableFrom(keyType)) {
  207. Binding<?> binding = entry.getValue();
  208. answer.add((Provider<T>) binding.getProvider());
  209. }
  210. }
  211. return answer;
  212. }
  213. @SuppressWarnings({"unchecked"})
  214. public <T> Set<Provider<T>> getProvidersOf(Matcher<Class> matcher) {
  215. Set<Provider<T>> answer = Sets.newHashSet();
  216. Set<Map.Entry<Key<?>, Binding<?>>> entries = getAllBindings().entrySet();
  217. for (Map.Entry<Key<?>, Binding<?>> entry : entries) {
  218. Key<?> key = entry.getKey();
  219. Class<?> keyType = getKeyType(key);
  220. if (keyType != null && matcher.matches(keyType)) {
  221. Binding<?> binding = entry.getValue();
  222. answer.add((Provider<T>) binding.getProvider());
  223. }
  224. }
  225. return answer;
  226. }
  227. public Class<? extends Annotation> getScopeAnnotation(Binding<?> binding) {
  228. Class<? extends Annotation> scopeAnnotation = null;
  229. if (binding instanceof BindingImpl) {
  230. BindingImpl bindingImpl = (BindingImpl) binding;
  231. Scoping scoping = bindingImpl.getScoping();
  232. if (scoping != null) {
  233. scopeAnnotation = scoping.getScopeAnnotation();
  234. if (scopeAnnotation == null) {
  235. Scope scope = scoping.getScopeInstance();
  236. if (scope instanceof HasScopeAnnotation) {
  237. HasScopeAnnotation hasScopeAnnotation = (HasScopeAnnotation) scope;
  238. scopeAnnotation = hasScopeAnnotation.getScopeAnnotation();
  239. }
  240. if (scopeAnnotation == null && (scoping == Scoping.EAGER_SINGLETON
  241. || scoping == Scoping.SINGLETON_ANNOTATION
  242. || scoping == Scoping.SINGLETON_INSTANCE)) {
  243. scopeAnnotation = Singleton.class;
  244. }
  245. }
  246. }
  247. }
  248. return scopeAnnotation;
  249. }
  250. public boolean hasBinding(Class<?> baseClass) {
  251. return !getBindingsOf(baseClass).isEmpty();
  252. }
  253. public boolean hasBinding(Key<?> key) {
  254. return getBinding(key) != null;
  255. }
  256. public boolean hasBinding(Matcher<Class> matcher) {
  257. return !getBindingsOf(matcher).isEmpty();
  258. }
  259. public Map<Key<?>, Binding<?>> getAllBindings() {
  260. Map<Key<?>, Binding<?>> all = new LinkedHashMap<Key<?>, Binding<?>>();
  261. com.google.inject.Injector i = injector;
  262. while (i != null) {
  263. all.putAll(i.getBindings());
  264. i = i.getParent();
  265. }
  266. return all;
  267. }
  268. // delegates of guice Injector
  269. public Injector createChildInjector(Iterable<? extends Module> modules) {
  270. return wrap(injector.createChildInjector(modules));
  271. }
  272. public Injector createChildInjector(Module... modules) {
  273. return wrap(injector.createChildInjector(modules));
  274. }
  275. public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type) {
  276. return injector.findBindingsByType(type);
  277. }
  278. public <T> Binding<T> getBinding(Key<T> key) {
  279. return injector.getBinding(key);
  280. }
  281. public <T> Binding<T> getBinding(Class<T> type) {
  282. return injector.getBinding(type);
  283. }
  284. public Map<Key<?>, Binding<?>> getBindings() {
  285. return injector.getBindings();
  286. }
  287. public <T> T getInstance(Key<T> key) {
  288. return injector.getInstance(key);
  289. }
  290. public <T> T getInstance(Class<T> type) {
  291. return injector.getInstance(type);
  292. }
  293. public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
  294. return injector.getMembersInjector(type);
  295. }
  296. public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
  297. return injector.getMembersInjector(typeLiteral);
  298. }
  299. public Injector getParent() {
  300. return wrap(injector.getParent());
  301. }
  302. public <T> Provider<T> getProvider(Key<T> key) {
  303. return injector.getProvider(key);
  304. }
  305. public <T> Provider<T> getProvider(Class<T> type) {
  306. return injector.getProvider(type);
  307. }
  308. public void injectMembers(Object instance) {
  309. injector.injectMembers(instance);
  310. }
  311. public static Injector create(Stage stage, Module... modules) {
  312. return wrap(Guice.createInjector(stage, modules));
  313. }
  314. public static Injector wrap(com.google.inject.Injector injector) {
  315. return new Injector(injector);
  316. }
  317. }