// 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; } }