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