/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.struts2.portlet.dispatcher; | |
import com.opensymphony.xwork2.ActionContext; | |
import com.opensymphony.xwork2.ActionProxy; | |
import com.opensymphony.xwork2.ActionProxyFactory; | |
import com.opensymphony.xwork2.config.ConfigurationException; | |
import com.opensymphony.xwork2.inject.Container; | |
import org.apache.commons.lang3.LocaleUtils; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.logging.log4j.LogManager; | |
import org.apache.logging.log4j.Logger; | |
import org.apache.logging.log4j.message.ParameterizedMessage; | |
import org.apache.struts2.StrutsConstants; | |
import org.apache.struts2.StrutsException; | |
import org.apache.struts2.StrutsStatics; | |
import org.apache.struts2.dispatcher.ApplicationMap; | |
import org.apache.struts2.dispatcher.Dispatcher; | |
import org.apache.struts2.dispatcher.HttpParameters; | |
import org.apache.struts2.dispatcher.RequestMap; | |
import org.apache.struts2.dispatcher.SessionMap; | |
import org.apache.struts2.dispatcher.mapper.ActionMapper; | |
import org.apache.struts2.dispatcher.mapper.ActionMapping; | |
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper; | |
import org.apache.struts2.portlet.PortletApplicationMap; | |
import org.apache.struts2.portlet.PortletConstants; | |
import org.apache.struts2.portlet.PortletPhase; | |
import org.apache.struts2.portlet.PortletRequestMap; | |
import org.apache.struts2.portlet.PortletSessionMap; | |
import org.apache.struts2.portlet.context.PortletActionContext; | |
import org.apache.struts2.portlet.servlet.PortletServletContext; | |
import org.apache.struts2.portlet.servlet.PortletServletRequest; | |
import org.apache.struts2.portlet.servlet.PortletServletResponse; | |
import org.apache.struts2.util.AttributeMap; | |
import javax.portlet.ActionRequest; | |
import javax.portlet.ActionResponse; | |
import javax.portlet.GenericPortlet; | |
import javax.portlet.PortletConfig; | |
import javax.portlet.PortletException; | |
import javax.portlet.PortletMode; | |
import javax.portlet.PortletRequest; | |
import javax.portlet.PortletResponse; | |
import javax.portlet.RenderRequest; | |
import javax.portlet.RenderResponse; | |
import javax.portlet.WindowState; | |
import javax.servlet.ServletContext; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.util.Enumeration; | |
import java.util.HashMap; | |
import java.util.Locale; | |
import java.util.Map; | |
import static org.apache.struts2.portlet.PortletConstants.ACTION_PARAM; | |
import static org.apache.struts2.portlet.PortletConstants.ACTION_RESET; | |
import static org.apache.struts2.portlet.PortletConstants.DEFAULT_ACTION_FOR_MODE; | |
import static org.apache.struts2.portlet.PortletConstants.DEFAULT_ACTION_NAME; | |
import static org.apache.struts2.portlet.PortletConstants.MODE_NAMESPACE_MAP; | |
import static org.apache.struts2.portlet.PortletConstants.MODE_PARAM; | |
import static org.apache.struts2.portlet.PortletConstants.PORTLET_CONFIG; | |
import static org.apache.struts2.portlet.PortletConstants.PORTLET_NAMESPACE; | |
import static org.apache.struts2.portlet.PortletConstants.REQUEST; | |
import static org.apache.struts2.portlet.PortletConstants.RESPONSE; | |
/** | |
* <!-- START SNIPPET: javadoc --> | |
* <p> | |
* Struts JSR-168 portlet dispatcher. Similar to the WW2 Servlet dispatcher, | |
* but adjusted to a portal environment. The portlet is configured through the <tt>portlet.xml</tt> | |
* descriptor. Examples and descriptions follow below: | |
* </p> | |
* <!-- END SNIPPET: javadoc --> | |
* | |
* @author Nils-Helge Garli | |
* @author Rainer Hermanns | |
* | |
* <p><b>Init parameters</b></p> | |
* <!-- START SNIPPET: params --> | |
* <table class="confluenceTable" summary=""> | |
* <tr> | |
* <th class="confluenceTh">Name</th> | |
* <th class="confluenceTh">Description</th> | |
* <th class="confluenceTh">Default value</th> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">portletNamespace</td><td class="confluenceTd">The namespace for the portlet in the xwork configuration. This | |
* namespace is prepended to all action lookups, and makes it possible to host multiple | |
* portlets in the same portlet application. If this parameter is set, the complete namespace | |
* will be <tt>/portletNamespace/modeNamespace/actionName</tt></td><td class="confluenceTd">The default namespace</td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">viewNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>view</tt> portlet | |
* mode</td><td class="confluenceTd">The default namespace</td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">editNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>edit</tt> portlet | |
* mode</td><td class="confluenceTd">The default namespace</td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">helpNamespace</td><td class="confluenceTd">Base namespace in the xwork configuration for the <tt>help</tt> portlet | |
* mode</td><td class="confluenceTd">The default namespace</td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">defaultViewAction</td><td class="confluenceTd">Default action to invoke in the <tt>view</tt> portlet mode if no action is | |
* specified</td><td class="confluenceTd"><tt>default</tt></td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">defaultEditAction</td><td class="confluenceTd">Default action to invoke in the <tt>edit</tt> portlet mode if no action is | |
* specified</td><td class="confluenceTd"><tt>default</tt></td> | |
* </tr> | |
* <tr> | |
* <td class="confluenceTd">defaultHelpAction</td><td class="confluenceTd">Default action to invoke in the <tt>help</tt> portlet mode if no action is | |
* specified</td><td class="confluenceTd"><tt>default</tt></td> | |
* </tr> | |
* </table> | |
* <!-- END SNIPPET: params --> | |
* <p><b>Example:</b></p> | |
* <pre> | |
* <!-- START SNIPPET: example --> | |
* | |
* <init-param> | |
* <!-- The view mode namespace. Maps to a namespace in the xwork config file --> | |
* <name>viewNamespace</name> | |
* <value>/view</value> | |
* </init-param> | |
* <init-param> | |
* <!-- The default action to invoke in view mode --> | |
* <name>defaultViewAction</name> | |
* <value>index</value> | |
* </init-param> | |
* <init-param> | |
* <!-- The view mode namespace. Maps to a namespace in the xwork config file --> | |
* <name>editNamespace</name> | |
* <value>/edit</value> | |
* </init-param> | |
* <init-param> | |
* <!-- The default action to invoke in view mode --> | |
* <name>defaultEditAction</name> | |
* <value>index</value> | |
* </init-param> | |
* <init-param> | |
* <!-- The view mode namespace. Maps to a namespace in the xwork config file --> | |
* <name>helpNamespace</name> | |
* <value>/help</value> | |
* </init-param> | |
* <init-param> | |
* <!-- The default action to invoke in view mode --> | |
* <name>defaultHelpAction</name> | |
* <value>index</value> | |
* </init-param> | |
* | |
* <!-- END SNIPPET: example --> | |
* </pre> | |
*/ | |
public class Jsr168Dispatcher extends GenericPortlet implements StrutsStatics { | |
private static final Logger LOG = LogManager.getLogger(Jsr168Dispatcher.class); | |
protected String portletNamespace = null; | |
private ActionProxyFactory factory = null; | |
private Map<PortletMode, String> modeMap = new HashMap<PortletMode, String>(3); | |
private Map<PortletMode, ActionMapping> actionMap = new HashMap<PortletMode, ActionMapping>(3); | |
private Dispatcher dispatcherUtils; | |
private ActionMapper actionMapper; | |
private Container container; | |
private ServletContext servletContext; | |
/** | |
* Initialize the portlet with the init parameters from <tt>portlet.xml</tt> | |
* | |
* @param cfg portlet configuration | |
* @throws PortletException in case of errors | |
*/ | |
public void init(PortletConfig cfg) throws PortletException { | |
super.init(cfg); | |
LOG.debug("Initializing portlet {}", getPortletName()); | |
Map<String, String> params = new HashMap<String, String>(); | |
for (Enumeration e = cfg.getInitParameterNames(); e.hasMoreElements(); ) { | |
String name = (String) e.nextElement(); | |
String value = cfg.getInitParameter(name); | |
params.put(name, value); | |
} | |
servletContext = new PortletServletContext(cfg.getPortletContext()); | |
dispatcherUtils = new Dispatcher(servletContext, params); | |
dispatcherUtils.init(); | |
// For testability | |
if (factory == null) { | |
factory = dispatcherUtils.getContainer().getInstance(ActionProxyFactory.class); | |
} | |
portletNamespace = cfg.getInitParameter("portletNamespace"); | |
LOG.debug("PortletNamespace: {}", portletNamespace); | |
parseModeConfig(actionMap, cfg, PortletMode.VIEW, "viewNamespace", | |
"defaultViewAction"); | |
parseModeConfig(actionMap, cfg, PortletMode.EDIT, "editNamespace", | |
"defaultEditAction"); | |
parseModeConfig(actionMap, cfg, PortletMode.HELP, "helpNamespace", | |
"defaultHelpAction"); | |
parseModeConfig(actionMap, cfg, new PortletMode("config"), "configNamespace", | |
"defaultConfigAction"); | |
parseModeConfig(actionMap, cfg, new PortletMode("about"), "aboutNamespace", | |
"defaultAboutAction"); | |
parseModeConfig(actionMap, cfg, new PortletMode("print"), "printNamespace", | |
"defaultPrintAction"); | |
parseModeConfig(actionMap, cfg, new PortletMode("preview"), "previewNamespace", | |
"defaultPreviewAction"); | |
parseModeConfig(actionMap, cfg, new PortletMode("edit_defaults"), | |
"editDefaultsNamespace", "defaultEditDefaultsAction"); | |
if (StringUtils.isEmpty(portletNamespace)) { | |
portletNamespace = ""; | |
} | |
container = dispatcherUtils.getContainer(); | |
actionMapper = container.getInstance(ActionMapper.class); | |
} | |
/** | |
* Parse the mode to namespace mappings configured in portlet.xml | |
* | |
* @param actionMap The map with mode <-> default action mapping. | |
* @param portletConfig The PortletConfig. | |
* @param portletMode The PortletMode. | |
* @param nameSpaceParam Name of the init parameter where the namespace for the mode | |
* is configured. | |
* @param defaultActionParam Name of the init parameter where the default action to | |
* execute for the mode is configured. | |
*/ | |
void parseModeConfig(Map<PortletMode, ActionMapping> actionMap, PortletConfig portletConfig, | |
PortletMode portletMode, String nameSpaceParam, | |
String defaultActionParam) { | |
String namespace = portletConfig.getInitParameter(nameSpaceParam); | |
if (StringUtils.isEmpty(namespace)) { | |
namespace = ""; | |
} | |
modeMap.put(portletMode, namespace); | |
String defaultAction = portletConfig.getInitParameter(defaultActionParam); | |
String method = null; | |
if (StringUtils.isEmpty(defaultAction)) { | |
defaultAction = DEFAULT_ACTION_NAME; | |
} | |
if (defaultAction.indexOf('!') >= 0) { | |
method = defaultAction.substring(defaultAction.indexOf('!') + 1); | |
defaultAction = defaultAction.substring(0, defaultAction.indexOf('!')); | |
} | |
StringBuilder fullPath = new StringBuilder(); | |
if (StringUtils.isNotEmpty(portletNamespace)) { | |
fullPath.append(portletNamespace); | |
} | |
if (StringUtils.isNotEmpty(namespace)) { | |
fullPath.append(namespace).append("/"); | |
} else { | |
fullPath.append("/"); | |
} | |
fullPath.append(defaultAction); | |
ActionMapping mapping = new ActionMapping(); | |
mapping.setName(getActionName(fullPath.toString())); | |
mapping.setNamespace(getNamespace(fullPath.toString())); | |
if (method != null) { | |
mapping.setMethod(method); | |
} | |
actionMap.put(portletMode, mapping); | |
} | |
/** | |
* Service an action from the <tt>event</tt> phase. | |
* | |
* @param request action request | |
* @param response action response | |
* @throws PortletException in case of errors | |
* @throws IOException in case of IO errors | |
* @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, | |
* javax.portlet.ActionResponse) | |
*/ | |
public void processAction(ActionRequest request, ActionResponse response) | |
throws PortletException, IOException { | |
if (LOG.isDebugEnabled()) { | |
LOG.debug("Entering processAction in mode ", request.getPortletMode().toString()); | |
} | |
resetActionContext(); | |
try { | |
serviceAction(request, response, getRequestMap(request), getParameterMap(request), | |
getSessionMap(request), getApplicationMap(), | |
portletNamespace, PortletPhase.ACTION_PHASE); | |
if (LOG.isDebugEnabled()) LOG.debug("Leaving processAction"); | |
} finally { | |
ActionContext.clear(); | |
} | |
} | |
/** | |
* Service an action from the <tt>render</tt> phase. | |
* | |
* @param request render request | |
* @param response render response | |
* @throws PortletException in case of errors | |
* @throws IOException in case of IO errors | |
* @see javax.portlet.Portlet#render(javax.portlet.RenderRequest, | |
* javax.portlet.RenderResponse) | |
*/ | |
public void render(RenderRequest request, RenderResponse response) | |
throws PortletException, IOException { | |
if (LOG.isDebugEnabled()) { | |
LOG.debug("Entering render in mode ", request.getPortletMode().toString()); | |
} | |
resetActionContext(); | |
response.setTitle(getTitle(request)); | |
if (!request.getWindowState().equals(WindowState.MINIMIZED)) { | |
try { | |
// Check to see if an event set the render to be included directly | |
serviceAction(request, response, getRequestMap(request), getParameterMap(request), | |
getSessionMap(request), getApplicationMap(), | |
portletNamespace, PortletPhase.RENDER_PHASE); | |
if (LOG.isDebugEnabled()) LOG.debug("Leaving render"); | |
} finally { | |
resetActionContext(); | |
} | |
} | |
} | |
/** | |
* Reset the action context. | |
*/ | |
void resetActionContext() { | |
ActionContext.clear(); | |
} | |
/** | |
* Merges all application and portlet attributes into a single | |
* <tt>HashMap</tt> to represent the entire <tt>Action</tt> context. | |
* | |
* @param requestMap a Map of all request attributes. | |
* @param parameterMap a Map of all request parameters. | |
* @param sessionMap a Map of all session attributes. | |
* @param applicationMap a Map of all servlet context attributes. | |
* @param request the PortletRequest object. | |
* @param response the PortletResponse object. | |
* @param servletRequest the HttpServletRequest object. | |
* @param servletResponse the HttpServletResponse object. | |
* @param servletContext the ServletContext object. | |
* @param portletConfig the PortletConfig object. | |
* @param phase The portlet phase (render or action, see | |
* {@link PortletConstants}) | |
* @return a HashMap representing the <tt>Action</tt> context. | |
* @throws IOException in case of IO errors | |
*/ | |
public Map<String, Object> createContextMap(Map<String, Object> requestMap, Map<String, String[]> parameterMap, | |
Map<String, Object> sessionMap, Map<String, Object> applicationMap, | |
PortletRequest request, PortletResponse response, HttpServletRequest servletRequest, | |
HttpServletResponse servletResponse, ServletContext servletContext, | |
PortletConfig portletConfig, PortletPhase phase) throws IOException { | |
// TODO Must put http request/response objects into map for use with | |
container.inject(servletRequest); | |
// ServletActionContext | |
Map<String, Object> extraContext = ActionContext.of(new HashMap<String, Object>()) | |
.withServletRequest(servletRequest) | |
.withServletResponse(servletResponse) | |
.withServletContext(servletContext) | |
.withParameters(HttpParameters.create(parameterMap).build()) | |
.withSession(sessionMap) | |
.withApplication(applicationMap) | |
.withLocale(getLocale(request)) | |
.with(StrutsStatics.STRUTS_PORTLET_CONTEXT, getPortletContext()) | |
.with(REQUEST, request) | |
.with(RESPONSE, response) | |
.with(PORTLET_CONFIG, portletConfig) | |
.with(PORTLET_NAMESPACE, portletNamespace) | |
.with(DEFAULT_ACTION_FOR_MODE, actionMap.get(request.getPortletMode())) | |
// helpers to get access to request/session/application scope | |
.with("request", requestMap) | |
.with("session", sessionMap) | |
.with("application", applicationMap) | |
.with("parameters", parameterMap) | |
.with(MODE_NAMESPACE_MAP, modeMap) | |
.with(PortletConstants.DEFAULT_ACTION_MAP, actionMap) | |
.with(PortletConstants.PHASE, phase) | |
.getContextMap(); | |
AttributeMap attrMap = new AttributeMap(extraContext); | |
extraContext.put("attr", attrMap); | |
return extraContext; | |
} | |
protected Locale getLocale(PortletRequest request) { | |
String defaultLocale = container.getInstance(String.class, StrutsConstants.STRUTS_LOCALE); | |
Locale locale; | |
if (defaultLocale != null) { | |
try { | |
locale = LocaleUtils.toLocale(defaultLocale); | |
} catch (IllegalArgumentException e) { | |
LOG.warn(new ParameterizedMessage("Cannot convert 'struts.locale' = [{}] to proper locale, defaulting to request locale [{}]", | |
defaultLocale, request.getLocale()), e); | |
locale = request.getLocale(); | |
} | |
} else { | |
locale = request.getLocale(); | |
} | |
return locale; | |
} | |
/** | |
* Loads the action and executes it. This method first creates the action | |
* context from the given parameters then loads an <tt>ActionProxy</tt> | |
* from the given action name and namespace. After that, the action is | |
* executed and output channels throught the response object. | |
* | |
* @param request the HttpServletRequest object. | |
* @param response the HttpServletResponse object. | |
* @param requestMap a Map of request attributes. | |
* @param parameterMap a Map of request parameters. | |
* @param sessionMap a Map of all session attributes. | |
* @param applicationMap a Map of all application attributes. | |
* @param portletNamespace the namespace or context of the action. | |
* @param phase The portlet phase (render or action, see {@link PortletConstants}) | |
* @throws PortletException in case of errors | |
*/ | |
public void serviceAction(PortletRequest request, PortletResponse response, Map<String, Object> requestMap, Map<String, String[]> parameterMap, | |
Map<String, Object> sessionMap, Map<String, Object> applicationMap, String portletNamespace, | |
PortletPhase phase) throws PortletException { | |
if (LOG.isDebugEnabled()) LOG.debug("serviceAction"); | |
Dispatcher.setInstance(dispatcherUtils); | |
String actionName = null; | |
String namespace; | |
try { | |
HttpServletRequest servletRequest = new PortletServletRequest(request, getPortletContext()); | |
HttpServletResponse servletResponse = createPortletServletResponse(response); | |
if (phase.isAction()) { | |
servletRequest = dispatcherUtils.wrapRequest(servletRequest); | |
if (servletRequest instanceof MultiPartRequestWrapper) { | |
// Multipart request. Request parameters are encoded in the multipart data, | |
// so we need to manually add them to the parameter map. | |
parameterMap.putAll(servletRequest.getParameterMap()); | |
} | |
} | |
container.inject(servletRequest); | |
ActionMapping mapping = getActionMapping(request, servletRequest); | |
actionName = mapping.getName(); | |
if ("renderDirect".equals(actionName)) { | |
namespace = request.getParameter(PortletConstants.RENDER_DIRECT_NAMESPACE); | |
} else { | |
namespace = mapping.getNamespace(); | |
} | |
Map<String, Object> extraContext = createContextMap(requestMap, parameterMap, | |
sessionMap, applicationMap, request, response, servletRequest, servletResponse, | |
servletContext, getPortletConfig(), phase); | |
extraContext.put(PortletConstants.ACTION_MAPPING, mapping); | |
if (LOG.isDebugEnabled()) { | |
LOG.debug("Creating action proxy for name = " + actionName + ", namespace = " + namespace); | |
} | |
ActionProxy proxy = factory.createActionProxy(namespace, actionName, mapping.getMethod(), extraContext); | |
request.setAttribute("struts.valueStack", proxy.getInvocation().getStack()); | |
proxy.execute(); | |
} catch (ConfigurationException e) { | |
if (LOG.isErrorEnabled()) { | |
LOG.error("Could not find action", e); | |
} | |
throw new PortletException("Could not find action " + actionName, e); | |
} catch (Exception e) { | |
if (LOG.isErrorEnabled()) { | |
LOG.error("Could not execute action", e); | |
} | |
throw new PortletException("Error executing action " + actionName, e); | |
} finally { | |
Dispatcher.setInstance(null); | |
} | |
} | |
/** | |
* Returns a Map of all application attributes. Copies all attributes from | |
* the {@link PortletActionContext}into an {@link ApplicationMap}. | |
* | |
* @return a Map of all application attributes. | |
*/ | |
protected Map<String, Object> getApplicationMap() { | |
return new PortletApplicationMap(getPortletContext()); | |
} | |
/** | |
* Gets the namespace of the action from the request. The namespace is the | |
* same as the portlet mode. E.g, view mode is mapped to namespace | |
* <code>view</code>, and edit mode is mapped to the namespace | |
* <code>edit</code> | |
* | |
* @param portletRequest the PortletRequest object. | |
* @param servletRequest the ServletRequest to use | |
* @return the namespace of the action. | |
*/ | |
protected ActionMapping getActionMapping(final PortletRequest portletRequest, final HttpServletRequest servletRequest) { | |
ActionMapping mapping; | |
String actionPath = getDefaultActionPath(portletRequest); | |
if (resetAction(portletRequest)) { | |
mapping = actionMap.get(portletRequest.getPortletMode()); | |
} else { | |
actionPath = servletRequest.getParameter(ACTION_PARAM); | |
if (StringUtils.isEmpty(actionPath)) { | |
mapping = actionMap.get(portletRequest.getPortletMode()); | |
} else { | |
// Use the usual action mapper, but it is expecting an action extension | |
// on the uri, so we add the default one, which should be ok as the | |
// portlet is a portlet first, a servlet second | |
mapping = actionMapper.getMapping(servletRequest, dispatcherUtils.getConfigurationManager()); | |
} | |
} | |
if (mapping == null) { | |
throw new StrutsException("Unable to locate action mapping for request, probably due to an invalid action path: " + actionPath); | |
} | |
return mapping; | |
} | |
protected String getDefaultActionPath(PortletRequest portletRequest) { | |
return null; | |
} | |
/** | |
* Get the namespace part of the action path. | |
* | |
* @param actionPath Full path to action | |
* @return The namespace part. | |
*/ | |
String getNamespace(String actionPath) { | |
int idx = actionPath.lastIndexOf('/'); | |
String namespace = ""; | |
if (idx >= 0) { | |
namespace = actionPath.substring(0, idx); | |
} | |
return namespace; | |
} | |
/** | |
* Get the action name part of the action path. | |
* | |
* @param actionPath Full path to action | |
* @return The action name. | |
*/ | |
String getActionName(String actionPath) { | |
int idx = actionPath.lastIndexOf('/'); | |
String action = actionPath; | |
if (idx >= 0) { | |
action = actionPath.substring(idx + 1); | |
} | |
return action; | |
} | |
/** | |
* Returns a Map of all request parameters. This implementation just calls | |
* {@link PortletRequest#getParameterMap()}. | |
* | |
* @param request the PortletRequest object. | |
* @return a Map of all request parameters. | |
* @throws IOException if an exception occurs while retrieving the parameter | |
* map. | |
*/ | |
protected Map<String, String[]> getParameterMap(PortletRequest request) throws IOException { | |
return new HashMap<String, String[]>(request.getParameterMap()); | |
} | |
/** | |
* Returns a Map of all request attributes. The default implementation is to | |
* wrap the request in a {@link RequestMap}. Override this method to | |
* customize how request attributes are mapped. | |
* | |
* @param request the PortletRequest object. | |
* @return a Map of all request attributes. | |
*/ | |
protected Map<String, Object> getRequestMap(PortletRequest request) { | |
return new PortletRequestMap(request); | |
} | |
/** | |
* Returns a Map of all session attributes. The default implementation is to | |
* wrap the reqeust in a {@link SessionMap}. Override this method to | |
* customize how session attributes are mapped. | |
* | |
* @param request the PortletRequest object. | |
* @return a Map of all session attributes. | |
*/ | |
protected Map<String, Object> getSessionMap(PortletRequest request) { | |
return new PortletSessionMap(request); | |
} | |
/** | |
* Convenience method to ease testing. | |
* | |
* @param factory action proxy factory | |
*/ | |
protected void setActionProxyFactory(ActionProxyFactory factory) { | |
this.factory = factory; | |
} | |
/** | |
* Check to see if the action parameter is valid for the current portlet mode. If the portlet | |
* mode has been changed with the portal widgets, the action name is invalid, since the | |
* action name belongs to the previous executing portlet mode. If this method evaluates to | |
* <code>true</code> the <code>default<Mode>Action</code> is used instead. | |
* | |
* @param request The portlet request. | |
* @return <code>true</code> if the action should be reset. | |
*/ | |
private boolean resetAction(PortletRequest request) { | |
boolean reset = false; | |
Map paramMap = request.getParameterMap(); | |
String[] modeParam = (String[]) paramMap.get(MODE_PARAM); | |
if (modeParam != null && modeParam.length == 1) { | |
String originatingMode = modeParam[0]; | |
String currentMode = request.getPortletMode().toString(); | |
if (!currentMode.equals(originatingMode)) { | |
reset = true; | |
} | |
} | |
if (reset) { | |
request.setAttribute(ACTION_RESET, Boolean.TRUE); | |
} else { | |
request.setAttribute(ACTION_RESET, Boolean.FALSE); | |
} | |
return reset; | |
} | |
public void destroy() { | |
if (dispatcherUtils != null) { | |
dispatcherUtils.cleanup(); | |
} else { | |
if (LOG.isWarnEnabled()) { | |
LOG.warn("Something is seriously wrong, DispatcherUtil is not initialized (null) "); | |
} | |
} | |
} | |
/** | |
* @param actionMapper the actionMapper to set | |
*/ | |
public void setActionMapper(ActionMapper actionMapper) { | |
this.actionMapper = actionMapper; | |
} | |
/** | |
* Method to create a PortletServletResponse matching the used Portlet API, to be overridden for JSR286 Dispatcher. | |
* | |
* @param response The Response used for building the wrapper. | |
* @return The wrapper response for Servlet bound usage. | |
*/ | |
protected PortletServletResponse createPortletServletResponse(PortletResponse response) { | |
return new PortletServletResponse(response); | |
} | |
} |