View Javadoc

1   /*
2    * $Id: Jsr168Dispatcher.java 569305 2007-08-24 09:13:29Z nilsga $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.portlet.dispatcher;
22  
23  import com.opensymphony.xwork2.ActionContext;
24  import com.opensymphony.xwork2.ActionProxy;
25  import com.opensymphony.xwork2.ActionProxyFactory;
26  import com.opensymphony.xwork2.config.ConfigurationException;
27  import com.opensymphony.xwork2.inject.Container;
28  import com.opensymphony.xwork2.util.FileManager;
29  import com.opensymphony.xwork2.util.LocalizedTextUtil;
30  import com.opensymphony.xwork2.util.TextUtils;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.struts2.StrutsConstants;
34  import org.apache.struts2.StrutsException;
35  import org.apache.struts2.StrutsStatics;
36  import org.apache.struts2.dispatcher.ApplicationMap;
37  import org.apache.struts2.dispatcher.Dispatcher;
38  import org.apache.struts2.dispatcher.RequestMap;
39  import org.apache.struts2.dispatcher.SessionMap;
40  import org.apache.struts2.dispatcher.mapper.ActionMapper;
41  import org.apache.struts2.dispatcher.mapper.ActionMapping;
42  import org.apache.struts2.portlet.PortletActionConstants;
43  import org.apache.struts2.portlet.PortletApplicationMap;
44  import org.apache.struts2.portlet.PortletRequestMap;
45  import org.apache.struts2.portlet.PortletSessionMap;
46  import org.apache.struts2.portlet.context.PortletActionContext;
47  import org.apache.struts2.portlet.servlet.PortletServletContext;
48  import org.apache.struts2.portlet.servlet.PortletServletRequest;
49  import org.apache.struts2.portlet.servlet.PortletServletResponse;
50  import org.apache.struts2.util.AttributeMap;
51  
52  import javax.portlet.*;
53  import javax.servlet.ServletContext;
54  import javax.servlet.http.HttpServletRequest;
55  import javax.servlet.http.HttpServletResponse;
56  import java.io.IOException;
57  import java.util.Enumeration;
58  import java.util.HashMap;
59  import java.util.Locale;
60  import java.util.Map;
61  
62  /***
63   * <!-- START SNIPPET: javadoc -->
64   * <p>
65   * Struts JSR-168 portlet dispatcher. Similar to the WW2 Servlet dispatcher,
66   * but adjusted to a portal environment. The portlet is configured through the <tt>portlet.xml</tt>
67   * descriptor. Examples and descriptions follow below:
68   * </p>
69   * <!-- END SNIPPET: javadoc -->
70   *
71   * @author Nils-Helge Garli
72   * @author Rainer Hermanns
73   *
74   * <p><b>Init parameters</b></p>
75   * <!-- START SNIPPET: params -->
76   * <table class="confluenceTable">
77   * <tr>
78   *  <th class="confluenceTh">Name</th>
79   * <th class="confluenceTh">Description</th>
80   * <th class="confluenceTh">Default value</th>
81   * </tr>
82   * <tr>
83   *  <td class="confluenceTd">portletNamespace</td><td class="confluenceTd">The namespace for the portlet in the xwork configuration. This
84   *      namespace is prepended to all action lookups, and makes it possible to host multiple
85   *      portlets in the same portlet application. If this parameter is set, the complete namespace
86   *      will be <tt>/portletNamespace/modeNamespace/actionName</tt></td><td class="confluenceTd">The default namespace</td>
87   * </tr>
88   * <tr>
89   *  <td class="confluenceTd">viewNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>view</tt> portlet
90   *      mode</td><td class="confluenceTd">The default namespace</td>
91   * </tr>
92   * <tr>
93   *  <td class="confluenceTd">editNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>edit</tt> portlet
94   *      mode</td><td class="confluenceTd">The default namespace</td>
95   * </tr>
96   * <tr>
97   *  <td class="confluenceTd">helpNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>help</tt> portlet
98   *      mode</td><td class="confluenceTd">The default namespace</td>
99   * </tr>
100  * <tr>
101  *  <td class="confluenceTd">defaultViewAction</td><td class="confluenceTd">Default action to invoke in the <tt>view</tt> portlet mode if no action is
102  *      specified</td><td class="confluenceTd"><tt>default</tt></td>
103  * </tr>
104  * <tr>
105  *  <td class="confluenceTd">defaultEditAction</td><td class="confluenceTd">Default action to invoke in the <tt>edit</tt> portlet mode if no action is
106  *      specified</td><td class="confluenceTd"><tt>default</tt></td>
107  * </tr>
108  * <tr>
109  *  <td class="confluenceTd">defaultHelpAction</td><td class="confluenceTd">Default action to invoke in the <tt>help</tt> portlet mode if no action is
110  *      specified</td><td class="confluenceTd"><tt>default</tt></td>
111  * </tr>
112  * </table>
113  * <!-- END SNIPPET: params -->
114  * <p><b>Example:</b></p>
115  * <pre>
116  * <!-- START SNIPPET: example -->
117  *
118  * &lt;init-param&gt;
119  *     &lt;!-- The view mode namespace. Maps to a namespace in the xwork config file --&gt;
120  *     &lt;name&gt;viewNamespace&lt;/name&gt;
121  *     &lt;value&gt;/view&lt;/value&gt;
122  * &lt;/init-param&gt;
123  * &lt;init-param&gt;
124  *    &lt;!-- The default action to invoke in view mode --&gt;
125  *    &lt;name&gt;defaultViewAction&lt;/name&gt;
126  *    &lt;value&gt;index&lt;/value&gt;
127  * &lt;/init-param&gt;
128  * &lt;init-param&gt;
129  *     &lt;!-- The view mode namespace. Maps to a namespace in the xwork config file --&gt;
130  *     &lt;name&gt;editNamespace&lt;/name&gt;
131  *     &lt;value&gt;/edit&lt;/value&gt;
132  * &lt;/init-param&gt;
133  * &lt;init-param&gt;
134  *     &lt;!-- The default action to invoke in view mode --&gt;
135  *     &lt;name&gt;defaultEditAction&lt;/name&gt;
136  *     &lt;value&gt;index&lt;/value&gt;
137  * &lt;/init-param&gt;
138  * &lt;init-param&gt;
139  *     &lt;!-- The view mode namespace. Maps to a namespace in the xwork config file --&gt;
140  *     &lt;name&gt;helpNamespace&lt;/name&gt;
141  *     &lt;value&gt;/help&lt;/value&gt;
142  * &lt;/init-param&gt;
143  * &lt;init-param&gt;
144  *     &lt;!-- The default action to invoke in view mode --&gt;
145  *     &lt;name&gt;defaultHelpAction&lt;/name&gt;
146  *     &lt;value&gt;index&lt;/value&gt;
147  * &lt;/init-param&gt;
148  *
149  * <!-- END SNIPPET: example -->
150  * </pre>
151  */
152 public class Jsr168Dispatcher extends GenericPortlet implements StrutsStatics,
153         PortletActionConstants {
154 
155     private static final Log LOG = LogFactory.getLog(Jsr168Dispatcher.class);
156 
157     private ActionProxyFactory factory = null;
158 
159     private Map<PortletMode,String> modeMap = new HashMap<PortletMode,String>(3);
160 
161     private Map<PortletMode,ActionMapping> actionMap = new HashMap<PortletMode,ActionMapping>(3);
162 
163     private String portletNamespace = null;
164 
165     private Dispatcher dispatcherUtils;
166     
167     private ActionMapper actionMapper;
168 
169     /***
170      * Initialize the portlet with the init parameters from <tt>portlet.xml</tt>
171      */
172     public void init(PortletConfig cfg) throws PortletException {
173         super.init(cfg);
174         LOG.debug("Initializing portlet " + getPortletName());
175         
176         Map<String,String> params = new HashMap<String,String>();
177         for (Enumeration e = cfg.getInitParameterNames(); e.hasMoreElements(); ) {
178             String name = (String) e.nextElement();
179             String value = cfg.getInitParameter(name);
180             params.put(name, value);
181         }
182 
183         // TODO: CHECK IF NEEDED (RG Portlet Refactoring Backports)
184         Dispatcher.setPortletSupportActive(true);
185         dispatcherUtils = new Dispatcher(new PortletServletContext(cfg.getPortletContext()), params);
186         dispatcherUtils.init();
187         
188         // For testability
189         if (factory == null) {
190             factory = dispatcherUtils.getConfigurationManager().getConfiguration().getContainer().getInstance(ActionProxyFactory.class);
191         }
192         portletNamespace = cfg.getInitParameter("portletNamespace");
193         LOG.debug("PortletNamespace: " + portletNamespace);
194         parseModeConfig(cfg, PortletMode.VIEW, "viewNamespace",
195                 "defaultViewAction");
196         parseModeConfig(cfg, PortletMode.EDIT, "editNamespace",
197                 "defaultEditAction");
198         parseModeConfig(cfg, PortletMode.HELP, "helpNamespace",
199                 "defaultHelpAction");
200         parseModeConfig(cfg, new PortletMode("config"), "configNamespace",
201                 "defaultConfigAction");
202         parseModeConfig(cfg, new PortletMode("about"), "aboutNamespace",
203                 "defaultAboutAction");
204         parseModeConfig(cfg, new PortletMode("print"), "printNamespace",
205                 "defaultPrintAction");
206         parseModeConfig(cfg, new PortletMode("preview"), "previewNamespace",
207                 "defaultPreviewAction");
208         parseModeConfig(cfg, new PortletMode("edit_defaults"),
209                 "editDefaultsNamespace", "defaultEditDefaultsAction");
210         if (!TextUtils.stringSet(portletNamespace)) {
211             portletNamespace = "";
212         }
213         LocalizedTextUtil
214                 .addDefaultResourceBundle("org/apache/struts2/struts-messages");
215 
216         Container container = dispatcherUtils.getContainer();
217         //check for configuration reloading
218         if ("true".equalsIgnoreCase(container.getInstance(String.class, StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD))) {
219             FileManager.setReloadingConfigs(true);
220         }
221         
222         actionMapper = container.getInstance(ActionMapper.class);
223     }
224 
225     /***
226      * Parse the mode to namespace mappings configured in portlet.xml
227      * @param portletConfig The PortletConfig
228      * @param portletMode The PortletMode
229      * @param nameSpaceParam Name of the init parameter where the namespace for the mode
230      * is configured.
231      * @param defaultActionParam Name of the init parameter where the default action to
232      * execute for the mode is configured.
233      */
234     private void parseModeConfig(PortletConfig portletConfig,
235             PortletMode portletMode, String nameSpaceParam,
236             String defaultActionParam) {
237         String namespace = portletConfig.getInitParameter(nameSpaceParam);
238         if (!TextUtils.stringSet(namespace)) {
239             namespace = "";
240         }
241         modeMap.put(portletMode, namespace);
242         String defaultAction = portletConfig
243                 .getInitParameter(defaultActionParam);
244         if (!TextUtils.stringSet(defaultAction)) {
245             defaultAction = DEFAULT_ACTION_NAME;
246         }
247         StringBuffer fullPath = new StringBuffer();
248         if (TextUtils.stringSet(portletNamespace)) {
249             fullPath.append(portletNamespace);
250         }
251         if (TextUtils.stringSet(namespace)) {
252             fullPath.append(namespace).append("/");
253         } else {
254             fullPath.append("/");
255         }
256         fullPath.append(defaultAction);
257         ActionMapping mapping = new ActionMapping();
258         mapping.setName(getActionName(fullPath.toString()));
259         mapping.setNamespace(getNamespace(fullPath.toString()));
260         actionMap.put(portletMode, mapping);
261     }
262 
263     /***
264      * Service an action from the <tt>event</tt> phase.
265      *
266      * @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest,
267      *      javax.portlet.ActionResponse)
268      */
269     public void processAction(ActionRequest request, ActionResponse response)
270             throws PortletException, IOException {
271         LOG.debug("Entering processAction");
272         resetActionContext();
273         try {
274             serviceAction(request, response, getActionMapping(request),
275                     getRequestMap(request), getParameterMap(request),
276                     getSessionMap(request), getApplicationMap(),
277                     portletNamespace, EVENT_PHASE);
278             LOG.debug("Leaving processAction");
279         } finally {
280             ActionContext.setContext(null);
281         }
282     }
283 
284     /***
285      * Service an action from the <tt>render</tt> phase.
286      *
287      * @see javax.portlet.Portlet#render(javax.portlet.RenderRequest,
288      *      javax.portlet.RenderResponse)
289      */
290     public void render(RenderRequest request, RenderResponse response)
291             throws PortletException, IOException {
292 
293         LOG.debug("Entering render");
294         resetActionContext();
295         response.setTitle(getTitle(request));
296         if(!request.getWindowState().equals(WindowState.MINIMIZED)) {
297         try {
298             // Check to see if an event set the render to be included directly
299             serviceAction(request, response, getActionMapping(request),
300                     getRequestMap(request), getParameterMap(request),
301                     getSessionMap(request), getApplicationMap(),
302                     portletNamespace, RENDER_PHASE);
303             LOG.debug("Leaving render");
304         } finally {
305             resetActionContext();
306         }
307 	}
308     }
309 
310     /***
311      *  Reset the action context.
312      */
313     private void resetActionContext() {
314         ActionContext.setContext(null);
315     }
316 
317     /***
318      * Merges all application and portlet attributes into a single
319      * <tt>HashMap</tt> to represent the entire <tt>Action</tt> context.
320      *
321      * @param requestMap a Map of all request attributes.
322      * @param parameterMap a Map of all request parameters.
323      * @param sessionMap a Map of all session attributes.
324      * @param applicationMap a Map of all servlet context attributes.
325      * @param request the PortletRequest object.
326      * @param response the PortletResponse object.
327      * @param portletConfig the PortletConfig object.
328      * @param phase The portlet phase (render or action, see
329      *        {@link PortletActionConstants})
330      * @return a HashMap representing the <tt>Action</tt> context.
331      */
332     public HashMap createContextMap(Map requestMap, Map parameterMap,
333             Map sessionMap, Map applicationMap, PortletRequest request,
334             PortletResponse response, PortletConfig portletConfig, Integer phase) throws IOException {
335 
336         // TODO Must put http request/response objects into map for use with
337         // ServletActionContext
338         HttpServletResponse dummyResponse = new PortletServletResponse(response);
339         HttpServletRequest dummyRequest = new PortletServletRequest(request, getPortletContext());
340         ServletContext dummyServletContext = new PortletServletContext(getPortletContext());
341         if(EVENT_PHASE.equals(phase)) {
342             dummyRequest = dispatcherUtils.wrapRequest(dummyRequest, dummyServletContext);
343         }
344         HashMap<String,Object> extraContext = new HashMap<String,Object>();
345         // The dummy servlet objects. Eases reuse of existing interceptors that uses the servlet objects.
346         extraContext.put(StrutsStatics.HTTP_REQUEST, dummyRequest);
347         extraContext.put(StrutsStatics.HTTP_RESPONSE, dummyResponse);
348         extraContext.put(StrutsStatics.SERVLET_CONTEXT, dummyServletContext);
349         // End dummy servlet objects
350         extraContext.put(ActionContext.PARAMETERS, parameterMap);
351         extraContext.put(ActionContext.SESSION, sessionMap);
352         extraContext.put(ActionContext.APPLICATION, applicationMap);
353 
354         String defaultLocale = dispatcherUtils.getContainer().getInstance(String.class, StrutsConstants.STRUTS_LOCALE);
355         Locale locale = null;
356         if (defaultLocale != null) {
357             locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
358         } else {
359             locale = request.getLocale();
360         }
361         extraContext.put(ActionContext.LOCALE, locale);
362 
363         extraContext.put(StrutsStatics.STRUTS_PORTLET_CONTEXT, getPortletContext());
364         extraContext.put(REQUEST, request);
365         extraContext.put(RESPONSE, response);
366         extraContext.put(PORTLET_CONFIG, portletConfig);
367         extraContext.put(PORTLET_NAMESPACE, portletNamespace);
368         extraContext.put(DEFAULT_ACTION_FOR_MODE, actionMap.get(request.getPortletMode()));
369         // helpers to get access to request/session/application scope
370         extraContext.put("request", requestMap);
371         extraContext.put("session", sessionMap);
372         extraContext.put("application", applicationMap);
373         extraContext.put("parameters", parameterMap);
374         extraContext.put(MODE_NAMESPACE_MAP, modeMap);
375 
376         extraContext.put(PHASE, phase);
377 
378         AttributeMap attrMap = new AttributeMap(extraContext);
379         extraContext.put("attr", attrMap);
380 
381         return extraContext;
382     }
383 
384     /***
385      * Loads the action and executes it. This method first creates the action
386      * context from the given parameters then loads an <tt>ActionProxy</tt>
387      * from the given action name and namespace. After that, the action is
388      * executed and output channels throught the response object.
389      *
390      * @param request the HttpServletRequest object.
391      * @param response the HttpServletResponse object.
392      * @param mapping the action mapping.
393      * @param requestMap a Map of request attributes.
394      * @param parameterMap a Map of request parameters.
395      * @param sessionMap a Map of all session attributes.
396      * @param applicationMap a Map of all application attributes.
397      * @param portletNamespace the namespace or context of the action.
398      * @param phase The portlet phase (render or action, see
399      *        {@link PortletActionConstants})
400      */
401     public void serviceAction(PortletRequest request, PortletResponse response,
402             ActionMapping mapping, Map requestMap, Map parameterMap,
403             Map sessionMap, Map applicationMap, String portletNamespace,
404             Integer phase) throws PortletException {
405         LOG.debug("serviceAction");
406         String actionName = mapping.getName();
407         String namespace = mapping.getNamespace();
408         Dispatcher.setInstance(dispatcherUtils);
409         try {
410             HashMap extraContext = createContextMap(requestMap, parameterMap,
411                     sessionMap, applicationMap, request, response,
412                     getPortletConfig(), phase);
413             LOG.debug("Creating action proxy for name = " + actionName
414                     + ", namespace = " + namespace);
415             ActionProxy proxy = factory.createActionProxy(namespace,
416                     actionName, extraContext);
417             proxy.setMethod(mapping.getMethod());
418             request.setAttribute("struts.valueStack", proxy.getInvocation()
419                     .getStack());
420             proxy.execute();
421         } catch (ConfigurationException e) {
422             LOG.error("Could not find action", e);
423             throw new PortletException("Could not find action " + actionName, e);
424         } catch (Exception e) {
425             LOG.error("Could not execute action", e);
426             throw new PortletException("Error executing action " + actionName,
427                     e);
428         } finally {
429             Dispatcher.setInstance(null);
430         }
431     }
432 
433     /***
434      * Returns a Map of all application attributes. Copies all attributes from
435      * the {@link PortletActionContext}into an {@link ApplicationMap}.
436      *
437      * @return a Map of all application attributes.
438      */
439     protected Map getApplicationMap() {
440         return new PortletApplicationMap(getPortletContext());
441     }
442 
443     /***
444      * Gets the namespace of the action from the request. The namespace is the
445      * same as the portlet mode. E.g, view mode is mapped to namespace
446      * <code>view</code>, and edit mode is mapped to the namespace
447      * <code>edit</code>
448      *
449      * @param request the PortletRequest object.
450      * @return the namespace of the action.
451      */
452     protected ActionMapping getActionMapping(final PortletRequest request) {
453         ActionMapping mapping = null;
454         String actionPath = null;
455         if (resetAction(request)) {
456             mapping = actionMap.get(request.getPortletMode());
457         } else {
458             actionPath = request.getParameter(ACTION_PARAM);
459             if (!TextUtils.stringSet(actionPath)) {
460                 mapping = actionMap.get(request
461                         .getPortletMode());
462             } else {
463                 
464                 // Use the usual action mapper, but it is expecting an action extension
465                 // on the uri, so we add the default one, which should be ok as the
466                 // portlet is a portlet first, a servlet second
467                 PortletServletRequest httpRequest = new PortletServletRequest(request, getPortletContext());
468                 mapping = actionMapper.getMapping(httpRequest, dispatcherUtils.getConfigurationManager());
469             }
470         }
471         
472         if (mapping == null) {
473             throw new StrutsException("Unable to locate action mapping for request, probably due to " +
474                     "an invalid action path: "+actionPath);
475         }
476         return mapping;
477     }
478 
479     /***
480      * Get the namespace part of the action path.
481      * @param actionPath Full path to action
482      * @return The namespace part.
483      */
484     String getNamespace(String actionPath) {
485         int idx = actionPath.lastIndexOf('/');
486         String namespace = "";
487         if (idx >= 0) {
488             namespace = actionPath.substring(0, idx);
489         }
490         return namespace;
491     }
492 
493     /***
494      * Get the action name part of the action path.
495      * @param actionPath Full path to action
496      * @return The action name.
497      */
498     String getActionName(String actionPath) {
499         int idx = actionPath.lastIndexOf('/');
500         String action = actionPath;
501         if (idx >= 0) {
502             action = actionPath.substring(idx + 1);
503         }
504         return action;
505     }
506 
507     /***
508      * Returns a Map of all request parameters. This implementation just calls
509      * {@link PortletRequest#getParameterMap()}.
510      *
511      * @param request the PortletRequest object.
512      * @return a Map of all request parameters.
513      * @throws IOException if an exception occurs while retrieving the parameter
514      *         map.
515      */
516     protected Map getParameterMap(PortletRequest request) throws IOException {
517         return new HashMap(request.getParameterMap());
518     }
519 
520     /***
521      * Returns a Map of all request attributes. The default implementation is to
522      * wrap the request in a {@link RequestMap}. Override this method to
523      * customize how request attributes are mapped.
524      *
525      * @param request the PortletRequest object.
526      * @return a Map of all request attributes.
527      */
528     protected Map getRequestMap(PortletRequest request) {
529         return new PortletRequestMap(request);
530     }
531 
532     /***
533      * Returns a Map of all session attributes. The default implementation is to
534      * wrap the reqeust in a {@link SessionMap}. Override this method to
535      * customize how session attributes are mapped.
536      *
537      * @param request the PortletRequest object.
538      * @return a Map of all session attributes.
539      */
540     protected Map getSessionMap(PortletRequest request) {
541         return new PortletSessionMap(request);
542     }
543 
544     /***
545      * Convenience method to ease testing.
546      * @param factory
547      */
548     protected void setActionProxyFactory(ActionProxyFactory factory) {
549         this.factory = factory;
550     }
551 
552     /***
553      * Check to see if the action parameter is valid for the current portlet mode. If the portlet
554      * mode has been changed with the portal widgets, the action name is invalid, since the
555      * action name belongs to the previous executing portlet mode. If this method evaluates to
556      * <code>true</code> the <code>default&lt;Mode&gt;Action</code> is used instead.
557      * @param request The portlet request.
558      * @return <code>true</code> if the action should be reset.
559      */
560     private boolean resetAction(PortletRequest request) {
561         boolean reset = false;
562         Map paramMap = request.getParameterMap();
563         String[] modeParam = (String[]) paramMap.get(MODE_PARAM);
564         if (modeParam != null && modeParam.length == 1) {
565             String originatingMode = modeParam[0];
566             String currentMode = request.getPortletMode().toString();
567             if (!currentMode.equals(originatingMode)) {
568                 reset = true;
569             }
570         }
571         if(reset) {
572         	request.setAttribute(ACTION_RESET, Boolean.TRUE);
573         }
574         else {
575         	request.setAttribute(ACTION_RESET, Boolean.FALSE);
576         }
577         return reset;
578     }
579 
580     public void destroy() {
581         if (dispatcherUtils == null) {
582             LOG.warn("something is seriously wrong, DispatcherUtil is not initialized (null) ");
583         } else {
584             dispatcherUtils.cleanup();
585         }
586     }
587 
588     /***
589      * @param actionMapper the actionMapper to set
590      */
591     public void setActionMapper(ActionMapper actionMapper) {
592         this.actionMapper = actionMapper;
593     }
594     
595 }