Jsr168Dispatcherpublic class Jsr168Dispatcher extends javax.portlet.GenericPortlet implements org.apache.struts2.StrutsStatics, org.apache.struts2.portlet.PortletActionConstants
Struts JSR-168 portlet dispatcher. Similar to the WW2 Servlet dispatcher,
but adjusted to a portal environment. The portlet is configured through the portlet.xml
descriptor. Examples and descriptions follow below:
|
Fields Summary |
---|
private static final Log | LOG | private com.opensymphony.xwork2.ActionProxyFactory | factory | private Map | modeMap | private Map | actionMap | private String | portletNamespace | private org.apache.struts2.dispatcher.Dispatcher | dispatcherUtils | private org.apache.struts2.dispatcher.mapper.ActionMapper | actionMapper |
Methods Summary |
---|
public java.util.HashMap | createContextMap(java.util.Map requestMap, java.util.Map parameterMap, java.util.Map sessionMap, java.util.Map applicationMap, javax.portlet.PortletRequest request, javax.portlet.PortletResponse response, javax.portlet.PortletConfig portletConfig, java.lang.Integer phase)Merges all application and portlet attributes into a single
HashMap to represent the entire Action context.
// TODO Must put http request/response objects into map for use with
// ServletActionContext
HashMap<String,Object> extraContext = new HashMap<String,Object>();
extraContext.put(ActionContext.PARAMETERS, parameterMap);
extraContext.put(ActionContext.SESSION, sessionMap);
extraContext.put(ActionContext.APPLICATION, applicationMap);
String defaultLocale = dispatcherUtils.getContainer().getInstance(String.class, StrutsConstants.STRUTS_LOCALE);
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
} else {
locale = request.getLocale();
}
extraContext.put(ActionContext.LOCALE, locale);
extraContext.put(StrutsStatics.STRUTS_PORTLET_CONTEXT, getPortletContext());
extraContext.put(REQUEST, request);
extraContext.put(RESPONSE, response);
extraContext.put(PORTLET_CONFIG, portletConfig);
extraContext.put(PORTLET_NAMESPACE, portletNamespace);
extraContext.put(DEFAULT_ACTION_FOR_MODE, actionMap.get(request.getPortletMode()));
// helpers to get access to request/session/application scope
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
extraContext.put(MODE_NAMESPACE_MAP, modeMap);
extraContext.put(PHASE, phase);
AttributeMap attrMap = new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
return extraContext;
| public void | destroy()
if (dispatcherUtils == null) {
LOG.warn("something is seriously wrong, DispatcherUtil is not initialized (null) ");
} else {
dispatcherUtils.cleanup();
}
| protected org.apache.struts2.dispatcher.mapper.ActionMapping | getActionMapping(javax.portlet.PortletRequest request)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
view , and edit mode is mapped to the namespace
edit
ActionMapping mapping = null;
String actionPath = null;
if (resetAction(request)) {
mapping = (ActionMapping) actionMap.get(request.getPortletMode());
} else {
actionPath = request.getParameter(ACTION_PARAM);
if (!TextUtils.stringSet(actionPath)) {
mapping = (ActionMapping) actionMap.get(request
.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
HttpServletRequestMock httpRequest = new HttpServletRequestMock()
.setServletPath(actionPath + ".action")
.setParameterMap(request.getParameterMap());
mapping = actionMapper.getMapping(httpRequest, 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;
| java.lang.String | getActionName(java.lang.String actionPath)Get the action name part of the action path.
int idx = actionPath.lastIndexOf('/");
String action = actionPath;
if (idx >= 0) {
action = actionPath.substring(idx + 1);
}
return action;
| protected java.util.Map | getApplicationMap()Returns a Map of all application attributes. Copies all attributes from
the {@link PortletActionContext}into an {@link ApplicationMap}.
return new PortletApplicationMap(getPortletContext());
| java.lang.String | getNamespace(java.lang.String actionPath)Get the namespace part of the action path.
int idx = actionPath.lastIndexOf('/");
String namespace = "";
if (idx >= 0) {
namespace = actionPath.substring(0, idx);
}
return namespace;
| protected java.util.Map | getParameterMap(javax.portlet.PortletRequest request)Returns a Map of all request parameters. This implementation just calls
{@link PortletRequest#getParameterMap()}.
return new HashMap(request.getParameterMap());
| protected java.util.Map | getRequestMap(javax.portlet.PortletRequest request)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.
return new PortletRequestMap(request);
| protected java.util.Map | getSessionMap(javax.portlet.PortletRequest 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.
return new PortletSessionMap(request);
| public void | init(javax.portlet.PortletConfig cfg)Initialize the portlet with the init parameters from portlet.xml
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);
}
Dispatcher.setPortletSupportActive(true);
dispatcherUtils = new Dispatcher(ServletContextHolderListener.getServletContext(), params);
dispatcherUtils.init();
// For testability
if (factory == null) {
factory = dispatcherUtils.getConfigurationManager().getConfiguration().getContainer().getInstance(ActionProxyFactory.class);
}
portletNamespace = cfg.getInitParameter("portletNamespace");
LOG.debug("PortletNamespace: " + portletNamespace);
parseModeConfig(cfg, PortletMode.VIEW, "viewNamespace",
"defaultViewAction");
parseModeConfig(cfg, PortletMode.EDIT, "editNamespace",
"defaultEditAction");
parseModeConfig(cfg, PortletMode.HELP, "helpNamespace",
"defaultHelpAction");
parseModeConfig(cfg, new PortletMode("config"), "configNamespace",
"defaultConfigAction");
parseModeConfig(cfg, new PortletMode("about"), "aboutNamespace",
"defaultAboutAction");
parseModeConfig(cfg, new PortletMode("print"), "printNamespace",
"defaultPrintAction");
parseModeConfig(cfg, new PortletMode("preview"), "previewNamespace",
"defaultPreviewAction");
parseModeConfig(cfg, new PortletMode("edit_defaults"),
"editDefaultsNamespace", "defaultEditDefaultsAction");
if (!TextUtils.stringSet(portletNamespace)) {
portletNamespace = "";
}
LocalizedTextUtil
.addDefaultResourceBundle("org/apache/struts2/struts-messages");
Container container = dispatcherUtils.getContainer();
//check for configuration reloading
if ("true".equalsIgnoreCase(container.getInstance(String.class, StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD))) {
FileManager.setReloadingConfigs(true);
}
actionMapper = container.getInstance(ActionMapper.class);
| private void | parseModeConfig(javax.portlet.PortletConfig portletConfig, javax.portlet.PortletMode portletMode, java.lang.String nameSpaceParam, java.lang.String defaultActionParam)Parse the mode to namespace mappings configured in portlet.xml
String namespace = portletConfig.getInitParameter(nameSpaceParam);
if (!TextUtils.stringSet(namespace)) {
namespace = "";
}
modeMap.put(portletMode, namespace);
String defaultAction = portletConfig
.getInitParameter(defaultActionParam);
if (!TextUtils.stringSet(defaultAction)) {
defaultAction = DEFAULT_ACTION_NAME;
}
StringBuffer fullPath = new StringBuffer();
if (TextUtils.stringSet(portletNamespace)) {
fullPath.append(portletNamespace);
}
if (TextUtils.stringSet(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()));
actionMap.put(portletMode, mapping);
| public void | processAction(javax.portlet.ActionRequest request, javax.portlet.ActionResponse response)Service an action from the event phase.
LOG.debug("Entering processAction");
resetActionContext();
try {
serviceAction(request, response, getActionMapping(request),
getRequestMap(request), getParameterMap(request),
getSessionMap(request), getApplicationMap(),
portletNamespace, EVENT_PHASE);
LOG.debug("Leaving processAction");
} finally {
ActionContext.setContext(null);
}
| public void | render(javax.portlet.RenderRequest request, javax.portlet.RenderResponse response)Service an action from the render phase.
LOG.debug("Entering render");
resetActionContext();
response.setTitle(getTitle(request));
try {
// Check to see if an event set the render to be included directly
serviceAction(request, response, getActionMapping(request),
getRequestMap(request), getParameterMap(request),
getSessionMap(request), getApplicationMap(),
portletNamespace, RENDER_PHASE);
LOG.debug("Leaving render");
} finally {
resetActionContext();
}
| private boolean | resetAction(javax.portlet.PortletRequest request)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
true the default<Mode>Action is used instead.
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;
}
}
return reset;
| private void | resetActionContext()Reset the action context.
ActionContext.setContext(null);
| public void | serviceAction(javax.portlet.PortletRequest request, javax.portlet.PortletResponse response, org.apache.struts2.dispatcher.mapper.ActionMapping mapping, java.util.Map requestMap, java.util.Map parameterMap, java.util.Map sessionMap, java.util.Map applicationMap, java.lang.String portletNamespace, java.lang.Integer phase)Loads the action and executes it. This method first creates the action
context from the given parameters then loads an ActionProxy
from the given action name and namespace. After that, the action is
executed and output channels throught the response object.
LOG.debug("serviceAction");
HashMap extraContext = createContextMap(requestMap, parameterMap,
sessionMap, applicationMap, request, response,
getPortletConfig(), phase);
String actionName = mapping.getName();
String namespace = mapping.getNamespace();
Dispatcher.setInstance(dispatcherUtils);
try {
LOG.debug("Creating action proxy for name = " + actionName
+ ", namespace = " + namespace);
ActionProxy proxy = factory.createActionProxy(namespace,
actionName, extraContext);
proxy.setMethod(mapping.getMethod());
request.setAttribute("struts.valueStack", proxy.getInvocation()
.getStack());
if (PortletActionConstants.RENDER_PHASE.equals(phase)
&& TextUtils.stringSet(request
.getParameter(EVENT_ACTION))) {
ActionProxy action = (ActionProxy) request.getPortletSession()
.getAttribute(EVENT_ACTION);
if (action != null) {
ValueStack stack = proxy.getInvocation().getStack();
Object top = stack.pop();
stack.push(action.getInvocation().getAction());
stack.push(top);
}
}
proxy.execute();
if (PortletActionConstants.EVENT_PHASE.equals(phase)) {
// Store the executed action in the session for retrieval in the
// render phase.
ActionResponse actionResp = (ActionResponse) response;
request.getPortletSession().setAttribute(EVENT_ACTION, proxy);
actionResp.setRenderParameter(EVENT_ACTION, "true");
}
} catch (ConfigurationException e) {
LOG.error("Could not find action", e);
throw new PortletException("Could not find action " + actionName, e);
} catch (Exception e) {
LOG.error("Could not execute action", e);
throw new PortletException("Error executing action " + actionName,
e);
} finally {
Dispatcher.setInstance(null);
}
| public void | setActionMapper(org.apache.struts2.dispatcher.mapper.ActionMapper actionMapper)
this.actionMapper = actionMapper;
| protected void | setActionProxyFactory(com.opensymphony.xwork2.ActionProxyFactory factory)Convenience method to ease testing.
this.factory = factory;
|
|