PageRenderTime 83ms CodeModel.GetById 55ms RepoModel.GetById 1ms app.codeStats 0ms

/extensions/struts2/src/com/google/inject/struts2/Struts2Factory.java

https://gitlab.com/metamorphiccode/guice
Java | 231 lines | 153 code | 37 blank | 41 comment | 18 complexity | 577cc8a5c5e605f0ac617a781008b4ea MD5 | raw file
  1. /**
  2. * Copyright (C) 2009 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.Injector;
  20. import com.google.inject.internal.Annotations;
  21. import com.opensymphony.xwork2.ActionInvocation;
  22. import com.opensymphony.xwork2.ObjectFactory;
  23. import com.opensymphony.xwork2.config.ConfigurationException;
  24. import com.opensymphony.xwork2.config.entities.InterceptorConfig;
  25. import com.opensymphony.xwork2.inject.Inject;
  26. import com.opensymphony.xwork2.interceptor.Interceptor;
  27. import java.lang.annotation.Annotation;
  28. import java.util.ArrayList;
  29. import java.util.HashSet;
  30. import java.util.List;
  31. import java.util.Map;
  32. import java.util.Set;
  33. import java.util.logging.Logger;
  34. /**
  35. * Cleanup up version from Bob's GuiceObjectFactory. Now works properly with
  36. * GS2 and fixes several bugs.
  37. *
  38. * @author dhanji@gmail.com
  39. * @author benmccann.com
  40. */
  41. public class Struts2Factory extends ObjectFactory {
  42. private static final long serialVersionUID = 1L;
  43. private static final Logger logger = Logger.getLogger(Struts2Factory.class.getName());
  44. private static final String ERROR_NO_INJECTOR =
  45. "Cannot find a Guice injector. Are you sure you registered a GuiceServletContextListener "
  46. + "that uses the Struts2GuicePluginModule in your application's web.xml?";
  47. private static @com.google.inject.Inject Injector injector;
  48. private final List<ProvidedInterceptor> interceptors = new ArrayList<ProvidedInterceptor>();
  49. private volatile Injector strutsInjector;
  50. @Override
  51. public boolean isNoArgConstructorRequired() {
  52. return false;
  53. }
  54. @Inject(value = "guice.module", required = false)
  55. void setModule(String moduleClassName) {
  56. throw new RuntimeException("The struts2 plugin no longer supports"
  57. + " specifying a module via the 'guice.module' property in XML."
  58. + " Please install your module via a GuiceServletContextListener instead.");
  59. }
  60. Set<Class<?>> boundClasses = new HashSet<Class<?>>();
  61. public Class<?> getClassInstance(String name) throws ClassNotFoundException {
  62. Class<?> clazz = super.getClassInstance(name);
  63. synchronized (this) {
  64. if (strutsInjector == null) {
  65. // We can only bind each class once.
  66. if (!boundClasses.contains(clazz)) {
  67. try {
  68. // Calling these methods now helps us detect ClassNotFoundErrors
  69. // early.
  70. clazz.getDeclaredFields();
  71. clazz.getDeclaredMethods();
  72. boundClasses.add(clazz);
  73. } catch (Throwable t) {
  74. // Struts should still work even though some classes aren't in the
  75. // classpath. It appears we always get the exception here when
  76. // this is the case.
  77. return clazz;
  78. }
  79. }
  80. }
  81. }
  82. return clazz;
  83. }
  84. @Override @SuppressWarnings("unchecked")
  85. public Object buildBean(Class clazz, Map<String, Object> extraContext) {
  86. if (strutsInjector == null) {
  87. synchronized (this) {
  88. if (strutsInjector == null) {
  89. createInjector();
  90. }
  91. }
  92. }
  93. return strutsInjector.getInstance(clazz);
  94. }
  95. private void createInjector() {
  96. logger.info("Loading struts2 Guice support...");
  97. // Something is wrong, since this should be there if GuiceServletContextListener
  98. // was present.
  99. if (injector == null) {
  100. logger.severe(ERROR_NO_INJECTOR);
  101. throw new RuntimeException(ERROR_NO_INJECTOR);
  102. }
  103. this.strutsInjector = injector.createChildInjector(new AbstractModule() {
  104. protected void configure() {
  105. // Tell the injector about all the action classes, etc., so it
  106. // can validate them at startup.
  107. for (Class<?> boundClass : boundClasses) {
  108. // TODO: Set source from Struts XML.
  109. bind(boundClass);
  110. }
  111. // Validate the interceptor class.
  112. for (ProvidedInterceptor interceptor : interceptors) {
  113. interceptor.validate(binder());
  114. }
  115. }
  116. });
  117. // Inject interceptors.
  118. for (ProvidedInterceptor interceptor : interceptors) {
  119. interceptor.inject();
  120. }
  121. logger.info("Injector created successfully.");
  122. }
  123. @SuppressWarnings("unchecked")
  124. public Interceptor buildInterceptor(InterceptorConfig interceptorConfig,
  125. Map interceptorRefParams) throws ConfigurationException {
  126. // Ensure the interceptor class is present.
  127. Class<? extends Interceptor> interceptorClass;
  128. try {
  129. interceptorClass = (Class<? extends Interceptor>)
  130. getClassInstance(interceptorConfig.getClassName());
  131. } catch (ClassNotFoundException e) {
  132. throw new RuntimeException(e);
  133. }
  134. ProvidedInterceptor providedInterceptor = new ProvidedInterceptor(
  135. interceptorConfig, interceptorRefParams, interceptorClass);
  136. interceptors.add(providedInterceptor);
  137. return providedInterceptor;
  138. }
  139. private Interceptor superBuildInterceptor(InterceptorConfig interceptorConfig,
  140. Map<String, String> interceptorRefParams) throws ConfigurationException {
  141. return super.buildInterceptor(interceptorConfig, interceptorRefParams);
  142. }
  143. private class ProvidedInterceptor implements Interceptor {
  144. private static final long serialVersionUID = 1L;
  145. private final InterceptorConfig config;
  146. private final Map<String, String> params;
  147. private final Class<? extends Interceptor> interceptorClass;
  148. private Interceptor delegate;
  149. ProvidedInterceptor(InterceptorConfig config, Map<String, String> params,
  150. Class<? extends Interceptor> interceptorClass) {
  151. this.config = config;
  152. this.params = params;
  153. this.interceptorClass = interceptorClass;
  154. }
  155. void validate(Binder binder) {
  156. // TODO: Set source from Struts XML.
  157. if (hasScope(interceptorClass)) {
  158. binder.addError("Scoping interceptors is not currently supported."
  159. + " Please remove the scope annotation from "
  160. + interceptorClass.getName() + ".");
  161. }
  162. // Make sure it implements Interceptor.
  163. if (!Interceptor.class.isAssignableFrom(interceptorClass)) {
  164. binder.addError(interceptorClass.getName() + " must implement "
  165. + Interceptor.class.getName() + ".");
  166. }
  167. }
  168. void inject() {
  169. delegate = superBuildInterceptor(config, params);
  170. }
  171. public void destroy() {
  172. if (null != delegate) {
  173. delegate.destroy();
  174. }
  175. }
  176. public void init() {
  177. throw new AssertionError();
  178. }
  179. public String intercept(ActionInvocation invocation) throws Exception {
  180. return delegate.intercept(invocation);
  181. }
  182. }
  183. /**
  184. * Returns true if the given class has a scope annotation.
  185. */
  186. private static boolean hasScope(Class<? extends Interceptor> interceptorClass) {
  187. for (Annotation annotation : interceptorClass.getAnnotations()) {
  188. if (Annotations.isScopeAnnotation(annotation.annotationType())) {
  189. return true;
  190. }
  191. }
  192. return false;
  193. }
  194. }