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.dispatcher;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.concurrent.CopyOnWriteArrayList;
35
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletException;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40
41 import org.apache.struts2.ServletActionContext;
42 import org.apache.struts2.StrutsConstants;
43 import org.apache.struts2.StrutsStatics;
44 import org.apache.struts2.config.BeanSelectionProvider;
45 import org.apache.struts2.config.DefaultPropertiesProvider;
46 import org.apache.struts2.config.LegacyPropertiesConfigurationProvider;
47 import org.apache.struts2.config.StrutsXmlConfigurationProvider;
48 import org.apache.struts2.dispatcher.mapper.ActionMapping;
49 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
50 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
51 import org.apache.struts2.util.AttributeMap;
52 import org.apache.struts2.util.ClassLoaderUtils;
53 import org.apache.struts2.util.ObjectFactoryDestroyable;
54 import org.apache.struts2.views.freemarker.FreemarkerManager;
55
56 import com.opensymphony.xwork2.ActionContext;
57 import com.opensymphony.xwork2.ActionProxy;
58 import com.opensymphony.xwork2.ActionProxyFactory;
59 import com.opensymphony.xwork2.ObjectFactory;
60 import com.opensymphony.xwork2.Result;
61 import com.opensymphony.xwork2.config.Configuration;
62 import com.opensymphony.xwork2.config.ConfigurationException;
63 import com.opensymphony.xwork2.config.ConfigurationManager;
64 import com.opensymphony.xwork2.config.ConfigurationProvider;
65 import com.opensymphony.xwork2.config.entities.InterceptorMapping;
66 import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
67 import com.opensymphony.xwork2.config.entities.PackageConfig;
68 import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
69 import com.opensymphony.xwork2.inject.Container;
70 import com.opensymphony.xwork2.inject.ContainerBuilder;
71 import com.opensymphony.xwork2.inject.Inject;
72 import com.opensymphony.xwork2.interceptor.Interceptor;
73 import com.opensymphony.xwork2.util.FileManager;
74 import com.opensymphony.xwork2.util.LocalizedTextUtil;
75 import com.opensymphony.xwork2.util.ValueStack;
76 import com.opensymphony.xwork2.util.ValueStackFactory;
77 import com.opensymphony.xwork2.util.location.LocatableProperties;
78 import com.opensymphony.xwork2.util.location.Location;
79 import com.opensymphony.xwork2.util.location.LocationUtils;
80 import com.opensymphony.xwork2.util.logging.Logger;
81 import com.opensymphony.xwork2.util.logging.LoggerFactory;
82 import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
83
84 import freemarker.template.Template;
85
86 /***
87 * A utility class the actual dispatcher delegates most of its tasks to. Each instance
88 * of the primary dispatcher holds an instance of this dispatcher to be shared for
89 * all requests.
90 *
91 * @see org.apache.struts2.dispatcher.FilterDispatcher
92 */
93 public class Dispatcher {
94
95 /***
96 * Provide a logging instance.
97 */
98 private static final Logger LOG = LoggerFactory.getLogger(Dispatcher.class);
99
100 /***
101 * Provide a thread local instance.
102 */
103 private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();
104
105 /***
106 * Store list of DispatcherListeners.
107 */
108 private static List<DispatcherListener> dispatcherListeners =
109 new CopyOnWriteArrayList<DispatcherListener>();
110
111 /***
112 * Store ConfigurationManager instance, set on init.
113 */
114 private ConfigurationManager configurationManager;
115
116 /***
117 * Store state of StrutsConstants.STRUTS_DEVMODE setting.
118 */
119 private boolean devMode;
120
121 /***
122 * Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
123 */
124 private String defaultEncoding;
125
126 /***
127 * Store state of StrutsConstants.STRUTS_LOCALE setting.
128 */
129 private String defaultLocale;
130
131 /***
132 * Store state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
133 */
134 private String multipartSaveDir;
135
136 /***
137 * Provide list of default configuration files.
138 */
139 private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
140
141 /***
142 * Store state of STRUTS_DISPATCHER_PARAMETERSWORKAROUND.
143 * <p/>
144 * The workaround is for WebLogic.
145 * We try to autodect WebLogic on Dispatcher init.
146 * The workaround can also be enabled manually.
147 */
148 private boolean paramsWorkaroundEnabled = false;
149
150 /***
151 * Provide the dispatcher instance for the current thread.
152 *
153 * @return The dispatcher instance
154 */
155 public static Dispatcher getInstance() {
156 return instance.get();
157 }
158
159 /***
160 * Store the dispatcher instance for this thread.
161 *
162 * @param instance The instance
163 */
164 public static void setInstance(Dispatcher instance) {
165 Dispatcher.instance.set(instance);
166 }
167
168 /***
169 * Add a dispatcher lifecycle listener.
170 *
171 * @param listener The listener to add
172 */
173 public static void addDispatcherListener(DispatcherListener listener) {
174 dispatcherListeners.add(listener);
175 }
176
177 /***
178 * Remove a specific dispatcher lifecycle listener.
179 *
180 * @param listener The listener
181 */
182 public static void removeDispatcherListener(DispatcherListener listener) {
183 dispatcherListeners.remove(listener);
184 }
185
186 private ServletContext servletContext;
187 private Map<String, String> initParams;
188
189 private ValueStackFactory valueStackFactory;
190
191
192 /***
193 * Create the Dispatcher instance for a given ServletContext and set of initialization parameters.
194 *
195 * @param servletContext Our servlet context
196 * @param initParams The set of initialization parameters
197 */
198 public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
199 this.servletContext = servletContext;
200 this.initParams = initParams;
201 }
202
203 /***
204 * Modify state of StrutsConstants.STRUTS_DEVMODE setting.
205 * @param mode New setting
206 */
207 @Inject(StrutsConstants.STRUTS_DEVMODE)
208 public void setDevMode(String mode) {
209 devMode = "true".equals(mode);
210 }
211
212 /***
213 * Modify state of StrutsConstants.STRUTS_LOCALE setting.
214 * @param val New setting
215 */
216 @Inject(value=StrutsConstants.STRUTS_LOCALE, required=false)
217 public void setDefaultLocale(String val) {
218 defaultLocale = val;
219 }
220
221 /***
222 * Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
223 * @param val New setting
224 */
225 @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
226 public void setDefaultEncoding(String val) {
227 defaultEncoding = val;
228 }
229
230 /***
231 * Modify state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
232 * @param val New setting
233 */
234 @Inject(StrutsConstants.STRUTS_MULTIPART_SAVEDIR)
235 public void setMultipartSaveDir(String val) {
236 multipartSaveDir = val;
237 }
238
239 @Inject
240 public void setValueStackFactory(ValueStackFactory valueStackFactory) {
241 this.valueStackFactory = valueStackFactory;
242 }
243
244 /***
245 * Releases all instances bound to this dispatcher instance.
246 */
247 public void cleanup() {
248
249
250 ObjectFactory objectFactory = getContainer().getInstance(ObjectFactory.class);
251 if (objectFactory == null) {
252 LOG.warn("Object Factory is null, something is seriously wrong, no clean up will be performed");
253 }
254 if (objectFactory instanceof ObjectFactoryDestroyable) {
255 try {
256 ((ObjectFactoryDestroyable)objectFactory).destroy();
257 }
258 catch(Exception e) {
259
260 LOG.error("exception occurred while destroying ObjectFactory ["+objectFactory+"]", e);
261 }
262 }
263
264
265 instance.set(null);
266
267
268 if (!dispatcherListeners.isEmpty()) {
269 for (DispatcherListener l : dispatcherListeners) {
270 l.dispatcherDestroyed(this);
271 }
272 }
273
274
275 Set<Interceptor> interceptors = new HashSet<Interceptor>();
276 Collection<PackageConfig> packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
277 for (PackageConfig packageConfig : packageConfigs) {
278 for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
279 if (config instanceof InterceptorStackConfig) {
280 for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
281 interceptors.add(interceptorMapping.getInterceptor());
282 }
283 }
284 }
285 }
286 for (Interceptor interceptor : interceptors) {
287 interceptor.destroy();
288 }
289
290
291 configurationManager.destroyConfiguration();
292 configurationManager = null;
293 }
294
295 private void init_DefaultProperties() {
296 configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
297 }
298
299 private void init_LegacyStrutsProperties() {
300 configurationManager.addConfigurationProvider(new LegacyPropertiesConfigurationProvider());
301 }
302
303 private void init_TraditionalXmlConfigurations() {
304 String configPaths = initParams.get("config");
305 if (configPaths == null) {
306 configPaths = DEFAULT_CONFIGURATION_PATHS;
307 }
308 String[] files = configPaths.split("//s*[,]//s*");
309 for (String file : files) {
310 if (file.endsWith(".xml")) {
311 if ("xwork.xml".equals(file)) {
312 configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
313 } else {
314 configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
315 }
316 } else {
317 throw new IllegalArgumentException("Invalid configuration file name");
318 }
319 }
320 }
321
322 private void init_CustomConfigurationProviders() {
323 String configProvs = initParams.get("configProviders");
324 if (configProvs != null) {
325 String[] classes = configProvs.split("//s*[,]//s*");
326 for (String cname : classes) {
327 try {
328 Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
329 ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();
330 configurationManager.addConfigurationProvider(prov);
331 } catch (InstantiationException e) {
332 throw new ConfigurationException("Unable to instantiate provider: "+cname, e);
333 } catch (IllegalAccessException e) {
334 throw new ConfigurationException("Unable to access provider: "+cname, e);
335 } catch (ClassNotFoundException e) {
336 throw new ConfigurationException("Unable to locate provider class: "+cname, e);
337 }
338 }
339 }
340 }
341
342 private void init_FilterInitParameters() {
343 configurationManager.addConfigurationProvider(new ConfigurationProvider() {
344 public void destroy() {}
345 public void init(Configuration configuration) throws ConfigurationException {}
346 public void loadPackages() throws ConfigurationException {}
347 public boolean needsReload() { return false; }
348
349 public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
350 props.putAll(initParams);
351 }
352 });
353 }
354
355 private void init_AliasStandardObjects() {
356 configurationManager.addConfigurationProvider(new BeanSelectionProvider());
357 }
358
359 private Container init_PreloadConfiguration() {
360 Configuration config = configurationManager.getConfiguration();
361 Container container = config.getContainer();
362
363 boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
364 LocalizedTextUtil.setReloadBundles(reloadi18n);
365
366 return container;
367 }
368
369 private void init_CheckConfigurationReloading(Container container) {
370 FileManager.setReloadingConfigs("true".equals(container.getInstance(String.class,
371 StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD)));
372 }
373
374 private void init_CheckWebLogicWorkaround(Container container) {
375
376 if (servletContext != null && servletContext.getServerInfo() != null
377 && servletContext.getServerInfo().indexOf("WebLogic") >= 0) {
378 LOG.info("WebLogic server detected. Enabling Struts parameter access work-around.");
379 paramsWorkaroundEnabled = true;
380 } else {
381 paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class,
382 StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND));
383 }
384 }
385
386 /***
387 * Load configurations, including both XML and zero-configuration strategies,
388 * and update optional settings, including whether to reload configurations and resource files.
389 */
390 public void init() {
391
392 if (configurationManager == null) {
393 configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
394 }
395
396 init_DefaultProperties();
397 init_TraditionalXmlConfigurations();
398 init_LegacyStrutsProperties();
399 init_CustomConfigurationProviders();
400 init_FilterInitParameters() ;
401 init_AliasStandardObjects() ;
402
403 Container container = init_PreloadConfiguration();
404 container.inject(this);
405 init_CheckConfigurationReloading(container);
406 init_CheckWebLogicWorkaround(container);
407
408 if (!dispatcherListeners.isEmpty()) {
409 for (DispatcherListener l : dispatcherListeners) {
410 l.dispatcherInitialized(this);
411 }
412 }
413 }
414
415 /***
416 * Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.
417 * <p/>
418 * This method first creates the action context from the given parameters,
419 * and then loads an <tt>ActionProxy</tt> from the given action name and namespace.
420 * After that, the Action method is executed and output channels through the response object.
421 * Actions not found are sent back to the user via the {@link Dispatcher#sendError} method,
422 * using the 404 return code.
423 * All other errors are reported by throwing a ServletException.
424 *
425 * @param request the HttpServletRequest object
426 * @param response the HttpServletResponse object
427 * @param mapping the action mapping object
428 * @throws ServletException when an unknown error occurs (not a 404, but typically something that
429 * would end up as a 5xx by the servlet container)
430 * @param context Our ServletContext object
431 */
432 public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
433 ActionMapping mapping) throws ServletException {
434
435 Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
436
437
438 ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
439 boolean nullStack = stack == null;
440 if (nullStack) {
441 ActionContext ctx = ActionContext.getContext();
442 if (ctx != null) {
443 stack = ctx.getValueStack();
444 }
445 }
446 if (stack != null) {
447 extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
448 }
449
450 String timerKey = "Handling request from Dispatcher";
451 try {
452 UtilTimerStack.push(timerKey);
453 String namespace = mapping.getNamespace();
454 String name = mapping.getName();
455 String method = mapping.getMethod();
456
457 Configuration config = configurationManager.getConfiguration();
458 ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
459 namespace, name, method, extraContext, true, false);
460
461 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
462
463
464 if (mapping.getResult() != null) {
465 Result result = mapping.getResult();
466 result.execute(proxy.getInvocation());
467 } else {
468 proxy.execute();
469 }
470
471
472 if (!nullStack) {
473 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
474 }
475 } catch (ConfigurationException e) {
476
477 if(devMode) {
478 LOG.error("Could not find action or result", e);
479 }
480 else {
481 LOG.warn("Could not find action or result", e);
482 }
483 sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
484 } catch (Exception e) {
485 sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
486 } finally {
487 UtilTimerStack.pop(timerKey);
488 }
489 }
490
491 /***
492 * Create a context map containing all the wrapped request objects
493 *
494 * @param request The servlet request
495 * @param response The servlet response
496 * @param mapping The action mapping
497 * @param context The servlet context
498 * @return A map of context objects
499 */
500 public Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
501 ActionMapping mapping, ServletContext context) {
502
503
504 Map requestMap = new RequestMap(request);
505
506
507 Map params = new HashMap(request.getParameterMap());
508
509
510 Map session = new SessionMap(request);
511
512
513 Map application = new ApplicationMap(context);
514
515 Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
516
517 if (mapping != null) {
518 extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
519 }
520 return extraContext;
521 }
522
523 /***
524 * Merge all application and servlet attributes into a single <tt>HashMap</tt> to represent the entire
525 * <tt>Action</tt> context.
526 *
527 * @param requestMap a Map of all request attributes.
528 * @param parameterMap a Map of all request parameters.
529 * @param sessionMap a Map of all session attributes.
530 * @param applicationMap a Map of all servlet context attributes.
531 * @param request the HttpServletRequest object.
532 * @param response the HttpServletResponse object.
533 * @param servletContext the ServletContextmapping object.
534 * @return a HashMap representing the <tt>Action</tt> context.
535 */
536 public HashMap<String,Object> createContextMap(Map requestMap,
537 Map parameterMap,
538 Map sessionMap,
539 Map applicationMap,
540 HttpServletRequest request,
541 HttpServletResponse response,
542 ServletContext servletContext) {
543 HashMap<String,Object> extraContext = new HashMap<String,Object>();
544 extraContext.put(ActionContext.PARAMETERS, new HashMap(parameterMap));
545 extraContext.put(ActionContext.SESSION, sessionMap);
546 extraContext.put(ActionContext.APPLICATION, applicationMap);
547
548 Locale locale;
549 if (defaultLocale != null) {
550 locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
551 } else {
552 locale = request.getLocale();
553 }
554
555 extraContext.put(ActionContext.LOCALE, locale);
556
557
558 extraContext.put(StrutsStatics.HTTP_REQUEST, request);
559 extraContext.put(StrutsStatics.HTTP_RESPONSE, response);
560 extraContext.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
561
562
563 extraContext.put("request", requestMap);
564 extraContext.put("session", sessionMap);
565 extraContext.put("application", applicationMap);
566 extraContext.put("parameters", parameterMap);
567
568 AttributeMap attrMap = new AttributeMap(extraContext);
569 extraContext.put("attr", attrMap);
570
571 return extraContext;
572 }
573
574 /***
575 * Return the path to save uploaded files to (this is configurable).
576 *
577 * @return the path to save uploaded files to
578 * @param servletContext Our ServletContext
579 */
580 private String getSaveDir(ServletContext servletContext) {
581 String saveDir = multipartSaveDir.trim();
582
583 if (saveDir.equals("")) {
584 File tempdir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
585 LOG.info("Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir");
586
587 if (tempdir != null) {
588 saveDir = tempdir.toString();
589 setMultipartSaveDir(saveDir);
590 }
591 } else {
592 File multipartSaveDir = new File(saveDir);
593
594 if (!multipartSaveDir.exists()) {
595 multipartSaveDir.mkdir();
596 }
597 }
598
599 if (LOG.isDebugEnabled()) {
600 LOG.debug("saveDir=" + saveDir);
601 }
602
603 return saveDir;
604 }
605
606 /***
607 * Prepare a request, including setting the encoding and locale.
608 *
609 * @param request The request
610 * @param response The response
611 */
612 public void prepare(HttpServletRequest request, HttpServletResponse response) {
613 String encoding = null;
614 if (defaultEncoding != null) {
615 encoding = defaultEncoding;
616 }
617
618 Locale locale = null;
619 if (defaultLocale != null) {
620 locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
621 }
622
623 if (encoding != null) {
624 try {
625 request.setCharacterEncoding(encoding);
626 } catch (Exception e) {
627 LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
628 }
629 }
630
631 if (locale != null) {
632 response.setLocale(locale);
633 }
634
635 if (paramsWorkaroundEnabled) {
636 request.getParameter("foo");
637 }
638 }
639
640 /***
641 * Wrap and return the given request or return the original request object.
642 * </p>
643 * This method transparently handles multipart data as a wrapped class around the given request.
644 * Override this method to handle multipart requests in a special way or to handle other types of requests.
645 * Note, {@link org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper} is
646 * flexible - look first to that object before overriding this method to handle multipart data.
647 *
648 * @param request the HttpServletRequest object.
649 * @param servletContext Our ServletContext object
650 * @return a wrapped request or original request.
651 * @see org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper
652 * @throws java.io.IOException on any error.
653 */
654 public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
655
656 if (request instanceof StrutsRequestWrapper) {
657 return request;
658 }
659
660 String content_type = request.getContentType();
661 if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
662 MultiPartRequest multi = getContainer().getInstance(MultiPartRequest.class);
663 request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));
664 } else {
665 request = new StrutsRequestWrapper(request);
666 }
667
668 return request;
669 }
670
671 /***
672 * Send an HTTP error response code.
673 *
674 * @param request the HttpServletRequest object.
675 * @param response the HttpServletResponse object.
676 * @param code the HttpServletResponse error code (see {@link javax.servlet.http.HttpServletResponse} for possible error codes).
677 * @param e the Exception that is reported.
678 * @param ctx the ServletContext object.
679 */
680 public void sendError(HttpServletRequest request, HttpServletResponse response,
681 ServletContext ctx, int code, Exception e) {
682 if (devMode) {
683 response.setContentType("text/html");
684
685 try {
686 FreemarkerManager mgr = getContainer().getInstance(FreemarkerManager.class);
687
688 freemarker.template.Configuration config = mgr.getConfiguration(ctx);
689 Template template = config.getTemplate("/org/apache/struts2/dispatcher/error.ftl");
690
691 List<Throwable> chain = new ArrayList<Throwable>();
692 Throwable cur = e;
693 chain.add(cur);
694 while ((cur = cur.getCause()) != null) {
695 chain.add(cur);
696 }
697
698 HashMap<String,Object> data = new HashMap<String,Object>();
699 data.put("exception", e);
700 data.put("unknown", Location.UNKNOWN);
701 data.put("chain", chain);
702 data.put("locator", new Locator());
703 template.process(data, response.getWriter());
704 response.getWriter().close();
705 } catch (Exception exp) {
706 try {
707 response.sendError(code, "Unable to show problem report: " + exp);
708 } catch (IOException ex) {
709
710 }
711 }
712 } else {
713 try {
714
715 if (code == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
716
717
718 request.setAttribute("javax.servlet.error.exception", e);
719
720
721 request.setAttribute("javax.servlet.jsp.jspException", e);
722 }
723
724
725 response.sendError(code, e.getMessage());
726 } catch (IOException e1) {
727
728 }
729 }
730 }
731
732
733
734 /***
735 * Provide an accessor class for static XWork utility.
736 */
737 public static class Locator {
738 public Location getLocation(Object obj) {
739 Location loc = LocationUtils.getLocation(obj);
740 if (loc == null) {
741 return Location.UNKNOWN;
742 }
743 return loc;
744 }
745 }
746
747 /***
748 * Expose the ConfigurationManager instance.
749 *
750 * @return The instance
751 */
752 public ConfigurationManager getConfigurationManager() {
753 return configurationManager;
754 }
755
756 /***
757 * Modify the ConfigurationManager instance
758 *
759 * @param mgr The configuration manager
760 */
761 public void setConfigurationManager(ConfigurationManager mgr) {
762 this.configurationManager = mgr;
763 }
764
765 /***
766 * Expose the dependency injection container.
767 * @return Our dependency injection container
768 */
769 public Container getContainer() {
770 ConfigurationManager mgr = getConfigurationManager();
771 if (mgr == null) {
772 throw new IllegalStateException("The configuration manager shouldn't be null");
773 } else {
774 Configuration config = mgr.getConfiguration();
775 if (config == null) {
776 throw new IllegalStateException("Unable to load configuration");
777 } else {
778 return config.getContainer();
779 }
780 }
781 }
782 }