1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.plexus;
23
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.servlet.ServletContext;
28
29 import org.codehaus.plexus.PlexusContainer;
30
31 import com.opensymphony.xwork2.Action;
32 import com.opensymphony.xwork2.ObjectFactory;
33 import com.opensymphony.xwork2.Result;
34 import com.opensymphony.xwork2.config.ConfigurationException;
35 import com.opensymphony.xwork2.config.entities.ActionConfig;
36 import com.opensymphony.xwork2.config.entities.InterceptorConfig;
37 import com.opensymphony.xwork2.config.entities.ResultConfig;
38 import com.opensymphony.xwork2.inject.Inject;
39 import com.opensymphony.xwork2.interceptor.Interceptor;
40 import com.opensymphony.xwork2.util.logging.Logger;
41 import com.opensymphony.xwork2.util.logging.LoggerFactory;
42 import com.opensymphony.xwork2.validator.Validator;
43
44 /***
45 * Plexus integartion. You need three optional files: plexus-request.xml, plexus-session.xml, and
46 * plexus-application.xml.
47 * <p/>
48 * The syntax of these files is:
49 * <p/>
50 * <pre>
51 * <plexus>
52 * <components>
53 * <component>
54 * <role>com.acme.MyBean</role>
55 * <implementation>com.acme.MyBean|com.acme.MyBeanImpl</implementation>
56 * <componentComposer>field|setter|?</componentComposer>
57 * <requirements>
58 * <requirement>
59 * <role>com.acme.MyOtherBean</role>
60 * </requirement>
61 * </requirements>
62 * <configuration>
63 * <foo>123</foo>
64 * <bar>hello, world</bar>
65 * </configuration>
66 * </component>
67 * </components>
68 * </plexus>
69 * </pre>
70 *
71 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
72 */
73 public class PlexusObjectFactory extends ObjectFactory {
74 private static final Logger LOG = LoggerFactory.getLogger(PlexusObjectFactory.class);
75
76 private static final String PLEXUS_COMPONENT_TYPE = "plexus.component.type";
77
78 private PlexusContainer base;
79
80
81
82 @Inject
83 public void setServletConfig(ServletContext servletContext) {
84 if (!PlexusLifecycleListener.isLoaded() || !PlexusFilter.isLoaded()) {
85
86 String message = "********** FATAL ERROR STARTING UP PLEXUS-STRUTS INTEGRATION **********\n" +
87 "Looks like the Plexus listener was not configured for your web app! \n" +
88 "You need to add the following to web.xml: \n" +
89 "\n" +
90 " <!-- this should be before the Struts filter -->\n" +
91 " <filter>\n" +
92 " <filter-name>plexus</filter-name>\n" +
93 " <filter-class>org.apache.struts2.plexus.PlexusFilter</filter-class>\n" +
94 " </filter>\n" +
95 "\n" +
96 "...\n" +
97 "\n" +
98 " <!-- this should be before the Struts filter -->\n" +
99 " <filter-mapping>\n" +
100 " <filter-name>plexus</filter-name>\n" +
101 " <url-pattern>/*</url-pattern>\n" +
102 " </filter-mapping>\n" +
103 "\n" +
104 "...\n" +
105 "\n" +
106 " <listener>\n" +
107 " <listener-class>org.apache.struts2.plexus.PlexusLifecycleListener</listener-class>\n" +
108 " </listener>";
109 LOG.fatal(message);
110 return;
111 }
112
113 base = (PlexusContainer) servletContext.getAttribute(PlexusLifecycleListener.KEY);
114 }
115
116
117
118
119 public Object buildAction(String actionName, String namespace, ActionConfig config, Map extraContext)
120 throws Exception {
121 if (extraContext == null) {
122 extraContext = new HashMap();
123 }
124
125 extraContext.put(PLEXUS_COMPONENT_TYPE, Action.class.getName());
126
127 return super.buildAction(actionName, namespace, config, extraContext);
128 }
129
130
131
132
133 public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams)
134 throws ConfigurationException {
135 String interceptorClassName = interceptorConfig.getClassName();
136 Map thisInterceptorClassParams = interceptorConfig.getParams();
137 Map params = (thisInterceptorClassParams == null) ? new HashMap() : new HashMap(thisInterceptorClassParams);
138 params.putAll(interceptorRefParams);
139
140 String message;
141 Throwable cause;
142
143 try {
144 Map extraContext = new HashMap();
145 extraContext.put(PLEXUS_COMPONENT_TYPE, Interceptor.class.getName());
146 Interceptor interceptor = (Interceptor) buildBean(interceptorClassName, extraContext);
147 reflectionProvider.setProperties(params, interceptor);
148 interceptor.init();
149
150 return interceptor;
151 }
152 catch (InstantiationException e) {
153 cause = e;
154 message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
155 }
156 catch (IllegalAccessException e) {
157 cause = e;
158 message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
159 }
160 catch (ClassCastException e) {
161 cause = e;
162 message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor";
163 }
164 catch (Exception e) {
165 cause = e;
166 message = "Caught Exception while registering Interceptor class " + interceptorClassName;
167 }
168 catch (NoClassDefFoundError e) {
169 cause = e;
170 message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?";
171 }
172
173 throw new ConfigurationException(message, cause);
174 }
175
176
177
178
179 public Result buildResult(ResultConfig resultConfig, Map extraContext)
180 throws Exception {
181 if (extraContext == null) {
182 extraContext = new HashMap();
183 }
184
185 extraContext.put(PLEXUS_COMPONENT_TYPE, Result.class.getName());
186
187 return super.buildResult(resultConfig, extraContext);
188 }
189
190
191
192
193 public Validator buildValidator(String className, Map params, Map extraContext)
194 throws Exception {
195 Map context = new HashMap();
196 context.put(PLEXUS_COMPONENT_TYPE, Validator.class.getName());
197 Validator validator = (Validator) buildBean(className, context);
198 reflectionProvider.setProperties(params, validator);
199
200 return validator;
201 }
202
203
204
205
206 public Object buildBean(Class clazz, Map extraContext)
207 throws Exception {
208 try {
209 return lookup(clazz.getName(), extraContext);
210 }
211 catch (Exception e) {
212 if (extraContext != null) {
213 String type = (String) extraContext.get(PLEXUS_COMPONENT_TYPE);
214
215 if (type != null) {
216 return lookup(type, clazz.getName(), extraContext);
217 }
218 }
219
220 throw e;
221 }
222 }
223
224
225
226
227 public Class getClassInstance(String className)
228 throws ClassNotFoundException {
229 PlexusContainer pc = PlexusThreadLocal.getPlexusContainer();
230
231 if (pc == null) {
232 pc = base;
233 }
234
235 try {
236 return pc.lookup(className).getClass();
237 }
238 catch (Exception e1) {
239 try {
240 return pc.lookup(Action.class.getName(), className).getClass();
241 }
242 catch (Exception e2) {
243 try {
244 return pc.lookup(Interceptor.class.getName(), className).getClass();
245 }
246 catch (Exception e3) {
247 try {
248 return pc.lookup(Validator.class.getName(), className).getClass();
249 }
250 catch (Exception e4) {
251 try {
252 return pc.lookup(Result.class.getName(), className).getClass();
253 }
254 catch (Exception e5) {
255 return super.getClassInstance(className);
256 }
257 }
258 }
259 }
260 }
261 }
262
263 /***
264 * Looks up an object
265 *
266 * @param role The role name
267 * @param extraContext The extra context
268 * @return The object
269 * @throws Exception If the lookup fails
270 */
271 private Object lookup(String role, Map extraContext)
272 throws Exception {
273 return lookup(role, null, extraContext);
274 }
275
276 /***
277 * Looks up an object
278 *
279 * @param role The role name
280 * @param roleHint The role hint
281 * @param extraContext The extra context
282 * @return The object
283 * @throws Exception If the lookup fails
284 */
285 private Object lookup(String role, String roleHint, Map extraContext)
286 throws Exception {
287 PlexusContainer pc = PlexusThreadLocal.getPlexusContainer();
288
289 if (pc == null) {
290 pc = base;
291 }
292
293 try {
294 return pc.lookup(role, roleHint);
295 }
296 catch (Exception e) {
297 LOG.debug("Can't load component (" + role + "/" + roleHint + ") with plexus, try now with struts.", e);
298 Object o = super.buildBean(super.getClassInstance(role), extraContext);
299 pc.autowire(o);
300 return o;
301 }
302 }
303 }