PageRenderTime 1326ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/struts2/plugin/src/com/google/inject/struts2/GuiceObjectFactory.java

https://github.com/jstrachan/guicey
Java | 241 lines | 172 code | 34 blank | 35 comment | 17 complexity | e6d4ab93af7879dcd35973b426340605 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Copyright (C) 2006 Google Inc.
  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.google.inject.struts2;
  17. import com.google.inject.AbstractModule;
  18. import com.google.inject.Binder;
  19. import com.google.inject.Guice;
  20. import com.google.inject.Injector;
  21. import com.google.inject.Module;
  22. import com.google.inject.ScopeAnnotation;
  23. import com.google.inject.servlet.ServletModule;
  24. import com.opensymphony.xwork2.ActionInvocation;
  25. import com.opensymphony.xwork2.ObjectFactory;
  26. import com.opensymphony.xwork2.config.ConfigurationException;
  27. import com.opensymphony.xwork2.config.entities.InterceptorConfig;
  28. import com.opensymphony.xwork2.inject.Inject;
  29. import com.opensymphony.xwork2.interceptor.Interceptor;
  30. import java.lang.annotation.Annotation;
  31. import java.util.ArrayList;
  32. import java.util.HashSet;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.Set;
  36. import java.util.logging.Logger;
  37. public class GuiceObjectFactory extends ObjectFactory {
  38. static final Logger logger =
  39. Logger.getLogger(GuiceObjectFactory.class.getName());
  40. Module module;
  41. volatile Injector injector;
  42. boolean developmentMode = false;
  43. List<ProvidedInterceptor> interceptors
  44. = new ArrayList<ProvidedInterceptor>();
  45. @Override
  46. public boolean isNoArgConstructorRequired() {
  47. return false;
  48. }
  49. @Inject(value = "guice.module", required = false)
  50. void setModule(String moduleClassName) {
  51. try {
  52. // Instantiate user's module.
  53. @SuppressWarnings({"unchecked"})
  54. Class<? extends Module> moduleClass =
  55. (Class<? extends Module>) Class.forName(moduleClassName);
  56. this.module = moduleClass.newInstance();
  57. } catch (Exception e) {
  58. throw new RuntimeException(e);
  59. }
  60. }
  61. @Inject(value = "struts.devMode", required = false)
  62. void setDevelopmentMode(String developmentMode) {
  63. this.developmentMode = developmentMode.trim().equals("true");
  64. }
  65. Set<Class<?>> boundClasses = new HashSet<Class<?>>();
  66. public Class getClassInstance(String name) throws ClassNotFoundException {
  67. Class<?> clazz = super.getClassInstance(name);
  68. synchronized (this) {
  69. if (injector == null) {
  70. // We can only bind each class once.
  71. if (!boundClasses.contains(clazz)) {
  72. try {
  73. // Calling these methods now helps us detect ClassNotFoundErrors
  74. // early.
  75. clazz.getDeclaredFields();
  76. clazz.getDeclaredMethods();
  77. boundClasses.add(clazz);
  78. } catch (Throwable t) {
  79. // Struts should still work even though some classes aren't in the
  80. // classpath. It appears we always get the exception here when
  81. // this is the case.
  82. return clazz;
  83. }
  84. }
  85. }
  86. }
  87. return clazz;
  88. }
  89. @SuppressWarnings("unchecked")
  90. public Object buildBean(Class clazz, Map extraContext) {
  91. if (injector == null) {
  92. synchronized (this) {
  93. if (injector == null) {
  94. createInjector();
  95. }
  96. }
  97. }
  98. return injector.getInstance(clazz);
  99. }
  100. private void createInjector() {
  101. try {
  102. logger.info("Creating injector...");
  103. this.injector = Guice.createInjector(new AbstractModule() {
  104. protected void configure() {
  105. // Install default servlet bindings.
  106. install(new ServletModule());
  107. // Install user's module.
  108. if (module != null) {
  109. logger.info("Installing " + module + "...");
  110. install(module);
  111. }
  112. else {
  113. logger.info("No module found. Set 'guice.module' to a Module "
  114. + "class name if you'd like to use one.");
  115. }
  116. // Tell the injector about all the action classes, etc., so it
  117. // can validate them at startup.
  118. for (Class<?> boundClass : boundClasses) {
  119. // TODO: Set source from Struts XML.
  120. bind(boundClass);
  121. }
  122. // Validate the interceptor class.
  123. for (ProvidedInterceptor interceptor : interceptors) {
  124. interceptor.validate(binder());
  125. }
  126. }
  127. });
  128. // Inject interceptors.
  129. for (ProvidedInterceptor interceptor : interceptors) {
  130. interceptor.inject();
  131. }
  132. } catch (Throwable t) {
  133. t.printStackTrace();
  134. System.exit(1);
  135. }
  136. logger.info("Injector created successfully.");
  137. }
  138. @SuppressWarnings("unchecked")
  139. public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
  140. Map interceptorRefParams) throws ConfigurationException {
  141. // Ensure the interceptor class is present.
  142. Class<? extends Interceptor> interceptorClass;
  143. try {
  144. interceptorClass = getClassInstance(interceptorConfig.getClassName());
  145. } catch (ClassNotFoundException e) {
  146. throw new RuntimeException(e);
  147. }
  148. ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
  149. interceptorConfig, interceptorRefParams, interceptorClass);
  150. interceptors.add(providedInterceptor);
  151. return providedInterceptor;
  152. }
  153. Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
  154. Map interceptorRefParams) throws ConfigurationException {
  155. return super.buildInterceptor(interceptorConfig, interceptorRefParams);
  156. }
  157. class ProvidedInterceptor implements Interceptor {
  158. final InterceptorConfig config;
  159. final Map params;
  160. final Class<? extends Interceptor> interceptorClass;
  161. Interceptor delegate;
  162. ProvidedInterceptor(InterceptorConfig config, Map params,
  163. Class<? extends Interceptor> interceptorClass) {
  164. this.config = config;
  165. this.params = params;
  166. this.interceptorClass = interceptorClass;
  167. }
  168. void validate(Binder binder) {
  169. // TODO: Set source from Struts XML.
  170. if (hasScope(interceptorClass)) {
  171. binder.addError("Scoping interceptors is not currently supported."
  172. + " Please remove the scope annotation from "
  173. + interceptorClass.getName() + ".");
  174. }
  175. // Make sure it implements Interceptor.
  176. if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
  177. binder.addError(interceptorClass.getName() + " must implement "
  178. + Interceptor.class.getName() + ".");
  179. }
  180. }
  181. void inject() {
  182. delegate = superBuildInterceptor(config, params);
  183. }
  184. public void destroy() {
  185. delegate.destroy();
  186. }
  187. public void init() {
  188. throw new AssertionError();
  189. }
  190. public String intercept(ActionInvocation invocation) throws Exception {
  191. return delegate.intercept(invocation);
  192. }
  193. }
  194. /**
  195. * Returns true if the given class has a scope annotation.
  196. */
  197. private static boolean hasScope(
  198. Class<? extends Interceptor> interceptorClass) {
  199. for (Annotation annotation : interceptorClass.getAnnotations()) {
  200. if (annotation.annotationType()
  201. .isAnnotationPresent(ScopeAnnotation.class)) {
  202. return true;
  203. }
  204. }
  205. return false;
  206. }
  207. }