// fgiust
// patched in order to get encoding parsed correctly. setEncoding() was called after the parsing of parameters,
// added a costructor that takes an additiona encoding parameter, set by ServletUnitHttpRequest
package com.meterware.servletunit;
/********************************************************************************************************************
* $Id: RequestContext.java,v 1.6 2004/10/28 23:50:46 russgold Exp $
*
* Copyright (c) 2003, Russell Gold
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*******************************************************************************************************************/
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import com.meterware.httpunit.HttpUnitUtils;
/**
* @author <a href="russgold@httpunit.org">Russell Gold</a>
*/
class RequestContext
{
private Hashtable<Object, String[]> _parameters = new Hashtable<Object, String[]>();
private Hashtable<Object, String[]> _visibleParameters;
private HttpServletRequest _parentRequest;
private URL _url;
private byte[] _messageBody;
private String _messageEncoding;
RequestContext(URL url)
{
this(url, null);
}
RequestContext(URL url, String messageEncoding)
{
_messageEncoding = messageEncoding;
_url = url;
String file = _url.getFile();
if (file.indexOf('?') >= 0)
loadParameters(file.substring(file.indexOf('?') + 1) /* urlEncoded */);
}
void setParentRequest(HttpServletRequest parentRequest)
{
_parentRequest = parentRequest;
_visibleParameters = null;
}
String getRequestURI()
{
return _url.getPath();
}
String getParameter(String name)
{
String[] parameters = getParameters().get(name);
return parameters == null ? null : parameters[0];
}
Enumeration<Object> getParameterNames()
{
return getParameters().keys();
}
Map<Object, String[]> getParameterMap()
{
return (Map<Object, String[]>) getParameters().clone();
}
String[] getParameterValues(String name)
{
return getParameters().get(name);
}
final static private int STATE_INITIAL = 0;
final static private int STATE_HAVE_NAME = 1;
final static private int STATE_HAVE_EQUALS = 2;
final static private int STATE_HAVE_VALUE = 3;
/**
* This method employs a state machine to parse a parameter query string. The transition rules are as follows: State
* \ text '=' '&' initial: have_name - initial have_name: - have_equals initial have_equals: have_value - initial
* have_value: - initial initial actions occur on the following transitions: initial -> have_name: save token as
* name have_equals -> initial: record parameter with null value have_value -> initial: record parameter with value
*/
void loadParameters(String queryString)
{
if (queryString.length() == 0)
return;
StringTokenizer st = new StringTokenizer(queryString, "&=", /* return tokens */true);
int state = STATE_INITIAL;
String name = null;
String value = null;
while (st.hasMoreTokens())
{
String token = st.nextToken();
if (token.equals("&"))
{
state = STATE_INITIAL;
if (name != null && value != null)
addParameter(name, value);
name = value = null;
}
else if (token.equals("="))
{
if (state == STATE_HAVE_NAME)
{
state = STATE_HAVE_EQUALS;
}
else if (state == STATE_HAVE_VALUE)
{
state = STATE_INITIAL;
}
}
else if (state == STATE_INITIAL)
{
name = HttpUnitUtils.decode(token, getMessageEncoding());
value = "";
state = STATE_HAVE_NAME;
}
else
{
value = HttpUnitUtils.decode(token, getMessageEncoding());
state = STATE_HAVE_VALUE;
}
}
if (name != null && value != null)
addParameter(name, value);
}
private void addParameter(String name, String encodedValue)
{
String[] values = _parameters.get(name);
_visibleParameters = null;
if (values == null)
{
_parameters.put(name, new String[]{encodedValue});
}
else
{
_parameters.put(name, extendedArray(values, encodedValue));
}
}
private static String[] extendedArray(String[] baseArray, String newValue)
{
String[] result = new String[baseArray.length + 1];
System.arraycopy(baseArray, 0, result, 0, baseArray.length);
result[baseArray.length] = newValue;
return result;
}
private Hashtable<Object, String[]> getParameters()
{
if (_messageBody != null)
{
loadParameters(getMessageBodyAsString());
_messageBody = null;
}
if (_visibleParameters == null)
{
if (_parentRequest == null)
{
_visibleParameters = _parameters;
}
else
{
_visibleParameters = new Hashtable<Object, String[]>();
final Map<Object, String[]> parameterMap = _parentRequest.getParameterMap();
for (Iterator<Object> i = parameterMap.keySet().iterator(); i.hasNext();)
{
Object key = i.next();
_visibleParameters.put(key, parameterMap.get(key));
}
for (Enumeration<Object> e = _parameters.keys(); e.hasMoreElements();)
{
Object key = e.nextElement();
_visibleParameters.put(key, _parameters.get(key));
}
}
}
return _visibleParameters;
}
private String getMessageBodyAsString()
{
try
{
return new String(_messageBody, "iso-8859-1");
}
catch (UnsupportedEncodingException e)
{
return "";
}
}
void setMessageBody(byte[] bytes)
{
_messageBody = bytes;
}
public void setMessageEncoding(String messageEncoding)
{
_messageEncoding = messageEncoding;
}
private String getMessageEncoding()
{
return _messageEncoding == null ? HttpUnitUtils.DEFAULT_CHARACTER_SET : _messageEncoding;
}
}