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