001: package com.meterware.servletunit;
002:
003: /********************************************************************************************************************
004: * $Id: RequestContext.java,v 1.6 2004/10/28 23:50:46 russgold Exp $
005: *
006: * Copyright (c) 2003, Russell Gold
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
009: * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
011: * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included in all copies or substantial portions
014: * of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
017: * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
019: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020: * DEALINGS IN THE SOFTWARE.
021: *
022: *******************************************************************************************************************/
023: import com.meterware.httpunit.HttpUnitUtils;
024:
025: import java.util.*;
026: import java.net.URL;
027: import java.io.UnsupportedEncodingException;
028:
029: import javax.servlet.http.HttpServletRequest;
030:
031: /**
032: *
033: * @author <a href="russgold@httpunit.org">Russell Gold</a>
034: **/
035: class RequestContext {
036:
037: private Hashtable _parameters = new Hashtable();
038: private Hashtable _visibleParameters;
039: private HttpServletRequest _parentRequest;
040: private URL _url;
041: private byte[] _messageBody;
042: private String _messageEncoding;
043:
044: RequestContext(URL url) {
045: _url = url;
046: String file = _url.getFile();
047: if (file.indexOf('?') >= 0)
048: loadParameters(file.substring(file.indexOf('?') + 1) /* urlEncoded */);
049: }
050:
051: void setParentRequest(HttpServletRequest parentRequest) {
052: _parentRequest = parentRequest;
053: _visibleParameters = null;
054: }
055:
056: String getRequestURI() {
057: return _url.getPath();
058: }
059:
060: String getParameter(String name) {
061: String[] parameters = (String[]) getParameters().get(name);
062: return parameters == null ? null : parameters[0];
063: }
064:
065: Enumeration getParameterNames() {
066: return getParameters().keys();
067: }
068:
069: Map getParameterMap() {
070: return (Map) getParameters().clone();
071: }
072:
073: String[] getParameterValues(String name) {
074: return (String[]) getParameters().get(name);
075: }
076:
077: final static private int STATE_INITIAL = 0;
078: final static private int STATE_HAVE_NAME = 1;
079: final static private int STATE_HAVE_EQUALS = 2;
080: final static private int STATE_HAVE_VALUE = 3;
081:
082: /**
083: * This method employs a state machine to parse a parameter query string.
084: * The transition rules are as follows:
085: * State \ text '=' '&'
086: * initial: have_name - initial
087: * have_name: - have_equals initial
088: * have_equals: have_value - initial
089: * have_value: - initial initial
090: * actions occur on the following transitions:
091: * initial -> have_name: save token as name
092: * have_equals -> initial: record parameter with null value
093: * have_value -> initial: record parameter with value
094: **/
095: void loadParameters(String queryString) {
096: if (queryString.length() == 0)
097: return;
098: StringTokenizer st = new StringTokenizer(queryString, "&=", /* return tokens */
099: true);
100: int state = STATE_INITIAL;
101: String name = null;
102: String value = null;
103:
104: while (st.hasMoreTokens()) {
105: String token = st.nextToken();
106: if (token.equals("&")) {
107: state = STATE_INITIAL;
108: if (name != null && value != null)
109: addParameter(name, value);
110: name = value = null;
111: } else if (token.equals("=")) {
112: if (state == STATE_HAVE_NAME) {
113: state = STATE_HAVE_EQUALS;
114: } else if (state == STATE_HAVE_VALUE) {
115: state = STATE_INITIAL;
116: }
117: } else if (state == STATE_INITIAL) {
118: name = HttpUnitUtils
119: .decode(token, getMessageEncoding());
120: value = "";
121: state = STATE_HAVE_NAME;
122: } else {
123: value = HttpUnitUtils.decode(token,
124: getMessageEncoding());
125: state = STATE_HAVE_VALUE;
126: }
127: }
128: if (name != null && value != null)
129: addParameter(name, value);
130: }
131:
132: private void addParameter(String name, String encodedValue) {
133: String[] values = (String[]) _parameters.get(name);
134: _visibleParameters = null;
135: if (values == null) {
136: _parameters.put(name, new String[] { encodedValue });
137: } else {
138: _parameters.put(name, extendedArray(values, encodedValue));
139: }
140: }
141:
142: private static String[] extendedArray(String[] baseArray,
143: String newValue) {
144: String[] result = new String[baseArray.length + 1];
145: System.arraycopy(baseArray, 0, result, 0, baseArray.length);
146: result[baseArray.length] = newValue;
147: return result;
148: }
149:
150: private Hashtable getParameters() {
151: if (_messageBody != null) {
152: loadParameters(getMessageBodyAsString());
153: _messageBody = null;
154: }
155: if (_visibleParameters == null) {
156: if (_parentRequest == null) {
157: _visibleParameters = _parameters;
158: } else {
159: _visibleParameters = new Hashtable();
160: final Map parameterMap = _parentRequest
161: .getParameterMap();
162: for (Iterator i = parameterMap.keySet().iterator(); i
163: .hasNext();) {
164: Object key = i.next();
165: _visibleParameters.put(key, parameterMap.get(key));
166: }
167: for (Enumeration e = _parameters.keys(); e
168: .hasMoreElements();) {
169: Object key = e.nextElement();
170: _visibleParameters.put(key, _parameters.get(key));
171: }
172: }
173: }
174: return _visibleParameters;
175: }
176:
177: private String getMessageBodyAsString() {
178: try {
179: return new String(_messageBody, "iso-8859-1");
180: } catch (UnsupportedEncodingException e) {
181: return "";
182: }
183: }
184:
185: void setMessageBody(byte[] bytes) {
186: _messageBody = bytes;
187: }
188:
189: public void setMessageEncoding(String messageEncoding) {
190: _messageEncoding = messageEncoding;
191: }
192:
193: private String getMessageEncoding() {
194: return _messageEncoding == null ? HttpUnitUtils.DEFAULT_CHARACTER_SET
195: : _messageEncoding;
196: }
197:
198: }
|