WW-3777 converts UrlHelper into an interface with default implementation, cleanups code and adds support for generics

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@1303298 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Lukasz Lenart
2012-03-21 07:11:29 +00:00
parent f01f6e3cfe
commit c52cd98c9e
18 changed files with 636 additions and 629 deletions
@@ -223,4 +223,8 @@ public final class StrutsConstants {
/** Enables caching of parsed OGNL expressions **/
public static final String STRUTS_ENABLE_OGNL_EXPRESSION_CACHE = "struts.ognl.enableExpressionCache";
/** The{@link org.apache.struts2.views.util.UrlHelper} implementation class **/
public static final String STRUTS_URL_HELPER = "struts.view.urlHelper";
}
@@ -21,19 +21,11 @@
package org.apache.struts2.components;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Stack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsException;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.util.FastByteArrayOutputStream;
@@ -41,9 +33,14 @@ import org.apache.struts2.views.jsp.TagUtils;
import org.apache.struts2.views.util.ContextUtil;
import org.apache.struts2.views.util.UrlHelper;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.TextParseUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Stack;
/**
* Base class to extend for UI components.
@@ -52,12 +49,14 @@ import com.opensymphony.xwork2.util.TextParseUtil;
*
*/
public class Component {
public static final String COMPONENT_STACK = "__component_stack";
protected ValueStack stack;
protected Map parameters;
protected ActionMapper actionMapper;
protected boolean throwExceptionOnELFailure;
private UrlHelper urlHelper;
/**
* Constructor.
@@ -91,7 +90,11 @@ public class Component {
public void setThrowExceptionsOnELFailure(String throwException) {
this.throwExceptionOnELFailure = "true".equals(throwException);
}
@Inject
public void setUrlHelper(UrlHelper urlHelper) {
this.urlHelper = urlHelper;
}
/**
* Gets the OGNL value stack assoicated with this component.
* @return the OGNL value stack assoicated with this component.
@@ -407,7 +410,7 @@ public class Component {
String finalNamespace = determineNamespace(namespace, getStack(), req);
ActionMapping mapping = new ActionMapping(finalAction, finalNamespace, finalMethod, parameters);
String uri = actionMapper.getUriFromActionMapping(mapping);
return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp);
return urlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp);
}
/**
@@ -445,8 +448,8 @@ public class Component {
stack.push(parameters);
stack.push(this);
try {
for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
for (Object o : params.entrySet()) {
Map.Entry entry = (Map.Entry) o;
String key = (String) entry.getKey();
stack.setValue(key, entry.getValue());
}
@@ -27,16 +27,15 @@ import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.StrutsException;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.views.util.UrlHelper;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -51,12 +50,17 @@ public class ServletUrlRenderer implements UrlRenderer {
private static final Logger LOG = LoggerFactory.getLogger(ServletUrlRenderer.class);
private ActionMapper actionMapper;
private UrlHelper urlHelper;
@Inject
public void setActionMapper(ActionMapper mapper) {
this.actionMapper = mapper;
}
@Inject
public void setUrlHelper(UrlHelper urlHelper) {
this.urlHelper = urlHelper;
}
/**
* {@inheritDoc}
@@ -87,7 +91,7 @@ public class ServletUrlRenderer implements UrlRenderer {
if (_value != null && _value.indexOf("?") > 0) {
_value = _value.substring(0, _value.indexOf("?"));
}
result = UrlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
result = urlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
}
String anchor = urlComponent.getAnchor();
if (StringUtils.isNotEmpty(anchor)) {
@@ -121,8 +125,7 @@ public class ServletUrlRenderer implements UrlRenderer {
* {@inheritDoc}
*/
public void renderFormUrl(Form formComponent) {
String namespace = formComponent.determineNamespace(formComponent.namespace, formComponent.getStack(),
formComponent.request);
String namespace = formComponent.determineNamespace(formComponent.namespace, formComponent.getStack(), formComponent.request);
String action;
if(formComponent.action != null) {
@@ -151,8 +154,8 @@ public class ServletUrlRenderer implements UrlRenderer {
if (actionConfig != null) {
ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
String result = UrlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
formComponent.request, formComponent.response, null, null, formComponent.includeContext, true);
String result = urlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
formComponent.request, formComponent.response, null, null, formComponent.includeContext, true);
formComponent.addParameter("action", result);
// let's try to get the actual action class and name
@@ -187,7 +190,7 @@ public class ServletUrlRenderer implements UrlRenderer {
LOG.warn("No configuration found for the specified action: '" + actionName + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
}
String result = UrlHelper.buildUrl(action, formComponent.request, formComponent.response, null, null, formComponent.includeContext, true);
String result = urlHelper.buildUrl(action, formComponent.request, formComponent.response, null, null, formComponent.includeContext, true);
formComponent.addParameter("action", result);
// namespace: cut out anything between the start and the last /
@@ -236,7 +239,7 @@ public class ServletUrlRenderer implements UrlRenderer {
}
if (UrlProvider.NONE.equalsIgnoreCase(includeParams)) {
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.EMPTY_MAP);
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.<String, Object>emptyMap());
} else if (UrlProvider.ALL.equalsIgnoreCase(includeParams)) {
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getHttpServletRequest().getParameterMap());
@@ -267,7 +270,7 @@ public class ServletUrlRenderer implements UrlRenderer {
}
private void includeGetParameters(UrlProvider urlComponent) {
String query = extractQueryString(urlComponent);
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), UrlHelper.parseQueryString(query));
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlHelper.parseQueryString(query));
}
private String extractQueryString(UrlProvider urlComponent) {
@@ -304,9 +307,9 @@ public class ServletUrlRenderer implements UrlRenderer {
* @param parameters component parameters
* @param contextParameters request parameters
*/
protected void mergeRequestParameters(String value, Map parameters, Map contextParameters){
protected void mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, Object> contextParameters){
Map mergedParams = new LinkedHashMap(contextParameters);
Map<String, Object> mergedParams = new LinkedHashMap<String, Object>(contextParameters);
// Merge contextParameters (from current request) with parameters specified in value attribute
// eg. value="someAction.action?id=someId&venue=someVenue"
@@ -315,30 +318,23 @@ public class ServletUrlRenderer implements UrlRenderer {
if (value != null && value.trim().length() > 0 && value.indexOf("?") > 0) {
String queryString = value.substring(value.indexOf("?")+1);
mergedParams = UrlHelper.parseQueryString(queryString);
for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
if (!mergedParams.containsKey(key)) {
mergedParams.put(key, entry.getValue());
mergedParams = urlHelper.parseQueryString(queryString);
for (Map.Entry<String, Object> entry : contextParameters.entrySet()) {
if (!mergedParams.containsKey(entry.getKey())) {
mergedParams.put(entry.getKey(), entry.getValue());
}
}
}
// Merge parameters specified in value attribute
// eg. value="someAction.action?id=someId&venue=someVenue"
// with parameters specified though param tag
// eg. <param name="id" value="%{'someId'}" />
// where parameters specified through param tag takes priority.
for (Iterator iterator = mergedParams.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
if (!parameters.containsKey(key)) {
parameters.put(key, entry.getValue());
for (Map.Entry<String, Object> entry : mergedParams.entrySet()) {
if (!parameters.containsKey(entry.getKey())) {
parameters.put(entry.getKey(), entry.getValue());
}
}
}
@@ -21,17 +21,6 @@
package org.apache.struts2.config;
import java.util.Properties;
import java.util.StringTokenizer;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.components.UrlRenderer;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.velocity.VelocityManager;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.TextProvider;
@@ -46,13 +35,27 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Context;
import com.opensymphony.xwork2.inject.Factory;
import com.opensymphony.xwork2.inject.Scope;
import com.opensymphony.xwork2.util.*;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import com.opensymphony.xwork2.validator.ActionValidatorManager;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.components.UrlRenderer;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.util.UrlHelper;
import org.apache.struts2.views.velocity.VelocityManager;
import java.util.Properties;
import java.util.StringTokenizer;
/**
* Selects the implementations of key framework extension points, using the loaded
@@ -178,7 +181,9 @@ import com.opensymphony.xwork2.validator.ActionValidatorManager;
* </ul>
*/
public class BeanSelectionProvider implements ConfigurationProvider {
public static final String DEFAULT_BEAN_NAME = "struts";
private static final Logger LOG = LoggerFactory.getLogger(BeanSelectionProvider.class);
public void destroy() {
@@ -191,7 +196,6 @@ public class BeanSelectionProvider implements ConfigurationProvider {
public void init(Configuration configuration) throws ConfigurationException {
// NO-OP
}
public boolean needsReload() {
@@ -216,6 +220,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
alias(UrlHelper.class, StrutsConstants.STRUTS_URL_HELPER, builder, props);
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
@@ -271,7 +276,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
String foundName = props.getProperty(key, DEFAULT_BEAN_NAME);
if (builder.contains(type, foundName)) {
if (LOG.isInfoEnabled()) {
LOG.info("Choosing bean ("+foundName+") for "+type);
LOG.info("Choosing bean (" + foundName + ") for " + type);
}
builder.alias(type, foundName, Container.DEFAULT_NAME);
} else {
@@ -305,8 +310,10 @@ public class BeanSelectionProvider implements ConfigurationProvider {
}
static class ObjectFactoryDelegateFactory implements Factory {
String name;
Class type;
ObjectFactoryDelegateFactory(String name, Class type) {
this.name = name;
this.type = type;
@@ -320,5 +327,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
throw new ConfigurationException("Unable to load bean "+type.getName()+" ("+name+")");
}
}
}
}
@@ -21,20 +21,17 @@
package org.apache.struts2.dispatcher;
import java.util.Arrays;
import java.util.List;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
import java.util.Arrays;
import java.util.List;
/**
* <!-- START SNIPPET: description -->
*
*
* This result uses the {@link ActionMapper} provided by the
* {@link ActionMapperFactory} to redirect the browser to a URL that invokes the
* specified action and (optional) namespace. This is better than the
@@ -44,40 +41,40 @@ import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
* and your application will still work. It is strongly recommended that if you
* are redirecting to another action, you use this result rather than the
* standard redirect result.
*
*
* See examples below for an example of how request parameters could be passed
* in.
*
*
* <!-- END SNIPPET: description -->
*
*
* <b>This result type takes the following parameters:</b>
*
*
* <!-- START SNIPPET: params -->
*
*
* <ul>
*
*
* <li><b>actionName (default)</b> - The name of the action that will be
* redirected to.</li>
*
*
* <li><b>namespace</b> - Used to determine which namespace the action is in
* that we're redirecting to. If namespace is null, the default will be the
* current namespace.</li>
*
*
* <li><b>suppressEmptyParameters</b> - Optional boolean (defaults to false) that
* can prevent parameters with no values from being included in the redirect
* URL.</li>
*
* <li><b>parse</b> - Boolean, true by default. If set to false, the actionName
* <li><b>parse</b> - Boolean, true by default. If set to false, the actionName
* param will not be parsed for Ognl expressions.</li>
*
* <li><b>anchor</b> - Optional. Also known as "fragment" or colloquially as
* <li><b>anchor</b> - Optional. Also known as "fragment" or colloquially as
* "hash". You can specify an anchor for a result.</li>
* </ul>
*
*
* <!-- END SNIPPET: params -->
*
*
* <b>Example:</b>
*
*
* <pre>
* <!-- START SNIPPET: example -->
* &lt;package name="public" extends="struts-default"&gt;
@@ -89,19 +86,19 @@ import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
* &lt;/result&gt;
* &lt;/action&gt;
* &lt;/package&gt;
*
*
* &lt;package name="secure" extends="struts-default" namespace="/secure"&gt;
* &lt;-- Redirect to an action in the same namespace --&gt;
* &lt;action name="dashboard" class="..."&gt;
* &lt;result&gt;dashboard.jsp&lt;/result&gt;
* &lt;result name="error" type="redirectAction"&gt;error&lt;/result&gt;
* &lt;/action&gt;
*
*
* &lt;action name="error" class="..."&gt;
* &lt;result&gt;error.jsp&lt;/result&gt;
* &lt;/action&gt;
* &lt;/package&gt;
*
*
* &lt;package name="passingRequestParameters" extends="struts-default" namespace="/passingRequestParameters"&gt;
* &lt;!-- Pass parameters (reportType, width and height) --&gt;
* &lt;!--
@@ -121,18 +118,18 @@ import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
* &lt;/result&gt;
* &lt;/action&gt;
* &lt;/package&gt;
*
*
*
*
* <!-- END SNIPPET: example -->
* </pre>
*
*
* @see ActionMapper
*/
public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler {
private static final long serialVersionUID = -9042425229314584066L;
/** The default parameter */
/* The default parameter */
public static final String DEFAULT_PARAM = "actionName";
protected String actionName;
@@ -165,68 +162,55 @@ public class ServletActionRedirectResult extends ServletRedirectResult implement
/**
* @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
*/
public void execute(ActionInvocation invocation) throws Exception
{
public void execute(ActionInvocation invocation) throws Exception {
actionName = conditionalParse(actionName, invocation);
if (namespace == null)
{
if (namespace == null) {
namespace = invocation.getProxy().getNamespace();
}
else
{
} else {
namespace = conditionalParse(namespace, invocation);
}
if (method == null)
{
if (method == null) {
method = "";
}
else
{
} else {
method = conditionalParse(method, invocation);
}
StringBuilder tmpLocation = new StringBuilder(actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)));
String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
setLocation(tmpLocation.toString());
setLocation(tmpLocation);
super.execute(invocation);
}
/**
* Sets the action name
*
* @param actionName
* The name
*
* @param actionName The name
*/
public void setActionName(String actionName)
{
public void setActionName(String actionName) {
this.actionName = actionName;
}
/**
* Sets the namespace
*
* @param namespace
* The namespace
*
* @param namespace The namespace
*/
public void setNamespace(String namespace)
{
public void setNamespace(String namespace) {
this.namespace = namespace;
}
/**
* Sets the method
*
* @param method
* The method
*
* @param method The method
*/
public void setMethod(String method)
{
public void setMethod(String method) {
this.method = method;
}
protected List<String> getProhibitedResultParams()
{
protected List<String> getProhibitedResultParams() {
return Arrays.asList(DEFAULT_PARAM, "namespace", "method", "encode", "parse", "location", "prependServletContext", "suppressEmptyParameters", "anchor");
}
}
@@ -22,8 +22,10 @@
package org.apache.struts2.dispatcher;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;
@@ -95,6 +97,8 @@ public class ServletDispatcherResult extends StrutsResultSupport {
private static final Logger LOG = LoggerFactory.getLogger(ServletDispatcherResult.class);
private UrlHelper urlHelper;
public ServletDispatcherResult() {
super();
}
@@ -103,6 +107,11 @@ public class ServletDispatcherResult extends StrutsResultSupport {
super(location);
}
@Inject
public void setUrlHelper(UrlHelper urlHelper) {
this.urlHelper = urlHelper;
}
/**
* Dispatches to the given location. Does its forward via a RequestDispatcher. If the
* dispatch fails a 404 error will be sent back in the http response.
@@ -128,11 +137,10 @@ public class ServletDispatcherResult extends StrutsResultSupport {
//add parameters passed on the location to #parameters
// see WW-2120
if (invocation != null && finalLocation != null && finalLocation.length() > 0
&& finalLocation.indexOf("?") > 0) {
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
Map parameters = (Map) invocation.getInvocationContext().getContextMap().get("parameters");
Map queryParams = UrlHelper.parseQueryString(queryString, true);
Map<String, Object> parameters = getParameters(invocation);
Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
}
@@ -140,7 +148,6 @@ public class ServletDispatcherResult extends StrutsResultSupport {
// if the view doesn't exist, let's do a 404
if (dispatcher == null) {
response.sendError(404, "result '" + finalLocation + "' not found");
return;
}
@@ -160,4 +167,10 @@ public class ServletDispatcherResult extends StrutsResultSupport {
}
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getParameters(ActionInvocation invocation) {
return (Map<String, Object>) invocation.getInvocationContext().getContextMap().get("parameters");
}
}
@@ -100,17 +100,14 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
private static final Logger LOG = LoggerFactory.getLogger(ServletRedirectResult.class);
protected boolean prependServletContext = true;
protected ActionMapper actionMapper;
protected int statusCode = SC_FOUND;
protected boolean suppressEmptyParameters = false;
protected Map<String, String> requestParameters = new LinkedHashMap<String, String>();
protected Map<String, Object> requestParameters = new LinkedHashMap<String, Object>();
protected String anchor;
private UrlHelper urlHelper;
public ServletRedirectResult() {
super();
}
@@ -125,13 +122,16 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
}
@Inject
public void setActionMapper(ActionMapper mapper)
{
public void setActionMapper(ActionMapper mapper) {
this.actionMapper = mapper;
}
public void setStatusCode(int code)
{
@Inject
public void setUrlHelper(UrlHelper urlHelper) {
this.urlHelper = urlHelper;
}
public void setStatusCode(int code) {
this.statusCode = code;
}
@@ -140,8 +140,7 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
*
* @param anchor
*/
public void setAnchor(String anchor)
{
public void setAnchor(String anchor) {
this.anchor = anchor;
}
@@ -149,22 +148,16 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
* Sets whether or not to prepend the servlet context path to the redirected
* URL.
*
* @param prependServletContext
* <tt>true</tt> to prepend the location with the servlet context
* path, <tt>false</tt> otherwise.
* @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path, <tt>false</tt> otherwise.
*/
public void setPrependServletContext(boolean prependServletContext)
{
public void setPrependServletContext(boolean prependServletContext) {
this.prependServletContext = prependServletContext;
}
public void execute(ActionInvocation invocation) throws Exception
{
if (anchor != null)
{
public void execute(ActionInvocation invocation) throws Exception {
if (anchor != null) {
anchor = conditionalParse(anchor, invocation);
}
super.execute(invocation);
}
@@ -172,58 +165,43 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
* Redirects to the location specified by calling
* {@link HttpServletResponse#sendRedirect(String)}.
*
* @param finalLocation
* the location to redirect to.
* @param invocation
* an encapsulation of the action execution state.
* @throws Exception
* if an error occurs when redirecting.
* @param finalLocation the location to redirect to.
* @param invocation an encapsulation of the action execution state.
* @throws Exception if an error occurs when redirecting.
*/
protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception
{
protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
if (isPathUrl(finalLocation))
{
if (!finalLocation.startsWith("/"))
{
if (isPathUrl(finalLocation)) {
if (!finalLocation.startsWith("/")) {
ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
String namespace = null;
if (mapping != null)
{
if (mapping != null) {
namespace = mapping.getNamespace();
}
if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace)))
{
if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
finalLocation = namespace + "/" + finalLocation;
}
else
{
} else {
finalLocation = "/" + finalLocation;
}
}
// if the URL's are relative to the servlet context, append the servlet context path
if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0))
{
if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
finalLocation = request.getContextPath() + finalLocation;
}
ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
if (resultConfig != null)
{
if (resultConfig != null) {
Map<String, String> resultConfigParams = resultConfig.getParams();
for (Map.Entry<String, String> e : resultConfigParams.entrySet())
{
if (!getProhibitedResultParams().contains(e.getKey()))
{
for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
if (!getProhibitedResultParams().contains(e.getKey())) {
String potentialValue = e.getValue() == null ? "" : conditionalParse(e.getValue(), invocation);
if (!suppressEmptyParameters || ((potentialValue != null) && (potentialValue.length() > 0)))
{
if (!suppressEmptyParameters || ((potentialValue != null) && (potentialValue.length() > 0))) {
requestParameters.put(e.getKey(), potentialValue);
}
}
@@ -231,27 +209,24 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
}
StringBuilder tmpLocation = new StringBuilder(finalLocation);
UrlHelper.buildParametersString(requestParameters, tmpLocation, "&");
urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
// add the anchor
if (anchor != null)
{
if (anchor != null) {
tmpLocation.append('#').append(anchor);
}
finalLocation = response.encodeRedirectURL(tmpLocation.toString());
}
if (LOG.isDebugEnabled())
{
if (LOG.isDebugEnabled()) {
LOG.debug("Redirecting to finalLocation " + finalLocation);
}
sendRedirect(response, finalLocation);
}
protected List<String> getProhibitedResultParams()
{
protected List<String> getProhibitedResultParams() {
return Arrays.asList(DEFAULT_PARAM, "namespace", "method", "encode", "parse", "location", "prependServletContext", "suppressEmptyParameters", "anchor");
}
@@ -259,20 +234,14 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
* Sends the redirection. Can be overridden to customize how the redirect is
* handled (i.e. to use a different status code)
*
* @param response
* The response
* @param finalLocation
* The location URI
* @param response The response
* @param finalLocation The location URI
* @throws IOException
*/
protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException
{
if (SC_FOUND == statusCode)
{
protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
if (SC_FOUND == statusCode) {
response.sendRedirect(finalLocation);
}
else
{
} else {
response.setStatus(statusCode);
response.setHeader("Location", finalLocation);
response.getWriter().write(finalLocation);
@@ -281,8 +250,7 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
}
private static boolean isPathUrl(String url)
{
private static boolean isPathUrl(String url) {
// filter out "http:", "https:", "mailto:", "file:", "ftp:"
// since the only valid places for : in URL's is before the path specification
// either before the port, or after the protocol
@@ -292,31 +260,28 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
/**
* Sets the suppressEmptyParameters option
*
* @param suppressEmptyParameters
* The new value for this option
* @param suppressEmptyParameters The new value for this option
*/
public void setSuppressEmptyParameters(boolean suppressEmptyParameters)
{
public void setSuppressEmptyParameters(boolean suppressEmptyParameters) {
this.suppressEmptyParameters = suppressEmptyParameters;
}
/**
* Adds a request parameter to be added to the redirect url
*
* @param key
* The parameter name
* @param value
* The parameter value
* @param key The parameter name
* @param value The parameter value
*/
public ServletRedirectResult addParameter(String key, Object value)
{
public ServletRedirectResult addParameter(String key, Object value) {
requestParameters.put(key, String.valueOf(value));
return this;
}
public void handle(ReflectionException ex)
{
public void handle(ReflectionException ex) {
// Only log as debug as they are probably parameters to be appended to the url
LOG.debug(ex.getMessage(), ex);
if (LOG.isDebugEnabled()) {
LOG.debug(ex.getMessage(), ex);
}
}
}
@@ -45,53 +45,49 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Struts base utility class, for use in Velocity and Freemarker templates
*
*/
public class StrutsUtil {
protected static final Logger LOG = LoggerFactory.getLogger(StrutsUtil.class);
protected HttpServletRequest request;
protected HttpServletResponse response;
protected Map classes = new Hashtable();
protected Map<String, Class> classes = new Hashtable<String, Class>();
protected OgnlTool ognl;
protected ValueStack stack;
private UrlHelper urlHelper;
private ObjectFactory objectFactory;
public StrutsUtil(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
this.stack = stack;
this.request = request;
this.response = response;
this.ognl = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(OgnlTool.class);
this.urlHelper = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(UrlHelper.class);
this.objectFactory = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(ObjectFactory.class);
}
public Object bean(Object aName) throws Exception {
String name = aName.toString();
Class c = (Class) classes.get(name);
Class c = classes.get(name);
if (c == null) {
c = ClassLoaderUtil.loadClass(name, StrutsUtil.class);
classes.put(name, c);
}
return ObjectFactory.getObjectFactory().buildBean(c, stack.getContext());
return objectFactory.buildBean(c, stack.getContext());
}
public boolean isTrue(String expression) {
Boolean retVal = (Boolean) stack.findValue(expression, Boolean.class);
if (retVal == null) {
return false;
}
return retVal.booleanValue();
return retVal != null && retVal;
}
public Object findString(String name) {
@@ -134,7 +130,7 @@ public class StrutsUtil {
}
public String buildUrl(String url) {
return UrlHelper.buildUrl(url, request, response, null);
return urlHelper.buildUrl(url, request, response, null);
}
public Object findValue(String expression, String className) throws ClassNotFoundException {
@@ -190,9 +186,8 @@ public class StrutsUtil {
Collection items = (Collection) stack.findValue(list);
if (items != null) {
for (Iterator iter = items.iterator(); iter.hasNext();) {
Object element = (Object) iter.next();
Object key = null;
for (Object element : items) {
Object key;
if ((listKey == null) || (listKey.length() == 0)) {
key = element;
@@ -284,4 +279,5 @@ public class StrutsUtil {
writer.write(aByte);
}
}
}
@@ -21,13 +21,14 @@
package org.apache.struts2.util;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.util.DefaultUrlHelper;
import org.apache.struts2.views.util.UrlHelper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.views.util.UrlHelper;
import java.util.HashMap;
import java.util.Map;
/**
@@ -36,11 +37,12 @@ import org.apache.struts2.views.util.UrlHelper;
*/
public class URLBean {
HashMap params;
HashMap<String, String> params;
HttpServletRequest request;
HttpServletResponse response;
String page;
private UrlHelper urlHelper;
public URLBean setPage(String page) {
this.page = page;
@@ -49,6 +51,7 @@ public class URLBean {
public void setRequest(HttpServletRequest request) {
this.request = request;
urlHelper = ServletActionContext.getContext().getInstance(DefaultUrlHelper.class);
}
public void setResponse(HttpServletResponse response) {
@@ -57,10 +60,10 @@ public class URLBean {
public String getURL() {
// all this trickier with maps is to reduce the number of objects created
Map fullParams = null;
Map<String, Object> fullParams = null;
if (params != null) {
fullParams = new HashMap();
fullParams = new HashMap<String, Object>();
}
if (page == null) {
@@ -78,12 +81,12 @@ public class URLBean {
fullParams.putAll(params);
}
return UrlHelper.buildUrl(page, request, response, fullParams);
return urlHelper.buildUrl(page, request, response, fullParams);
}
public URLBean addParameter(String name, Object value) {
if (params == null) {
params = new HashMap();
params = new HashMap<String, String>();
}
if (value == null) {
@@ -0,0 +1,335 @@
/*
* $Id$
*
* 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.views.util;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Default implementation of UrlHelper
*/
public class DefaultUrlHelper implements UrlHelper {
private static final Logger LOG = LoggerFactory.getLogger(DefaultUrlHelper.class);
private String encoding = "UTF-8";
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setEncoding(String encoding) {
if (StringUtils.isNotEmpty(encoding)) {
this.encoding = encoding;
}
}
public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params) {
return buildUrl(action, request, response, params, null, true, true);
}
public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult) {
return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
}
public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true);
}
public String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) {
StringBuilder link = new StringBuilder();
boolean changedScheme = false;
// FIXME: temporary hack until class is made a properly injected bean
Container cont = ActionContext.getContext().getContainer();
int httpPort = Integer.parseInt(cont.getInstance(String.class, StrutsConstants.STRUTS_URL_HTTP_PORT));
int httpsPort = Integer.parseInt(cont.getInstance(String.class, StrutsConstants.STRUTS_URL_HTTPS_PORT));
// only append scheme if it is different to the current scheme *OR*
// if we explicity want it to be appended by having forceAddSchemeHostAndPort = true
if (forceAddSchemeHostAndPort) {
String reqScheme = request.getScheme();
changedScheme = true;
link.append(scheme != null ? scheme : reqScheme);
link.append("://");
link.append(request.getServerName());
if (scheme != null) {
// If switching schemes, use the configured port for the particular scheme.
if (!scheme.equals(reqScheme)) {
if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
link.append(":");
link.append(scheme.equals("http") ? httpPort : httpsPort);
}
// Else use the port from the current request.
} else {
int reqPort = request.getServerPort();
if ((scheme.equals("http") && (reqPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && reqPort != DEFAULT_HTTPS_PORT)) {
link.append(":");
link.append(reqPort);
}
}
}
}
else if ((scheme != null) && !scheme.equals(request.getScheme())) {
changedScheme = true;
link.append(scheme);
link.append("://");
link.append(request.getServerName());
if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
{
link.append(":");
link.append(scheme.equals("http") ? httpPort : httpsPort);
}
}
if (action != null) {
// Check if context path needs to be added
// Add path to absolute links
if (action.startsWith("/") && includeContext) {
String contextPath = request.getContextPath();
if (!contextPath.equals("/")) {
link.append(contextPath);
}
} else if (changedScheme) {
// (Applicable to Servlet 2.4 containers)
// If the request was forwarded, the attribute below will be set with the original URL
String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
// If the attribute wasn't found, default to the value in the request object
if (uri == null) {
uri = request.getRequestURI();
}
link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
}
// Add page
link.append(action);
} else {
// Go to "same page"
String requestURI = (String) request.getAttribute("struts.request_uri");
// (Applicable to Servlet 2.4 containers)
// If the request was forwarded, the attribute below will be set with the original URL
if (requestURI == null) {
requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
}
// If neither request attributes were found, default to the value in the request object
if (requestURI == null) {
requestURI = request.getRequestURI();
}
link.append(requestURI);
}
//if the action was not explicitly set grab the params from the request
if (escapeAmp) {
buildParametersString(params, link);
} else {
buildParametersString(params, link, "&");
}
String result = link.toString();
if (StringUtils.containsIgnoreCase(result, "<script")){
result = StringEscapeUtils.escapeEcmaScript(result);
}
try {
result = encodeResult ? response.encodeURL(result) : result;
} catch (Exception ex) {
// Could not encode the URL for some reason
// Use it unchanged
result = link.toString();
}
return result;
}
public void buildParametersString(Map<String, Object> params, StringBuilder link) {
buildParametersString(params, link, AMP);
}
public void buildParametersString(Map<String, Object> params, StringBuilder link, String paramSeparator) {
if ((params != null) && (params.size() > 0)) {
if (!link.toString().contains("?")) {
link.append("?");
} else {
link.append(paramSeparator);
}
// Set params
Iterator<Map.Entry<String, Object>> iter = params.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Object> entry = iter.next();
String name = entry.getKey();
Object value = entry.getValue();
if (value instanceof Iterable) {
for (Iterator iterator = ((Iterable) value).iterator(); iterator
.hasNext();) {
Object paramValue = iterator.next();
link.append(buildParameterSubstring(name, paramValue
.toString()));
if (iterator.hasNext())
link.append(paramSeparator);
}
} else if (value instanceof Object[]) {
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++) {
Object paramValue = array[i];
link.append(buildParameterSubstring(name, paramValue
.toString()));
if (i < array.length - 1)
link.append(paramSeparator);
}
} else {
link.append(buildParameterSubstring(name, value != null ? value.toString() : StringUtils.EMPTY));
}
if (iter.hasNext()) {
link.append(paramSeparator);
}
}
}
}
private String buildParameterSubstring(String name, String value) {
StringBuilder builder = new StringBuilder();
builder.append(translateAndEncode(name));
builder.append('=');
builder.append(translateAndEncode(value));
return builder.toString();
}
/**
* Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
* encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
*
* @param input
* @return the translated and encoded string
*/
public String translateAndEncode(String input) {
String translatedInput = translateVariable(input);
try {
return URLEncoder.encode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
}
return translatedInput;
}
}
public String translateAndDecode(String input) {
String translatedInput = translateVariable(input);
try {
return URLDecoder.decode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
}
return translatedInput;
}
}
private String translateVariable(String input) {
ValueStack valueStack = ServletActionContext.getContext().getValueStack();
return TextParseUtil.translateVariables(input, valueStack);
}
public Map<String, Object> parseQueryString(String queryString) {
return parseQueryString(queryString, false);
}
public Map<String, Object> parseQueryString(String queryString, boolean forceValueArray) {
Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
if (queryString != null) {
String[] params = queryString.split("&");
for (String param : params) {
if (param.trim().length() > 0) {
String[] tmpParams = param.split("=");
String paramName = null;
String paramValue = "";
if (tmpParams.length > 0) {
paramName = tmpParams[0];
}
if (tmpParams.length > 1) {
paramValue = tmpParams[1];
}
if (paramName != null) {
paramName = translateAndDecode(paramName);
String translatedParamValue = translateAndDecode(paramValue);
if (queryParams.containsKey(paramName) || forceValueArray) {
// WW-1619 append new param value to existing value(s)
Object currentParam = queryParams.get(paramName);
if (currentParam instanceof String) {
queryParams.put(paramName, new String[]{(String) currentParam, translatedParamValue});
} else {
String currentParamValues[] = (String[]) currentParam;
if (currentParamValues != null) {
List<String> paramList = Arrays.asList(currentParamValues);
paramList.add(translatedParamValue);
queryParams.put(paramName, paramList.toArray(new String[paramList.size()]));
} else {
queryParams.put(paramName, new String[]{translatedParamValue});
}
}
} else {
queryParams.put(paramName, translatedParamValue);
}
}
}
}
}
return queryParams;
}
}
@@ -1,364 +1,43 @@
/*
* $Id$
*
* 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.views.util;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* UrlHelper
*
* Helper class used to build Urls or parse request params
*/
public class UrlHelper {
private static final Logger LOG = LoggerFactory.getLogger(UrlHelper.class);
public interface UrlHelper {
/**
* Default HTTP port (80).
*/
private static final int DEFAULT_HTTP_PORT = 80;
static final int DEFAULT_HTTP_PORT = 80;
/**
* Default HTTPS port (443).
*/
private static final int DEFAULT_HTTPS_PORT = 443;
static final int DEFAULT_HTTPS_PORT = 443;
private static final String AMP = "&amp;";
static final String AMP = "&amp;";
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) {
return buildUrl(action, request, response, params, null, true, true);
}
String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params);
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult) {
return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
}
String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult);
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true);
}
String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort);
public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) {
StringBuilder link = new StringBuilder();
String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map<String, Object> params, String scheme,
boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp);
boolean changedScheme = false;
void buildParametersString(Map<String, Object> params, StringBuilder link);
// FIXME: temporary hack until class is made a properly injected bean
Container cont = ActionContext.getContext().getContainer();
int httpPort = Integer.parseInt(cont.getInstance(String.class, StrutsConstants.STRUTS_URL_HTTP_PORT));
int httpsPort = Integer.parseInt(cont.getInstance(String.class, StrutsConstants.STRUTS_URL_HTTPS_PORT));
void buildParametersString(Map<String, Object> params, StringBuilder link, String paramSeparator);
// only append scheme if it is different to the current scheme *OR*
// if we explicity want it to be appended by having forceAddSchemeHostAndPort = true
if (forceAddSchemeHostAndPort) {
String reqScheme = request.getScheme();
changedScheme = true;
link.append(scheme != null ? scheme : reqScheme);
link.append("://");
link.append(request.getServerName());
Map<String, Object> parseQueryString(String queryString);
if (scheme != null) {
// If switching schemes, use the configured port for the particular scheme.
if (!scheme.equals(reqScheme)) {
if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
link.append(":");
link.append(scheme.equals("http") ? httpPort : httpsPort);
}
// Else use the port from the current request.
} else {
int reqPort = request.getServerPort();
Map<String, Object> parseQueryString(String queryString, boolean forceValueArray);
if ((scheme.equals("http") && (reqPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && reqPort != DEFAULT_HTTPS_PORT)) {
link.append(":");
link.append(reqPort);
}
}
}
}
else if ((scheme != null) && !scheme.equals(request.getScheme())) {
changedScheme = true;
link.append(scheme);
link.append("://");
link.append(request.getServerName());
if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT))
{
link.append(":");
link.append(scheme.equals("http") ? httpPort : httpsPort);
}
}
if (action != null) {
// Check if context path needs to be added
// Add path to absolute links
if (action.startsWith("/") && includeContext) {
String contextPath = request.getContextPath();
if (!contextPath.equals("/")) {
link.append(contextPath);
}
} else if (changedScheme) {
// (Applicable to Servlet 2.4 containers)
// If the request was forwarded, the attribute below will be set with the original URL
String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
// If the attribute wasn't found, default to the value in the request object
if (uri == null) {
uri = request.getRequestURI();
}
link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
}
// Add page
link.append(action);
} else {
// Go to "same page"
String requestURI = (String) request.getAttribute("struts.request_uri");
// (Applicable to Servlet 2.4 containers)
// If the request was forwarded, the attribute below will be set with the original URL
if (requestURI == null) {
requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
}
// If neither request attributes were found, default to the value in the request object
if (requestURI == null) {
requestURI = request.getRequestURI();
}
link.append(requestURI);
}
//if the action was not explicitly set grab the params from the request
if (escapeAmp) {
buildParametersString(params, link);
} else {
buildParametersString(params, link, "&");
}
String result = link.toString();
if (StringUtils.containsIgnoreCase(result, "<script")){
result = StringEscapeUtils.escapeEcmaScript(result);
}
try {
result = encodeResult ? response.encodeURL(result) : result;
} catch (Exception ex) {
// Could not encode the URL for some reason
// Use it unchanged
result = link.toString();
}
return result;
}
public static void buildParametersString(Map params, StringBuilder link) {
buildParametersString(params, link, AMP);
}
public static void buildParametersString(Map params, StringBuilder link, String paramSeparator) {
if ((params != null) && (params.size() > 0)) {
if (link.toString().indexOf("?") == -1) {
link.append("?");
} else {
link.append(paramSeparator);
}
// Set params
Iterator iter = params.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof Iterable) {
for (Iterator iterator = ((Iterable) value).iterator(); iterator
.hasNext();) {
Object paramValue = iterator.next();
link.append(buildParameterSubstring(name, paramValue
.toString()));
if (iterator.hasNext())
link.append(paramSeparator);
}
} else if (value instanceof Object[]) {
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++) {
Object paramValue = array[i];
link.append(buildParameterSubstring(name, paramValue
.toString()));
if (i < array.length - 1)
link.append(paramSeparator);
}
} else {
link.append(buildParameterSubstring(name, value != null ? value.toString() : StringUtils.EMPTY));
}
if (iter.hasNext())
link.append(paramSeparator);
}
}
}
private static String buildParameterSubstring(String name, String value) {
StringBuilder builder = new StringBuilder();
builder.append(translateAndEncode(name));
builder.append('=');
builder.append(translateAndEncode(value));
return builder.toString();
}
/**
* Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
* encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
*
* @param input
* @return the translated and encoded string
*/
public static String translateAndEncode(String input) {
String translatedInput = translateVariable(input);
String encoding = getEncodingFromConfiguration();
try {
return URLEncoder.encode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
}
return translatedInput;
}
}
public static String translateAndDecode(String input) {
String translatedInput = translateVariable(input);
String encoding = getEncodingFromConfiguration();
try {
return URLDecoder.decode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
}
return translatedInput;
}
}
private static String translateVariable(String input) {
ValueStack valueStack = ServletActionContext.getContext().getValueStack();
String output = TextParseUtil.translateVariables(input, valueStack);
return output;
}
private static String getEncodingFromConfiguration() {
final String encoding;
// FIXME: temporary hack until class is made a properly injected bean
Container cont = ActionContext.getContext().getContainer();
String customEncoding = cont.getInstance(String.class, StrutsConstants.STRUTS_I18N_ENCODING);
if (customEncoding != null) {
encoding = customEncoding;
} else {
encoding = "UTF-8";
}
return encoding;
}
public static Map parseQueryString(String queryString) {
return parseQueryString(queryString, false);
}
public static Map parseQueryString(String queryString, boolean forceValueArray) {
Map queryParams = new LinkedHashMap();
if (queryString != null) {
String[] params = queryString.split("&");
for (int a=0; a< params.length; a++) {
if (params[a].trim().length() > 0) {
String[] tmpParams = params[a].split("=");
String paramName = null;
String paramValue = "";
if (tmpParams.length > 0) {
paramName = tmpParams[0];
}
if (tmpParams.length > 1) {
paramValue = tmpParams[1];
}
if (paramName != null) {
paramName = translateAndDecode(paramName);
String translatedParamValue = translateAndDecode(paramValue);
if(queryParams.containsKey(paramName) || forceValueArray) {
// WW-1619 append new param value to existing value(s)
Object currentParam = queryParams.get(paramName);
if(currentParam instanceof String) {
queryParams.put(paramName, new String[] {
(String) currentParam, translatedParamValue});
} else {
String currentParamValues[] = (String[]) currentParam;
if (currentParamValues != null) {
List paramList = new ArrayList(Arrays
.asList(currentParamValues));
paramList.add(translatedParamValue);
String newParamValues[] = new String[paramList
.size()];
queryParams.put(paramName, paramList
.toArray(newParamValues));
} else {
queryParams.put(paramName, new String[] {translatedParamValue});
}
}
} else {
queryParams.put(paramName, translatedParamValue);
}
}
}
}
}
return queryParams;
}
}
@@ -73,6 +73,7 @@
<bean type="com.opensymphony.xwork2.TextProvider" name="struts" class="com.opensymphony.xwork2.TextProviderSupport" scope="default" />
<bean type="org.apache.struts2.components.UrlRenderer" name="struts" class="org.apache.struts2.components.ServletUrlRenderer"/>
<bean type="org.apache.struts2.views.util.UrlHelper" name="struts" class="org.apache.struts2.views.util.DefaultUrlHelper"/>
<bean type="com.opensymphony.xwork2.util.ValueStackFactory" name="struts" class="com.opensymphony.xwork2.ognl.OgnlValueStackFactory" />
<bean type="com.opensymphony.xwork2.util.reflection.ReflectionProvider" name="struts" class="com.opensymphony.xwork2.ognl.OgnlReflectionProvider" />
@@ -31,6 +31,7 @@ import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsTestCase;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.views.util.DefaultUrlHelper;
import org.easymock.IMocksControl;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -89,6 +90,7 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
result.setEncode(false);
result.setPrependServletContext(false);
result.setAnchor("fragment");
result.setUrlHelper(new DefaultUrlHelper());
IMocksControl control = createControl();
ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
@@ -143,6 +145,7 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
result.setEncode(false);
result.setPrependServletContext(false);
result.setAnchor("fragment");
result.setUrlHelper(new DefaultUrlHelper());
IMocksControl control = createControl();
ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
@@ -177,7 +180,7 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
.build();
ObjectFactory factory = container.getInstance(ObjectFactory.class);
ServletActionRedirectResult result = (ServletActionRedirectResult) factory.buildResult(resultConfig, new HashMap());
ServletActionRedirectResult result = (ServletActionRedirectResult) factory.buildResult(resultConfig, new HashMap<String, Object>());
assertNotNull(result);
}
@@ -35,19 +35,24 @@ import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsTestCase;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import static org.easymock.EasyMock.*;
import org.apache.struts2.views.util.DefaultUrlHelper;
import org.easymock.IMocksControl;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static javax.servlet.http.HttpServletResponse.SC_SEE_OTHER;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import static javax.servlet.http.HttpServletResponse.SC_SEE_OTHER;
import static org.easymock.EasyMock.createControl;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
/**
*/
@@ -188,6 +193,7 @@ public class ServletRedirectResultTest extends StrutsTestCase implements StrutsS
result.setEncode(false);
result.setPrependServletContext(false);
result.setAnchor("fragment");
result.setUrlHelper(new DefaultUrlHelper());
IMocksControl control = createControl();
ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
@@ -38,12 +38,13 @@ import java.util.TreeMap;
/**
* Test case for UrlHelper.
* Test case for DefaultUrlHelper.
*
*/
public class UrlHelperTest extends StrutsTestCase {
public class DefaultUrlHelperTest extends StrutsTestCase {
private StubContainer stubContainer;
private DefaultUrlHelper urlHelper;
public void testForceAddSchemeHostAndPort() throws Exception {
String expectedUrl = "http://localhost/contextPath/path1/path2/myAction.action";
@@ -57,7 +58,7 @@ public class UrlHelperTest extends StrutsTestCase {
Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl, expectedUrl);
String result = UrlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse)mockHttpServletResponse.proxy(), null, "http", true, true, true);
String result = urlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), null, "http", true, true, true);
assertEquals(expectedUrl, result);
mockHttpServletRequest.verify();
}
@@ -73,7 +74,7 @@ public class UrlHelperTest extends StrutsTestCase {
Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl, expectedUrl);
String result = UrlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest)mockHttpServletRequest.proxy(), (HttpServletResponse)mockHttpServletResponse.proxy(), null, "http", true, true, false);
String result = urlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), null, "http", true, true, false);
assertEquals(expectedUrl, result);
}
@@ -90,7 +91,7 @@ public class UrlHelperTest extends StrutsTestCase {
Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl, expectedUrl);
String result = UrlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse)mockHttpServletResponse.proxy(), null, "http", true, true, true);
String result = urlHelper.buildUrl("/path1/path2/myAction.action", (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), null, "http", true, true, true);
assertEquals(expectedUrl, result);
mockHttpServletRequest.verify();
}
@@ -105,7 +106,7 @@ public class UrlHelperTest extends StrutsTestCase {
StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue");
UrlHelper.buildParametersString(parameters, url);
urlHelper.buildParametersString(parameters, url);
assertEquals(
expectedUrl, url.toString());
@@ -121,7 +122,7 @@ public class UrlHelperTest extends StrutsTestCase {
StringBuilder url = new StringBuilder("http://localhost:8080/myContext/myPage.jsp?initParam=initValue");
UrlHelper.buildParametersString(parameters, url);
urlHelper.buildParametersString(parameters, url);
assertEquals(
expectedUrl, url.toString());
@@ -140,10 +141,10 @@ public class UrlHelperTest extends StrutsTestCase {
mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl,
expectedUrl);
String result = UrlHelper.buildUrl("/path1/path2/myAction.action",
(HttpServletRequest) mockHttpServletRequest.proxy(),
(HttpServletResponse) mockHttpServletResponse.proxy(), null,
null, true, true, true);
String result = urlHelper.buildUrl("/path1/path2/myAction.action",
(HttpServletRequest) mockHttpServletRequest.proxy(),
(HttpServletResponse) mockHttpServletResponse.proxy(), null,
null, true, true, true);
assertEquals(expectedUrl, result);
mockHttpServletRequest.verify();
}
@@ -158,7 +159,7 @@ public class UrlHelperTest extends StrutsTestCase {
Mock mockHttpServletResponse = new Mock(HttpServletResponse.class);
mockHttpServletResponse.expectAndReturn("encodeURL", expectedUrl, expectedUrl);
String actualUrl = UrlHelper.buildUrl(expectedUrl, (HttpServletRequest) mockHttpServletRequest.proxy(),
String actualUrl = urlHelper.buildUrl(expectedUrl, (HttpServletRequest) mockHttpServletRequest.proxy(),
(HttpServletResponse) mockHttpServletResponse.proxy(), new HashMap());
assertEquals(expectedUrl, actualUrl);
}
@@ -178,7 +179,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", "world");
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params);
assertEquals(expectedString, urlString);
}
@@ -197,7 +198,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", "world");
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, null, true, true, false, false);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, null, true, true, false, false);
assertEquals(expectedString, urlString);
}
@@ -213,7 +214,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", new String[]{"earth", "mars"});
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params);
assertEquals(expectedString, urlString);
}
@@ -238,7 +239,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", new String[]{"earth", "mars"});
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
assertEquals(expectedString, urlString);
}
@@ -263,7 +264,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", new String[]{"earth", "mars"});
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "http", true, true);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "http", true, true);
assertEquals(expectedString, urlString);
}
@@ -292,7 +293,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", new String[]{"earth", "mars"});
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
assertEquals(expectedString, urlString);
}
@@ -321,7 +322,7 @@ public class UrlHelperTest extends StrutsTestCase {
params.put("hello", new String[]{"earth", "mars"});
params.put("foo", "bar");
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "http", true, true);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "http", true, true);
assertEquals(expectedString, urlString);
}
@@ -348,13 +349,13 @@ public class UrlHelperTest extends StrutsTestCase {
String actionName = "promo.html";
Map params = new TreeMap();
String urlString = UrlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
String urlString = urlHelper.buildUrl(actionName, (HttpServletRequest) mockHttpServletRequest.proxy(), (HttpServletResponse) mockHttpServletResponse.proxy(), params, "https", true, true);
assertEquals(expectedString, urlString);
}
public void testParseQuery() throws Exception {
Map result = UrlHelper.parseQueryString("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E");
Map result = urlHelper.parseQueryString("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E");
assertEquals(result.get("aaa"), "aaaval");
assertEquals(result.get("bbb"), "bbbval");
@@ -363,14 +364,14 @@ public class UrlHelperTest extends StrutsTestCase {
}
public void testParseEmptyQuery() throws Exception {
Map result = UrlHelper.parseQueryString("");
Map result = urlHelper.parseQueryString("");
assertNotNull(result);
assertEquals(result.size(), 0);
}
public void testParseNullQuery() throws Exception {
Map result = UrlHelper.parseQueryString(null);
Map result = urlHelper.parseQueryString(null);
assertNotNull(result);
assertEquals(result.size(), 0);
@@ -379,7 +380,7 @@ public class UrlHelperTest extends StrutsTestCase {
public void testTranslateAndEncode() throws Exception {
setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8");
String result = UrlHelper.translateAndEncode("\u65b0\u805e");
String result = urlHelper.translateAndEncode("\u65b0\u805e");
String expectedResult = "%E6%96%B0%E8%81%9E";
assertEquals(result, expectedResult);
@@ -387,7 +388,7 @@ public class UrlHelperTest extends StrutsTestCase {
public void testTranslateAndDecode() throws Exception {
setProp(StrutsConstants.STRUTS_I18N_ENCODING, "UTF-8");
String result = UrlHelper.translateAndDecode("%E6%96%B0%E8%81%9E");
String result = urlHelper.translateAndDecode("%E6%96%B0%E8%81%9E");
String expectedResult = "\u65b0\u805e";
assertEquals(result, expectedResult);
@@ -397,6 +398,7 @@ public class UrlHelperTest extends StrutsTestCase {
super.setUp();
stubContainer = new StubContainer(container);
ActionContext.getContext().put(ActionContext.CONTAINER, stubContainer);
urlHelper = new DefaultUrlHelper();
}
private void setProp(String key, String val) {
@@ -48,13 +48,14 @@ public abstract class JSPRuntime {
public static void handle(String location, boolean flush) throws Exception {
final HttpServletResponse response = ServletActionContext.getResponse();
final HttpServletRequest request = ServletActionContext.getRequest();
final UrlHelper urlHelper = ServletActionContext.getContext().getInstance(UrlHelper.class);
int i = location.indexOf("?");
if (i > 0) {
//extract params from the url and add them to the request
Map parameters = ActionContext.getContext().getParameters();
Map<String, Object> parameters = ActionContext.getContext().getParameters();
String query = location.substring(i + 1);
Map queryParams = UrlHelper.parseQueryString(query, true);
Map<String, Object> queryParams = urlHelper.parseQueryString(query, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
location = location.substring(0, i);
@@ -28,6 +28,8 @@ import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;
import junit.framework.TestCase;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.views.util.DefaultUrlHelper;
import org.apache.struts2.views.util.UrlHelper;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -266,6 +268,10 @@ public class EmbeddedJSPResultTest extends TestCase {
//mock container
Container container = EasyMock.createNiceMock(Container.class);
EasyMock.expect(container.getInstance(XWorkConverter.class)).andReturn(converter).anyTimes();
UrlHelper urlHelper = new DefaultUrlHelper();
EasyMock.expect(container.getInstance(UrlHelper.class)).andReturn(urlHelper).anyTimes();
EasyMock.replay(container);
stackContext.put(ActionContext.CONTAINER, container);
actionContext.setContainer(container);
@@ -28,15 +28,16 @@ import java.util.Map;
import javax.portlet.PortletMode;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.portlet.PortletActionConstants;
import org.apache.struts2.views.util.UrlHelper;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.struts2.views.util.UrlHelper;
/**
*
@@ -133,14 +134,12 @@ public class PortletActionRedirectResult extends PortletResult {
public static final String DEFAULT_PARAM = "actionName";
protected String actionName;
protected String namespace;
protected String method;
private Map<String, String> requestParameters = new LinkedHashMap<String, String>();
private Map<String, Object> requestParameters = new LinkedHashMap<String, Object>();
private ActionMapper actionMapper;
private UrlHelper urlHelper;
public PortletActionRedirectResult() {
super();
@@ -161,23 +160,27 @@ public class PortletActionRedirectResult extends PortletResult {
this.method = method;
}
protected List<String> prohibitedResultParam = Arrays.asList(new String[] { DEFAULT_PARAM, "namespace", "method",
"encode", "parse", "location", "prependServletContext" });
protected List<String> prohibitedResultParam = Arrays.asList(DEFAULT_PARAM, "namespace", "method", "encode", "parse",
"location", "prependServletContext");
@Inject
public void setActionMapper(ActionMapper actionMapper) {
this.actionMapper = actionMapper;
}
/**
@Inject
public void setUrlHelper(UrlHelper urlHelper) {
this.urlHelper = urlHelper;
}
/**
* @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
*/
public void execute(ActionInvocation invocation) throws Exception {
actionName = conditionalParse(actionName, invocation);
String portletNamespace = (String)invocation.getInvocationContext().get(PortletActionConstants.PORTLET_NAMESPACE);
if (portletMode != null) {
Map<PortletMode, String> namespaceMap = (Map<PortletMode, String>) invocation.getInvocationContext().get(
PortletActionConstants.MODE_NAMESPACE_MAP);
Map<PortletMode, String> namespaceMap = getNamespaceMap(invocation);
namespace = namespaceMap.get(portletMode);
}
if (namespace == null) {
@@ -194,30 +197,32 @@ public class PortletActionRedirectResult extends PortletResult {
String resultCode = invocation.getResultCode();
if (resultCode != null) {
ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(resultCode);
Map resultConfigParams = resultConfig.getParams();
for (Iterator i = resultConfigParams.entrySet().iterator(); i.hasNext();) {
Map.Entry e = (Map.Entry) i.next();
if (!prohibitedResultParam.contains(e.getKey())) {
requestParameters.put(e.getKey().toString(), e.getValue() == null ? "" : conditionalParse(e
.getValue().toString(), invocation));
}
}
Map<String, String> resultConfigParams = resultConfig.getParams();
for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
if (!prohibitedResultParam.contains(e.getKey())) {
requestParameters.put(e.getKey(), e.getValue() == null ? "" : conditionalParse(e.getValue(), invocation));
}
}
}
StringBuilder tmpLocation = new StringBuilder(actionMapper.getUriFromActionMapping(new ActionMapping(actionName,
(portletNamespace == null ? namespace : portletNamespace + namespace), method, null)));
UrlHelper.buildParametersString(requestParameters, tmpLocation, "&");
urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
setLocation(tmpLocation.toString());
super.execute(invocation);
}
/**
@SuppressWarnings("unchecked")
private Map<PortletMode, String> getNamespaceMap(ActionInvocation invocation) {
return (Map<PortletMode, String>) invocation.getInvocationContext().get(PortletActionConstants.MODE_NAMESPACE_MAP);
}
/**
* Sets the action name
*
* @param actionName
* The name
* @param actionName The name
*/
public void setActionName(String actionName) {
this.actionName = actionName;
@@ -226,8 +231,7 @@ public class PortletActionRedirectResult extends PortletResult {
/**
* Sets the namespace
*
* @param namespace
* The namespace
* @param namespace The namespace
*/
public void setNamespace(String namespace) {
this.namespace = namespace;
@@ -236,8 +240,7 @@ public class PortletActionRedirectResult extends PortletResult {
/**
* Sets the method
*
* @param method
* The method
* @param method The method
*/
public void setMethod(String method) {
this.method = method;
@@ -246,10 +249,8 @@ public class PortletActionRedirectResult extends PortletResult {
/**
* Adds a request parameter to be added to the redirect url
*
* @param key
* The parameter name
* @param value
* The parameter value
* @param key The parameter name
* @param value The parameter value
*/
public PortletActionRedirectResult addParameter(String key, Object value) {
requestParameters.put(key, String.valueOf(value));