Revision: 643
http://stripes.svn.sourceforge.net/stripes/?rev=643&view=rev
Author: bengunter
Date: 2007-12-04 08:56:07 -0800 (Tue, 04 Dec 2007)
Log Message:
-----------
Fixed STS-435: Change clean URLs not to rely on internal forwards. The fix for
STS-448 broke clean URLs on internal forwards because the code depended on
layers of StripesRequestWrappers. That is no longer the case. When a request is
forwarded through StripesFilter, the filter notifies the lone
StripesRequestWrapper, which merges any new URI parameters into the ones from
the previous request.
Modified Paths:
--------------
trunk/stripes/src/net/sourceforge/stripes/controller/StripesFilter.java
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java
Modified:
trunk/stripes/src/net/sourceforge/stripes/controller/StripesFilter.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/controller/StripesFilter.java
2007-12-04 05:24:15 UTC (rev 642)
+++ trunk/stripes/src/net/sourceforge/stripes/controller/StripesFilter.java
2007-12-04 16:56:07 UTC (rev 643)
@@ -30,6 +30,7 @@
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Locale;
@@ -197,6 +198,11 @@
}
httpRequest = request;
}
+ else {
+ // process URI parameters on subsequent invocations
+
StripesRequestWrapper.findStripesWrapper(httpRequest).pushUriParameters(
+ (HttpServletRequestWrapper) httpRequest);
+ }
// Execute the rest of the chain
flashInbound(httpRequest);
@@ -214,6 +220,10 @@
// Once the request is processed, take the Configuration back
out of thread local
StripesFilter.configurationStash.remove();
}
+ else {
+ // restore URI parameters to their previous state
+
StripesRequestWrapper.findStripesWrapper(httpRequest).popUriParameters();
+ }
}
}
Modified:
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java
2007-12-04 05:24:15 UTC (rev 642)
+++
trunk/stripes/src/net/sourceforge/stripes/controller/StripesRequestWrapper.java
2007-12-04 16:56:07 UTC (rev 643)
@@ -20,13 +20,13 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.Stack;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
@@ -40,7 +40,7 @@
* HttpServletRequestWrapper that is used to make the file upload
functionality transparent.
* Every request handled by Stripes is wrapped. Those containing multipart
form file uploads
* are parsed and treated differently, while normal requests are silently
wrapped and all calls
- * are delgated to the real request.
+ * are delegated to the real request.
*
* @author Tim Fennell
*/
@@ -52,11 +52,8 @@
/** The Locale that is going to be used to process the request. */
private Locale locale;
- /** Flag that indicates if parameters have been initialized. */
- private boolean parametersInitialized;
-
/** Local copy of the parameter map, into which URI-embedded parameters
will be merged. */
- private Map<String, String[]> parameterMap;
+ private MergedParameterMap parameterMap;
/**
* Looks for the StripesRequesetWrapper for the specific request and
returns it. This is done
@@ -111,7 +108,7 @@
/**
* Responsible for constructing the MultipartWrapper object and setting it
on to
- * the instnace variable 'multipart'.
+ * the instance variable 'multipart'.
*
* @param request the HttpServletRequest to wrap
* this is not a file size limit, but a post size limit.
@@ -177,69 +174,30 @@
@SuppressWarnings("unchecked")
@Override
public Map<String, String[]> getParameterMap() {
- // lazy initialization
- if (this.parametersInitialized) {
- if (this.parameterMap == null)
- return super.getParameterMap();
+ if (this.parameterMap == null) {
+ if (isMultipart())
+ this.parameterMap = new MergedParameterMap(this,
this.multipart);
else
- return this.parameterMap;
+ this.parameterMap = new MergedParameterMap(this);
}
- if (isMultipart()) {
- Map<String, String[]> params = new HashMap<String, String[]>();
- Enumeration names = this.multipart.getParameterNames();
+ return this.parameterMap;
+ }
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- params.put(name, this.multipart.getParameterValues(name));
- }
-
- this.parameterMap = mergeURIParameters(params);
- }
- else {
- Map<String, String[]> params = mergeURIParameters(null);
- if (params != null) {
- this.parameterMap = new MergedParameterMap(this, params);
- }
- }
-
- this.parametersInitialized = true;
- return getParameterMap();
+ /**
+ * Extract new URI parameters from the URI of the given [EMAIL PROTECTED]
request} and merge them with the
+ * previous URI parameters.
+ */
+ public void pushUriParameters(HttpServletRequestWrapper request) {
+ this.parameterMap.pushUriParameters(request);
}
- /** Merges URI-embedded parameters into an existing parameter map. */
- protected Map<String, String[]> mergeURIParameters(Map<String, String[]>
params) {
- UrlBinding binding = UrlBindingFactory.getInstance().getBinding(this);
- if (binding != null && binding.getParameters().size() > 0) {
- for (UrlBindingParameter p : binding.getParameters()) {
- String name = p.getName();
- if (name != null) {
- String value = p.getValue();
- if (UrlBindingParameter.PARAMETER_NAME_EVENT.equals(name))
{
- name = value;
- value = "";
- }
- if (name != null && value != null) {
- if (params == null) {
- params = new LinkedHashMap<String, String[]>();
- }
- String[] values = params.get(name);
- if (values == null) {
- values = new String[] { value };
- }
- else {
- String[] tmp = new String[values.length + 1];
- System.arraycopy(values, 0, tmp, 0, values.length);
- tmp[tmp.length - 1] = value;
- values = tmp;
- }
- params.put(name, values);
- }
- }
- }
- }
-
- return params;
+ /**
+ * Restore the URI parameters to the state they were in before the
previous call to
+ * [EMAIL PROTECTED] #pushUriParameters(HttpServletRequest)}.
+ */
+ public void popUriParameters() {
+ this.parameterMap.popUriParameters();
}
/**
@@ -299,6 +257,12 @@
}
}
+/**
+ * A [EMAIL PROTECTED] Map} implementation that is used by [EMAIL PROTECTED]
StripesRequestWrapper} to merge URI parameter
+ * values with request parameter values on the fly.
+ *
+ * @author Ben Gunter
+ */
class MergedParameterMap implements Map<String, String[]> {
protected class Entry implements Map.Entry<String, String[]> {
private String key;
@@ -336,14 +300,48 @@
}
}
- private StripesRequestWrapper request;
+ private HttpServletRequestWrapper request;
+ private Stack<HttpServletRequestWrapper> requestStack;
private Map<String, String[]> uriParams;
+ private Stack<Map<String, String[]>> uriParamStack;
- protected MergedParameterMap(StripesRequestWrapper request, Map<String,
String[]> uriParams) {
+ protected MergedParameterMap(StripesRequestWrapper request) {
this.request = request;
- this.uriParams = uriParams;
+ this.uriParams = getUriParameters(request);
+ if (this.uriParams == null) {
+ this.uriParams = Collections.emptyMap();
+ }
}
+ protected MergedParameterMap(StripesRequestWrapper request,
MultipartWrapper multipart) {
+ this.request = request;
+
+ // extract URI parameters
+ Map<String, String[]> uriParams = getUriParameters(request);
+
+ /*
+ * Special handling of parameters if this is a multipart request. The
parameters will be
+ * pulled from the MultipartWrapper and merged in with the URI
parameters.
+ */
+ Map<String, String[]> multipartParams = null;
+ Enumeration<?> names = multipart.getParameterNames();
+ if (names != null && names.hasMoreElements()) {
+ multipartParams = new LinkedHashMap<String, String[]>();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ multipartParams.put(name, multipart.getParameterValues(name));
+ }
+ }
+
+ // if no multipart params and no URI params then use empty map
+ if (uriParams == null && multipartParams == null) {
+ this.uriParams = Collections.emptyMap();
+ }
+ else {
+ this.uriParams = mergeParameters(uriParams, multipartParams);
+ }
+ }
+
public void clear() {
throw new UnsupportedOperationException();
}
@@ -422,18 +420,110 @@
/** Get the parameter map from the request that is wrapped by the [EMAIL
PROTECTED] StripesRequestWrapper}. */
@SuppressWarnings("unchecked")
protected Map<String, String[]> getParameterMap() {
- return request.getRequest().getParameterMap();
+ return request == null ? Collections.emptyMap() :
request.getRequest().getParameterMap();
}
/**
- * Merges request parameter values from the original request with the
parameters that are
+ * Extract new URI parameters from the URI of the given [EMAIL PROTECTED]
request} and merge them with the
+ * previous URI parameters.
+ */
+ public void pushUriParameters(HttpServletRequestWrapper request) {
+ if (this.uriParamStack == null) {
+ this.uriParamStack = new Stack<Map<String, String[]>>();
+ this.requestStack = new Stack<HttpServletRequestWrapper>();
+ }
+ Map<String, String[]> map = getUriParameters(request);
+ this.uriParamStack.push(this.uriParams);
+ this.uriParams = mergeParameters(this.uriParams, map);
+ this.requestStack.push(request);
+ this.request = request;
+ }
+
+ /**
+ * Restore the URI parameters to the state they were in before the
previous call to
+ * [EMAIL PROTECTED] #pushUriParameters(HttpServletRequest)}.
+ */
+ public void popUriParameters() {
+ if (this.uriParamStack.isEmpty())
+ this.uriParams = null;
+ else
+ this.uriParams = this.uriParamStack.pop();
+ }
+
+ /**
+ * Extract any parameters embedded in the URI of the given [EMAIL
PROTECTED] request} and return them in a
+ * [EMAIL PROTECTED] Map}. If no parameters are present in the URI, then
return null.
+ */
+ public static Map<String, String[]> getUriParameters(HttpServletRequest
request) {
+ Map<String, String[]> params = null;
+ UrlBinding binding =
UrlBindingFactory.getInstance().getBinding(request);
+ if (binding != null && binding.getParameters().size() > 0) {
+ for (UrlBindingParameter p : binding.getParameters()) {
+ String name = p.getName();
+ if (name != null) {
+ String value = p.getValue();
+ if (UrlBindingParameter.PARAMETER_NAME_EVENT.equals(name))
{
+ name = value;
+ value = "";
+ }
+ if (name != null && value != null) {
+ if (params == null) {
+ params = new LinkedHashMap<String, String[]>();
+ }
+ String[] values = params.get(name);
+ if (values == null) {
+ values = new String[] { value };
+ }
+ else {
+ String[] tmp = new String[values.length + 1];
+ System.arraycopy(values, 0, tmp, 0, values.length);
+ tmp[tmp.length - 1] = value;
+ values = tmp;
+ }
+ params.put(name, values);
+ }
+ }
+ }
+ }
+
+ return params;
+ }
+
+ /** Merge the values from [EMAIL PROTECTED] source} into [EMAIL PROTECTED]
target}. */
+ public static Map<String, String[]> mergeParameters(Map<String, String[]>
target,
+ Map<String, String[]> source) {
+ // target must not be null and we must not modify source
+ if (target == null)
+ target = new LinkedHashMap<String, String[]>();
+
+ // nothing to do if source is null or empty
+ if (source == null || source.isEmpty())
+ return target;
+
+ // merge the values from source that already exist in target
+ for (Map.Entry<String, String[]> entry : target.entrySet()) {
+ entry.setValue(mergeParameters(entry.getValue(),
source.get(entry.getKey())));
+ }
+
+ // copy the values from source that do not exist in target
+ for (Map.Entry<String, String[]> entry : source.entrySet()) {
+ if (!target.containsKey(entry.getKey())) {
+ target.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ return target;
+ }
+
+ /**
+ * Merge request parameter values from the original request with the
parameters that are
* embedded in the URI. Either or both arguments may be empty or null.
*
* @param requestParams the parameters from the original request
* @param uriParams parameters extracted from the URI
* @return the merged parameter values
*/
- protected String[] mergeParameters(String[] requestParams, String[]
uriParams) {
+ public static String[] mergeParameters(String[] requestParams, String[]
uriParams) {
if (requestParams == null || requestParams.length == 0) {
if (uriParams == null || uriParams.length == 0)
return null;
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development