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