001: package com.meterware.httpunit;
002:
003: /********************************************************************************************************************
004: * $Id: HttpWebResponse.java,v 1.33 2004/08/10 20:28:52 russgold Exp $
005: *
006: * Copyright (c) 2000-2004, 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 java.io.BufferedInputStream;
024: import java.io.IOException;
025: import java.io.InputStream;
026:
027: import java.net.HttpURLConnection;
028: import java.net.URL;
029: import java.net.URLConnection;
030: import java.net.UnknownHostException;
031:
032: import java.util.Enumeration;
033: import java.util.Hashtable;
034: import java.util.StringTokenizer;
035: import java.util.Vector;
036:
037: /**
038: * A response from a web server to an Http request.
039: *
040: * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
041: **/
042: class HttpWebResponse extends WebResponse {
043:
044: private String _referer;
045:
046: /**
047: * Constructs a response object from an input stream.
048: * @param frame the target window or frame to which the request should be directed
049: * @param url the url from which the response was received
050: * @param connection the URL connection from which the response can be read
051: **/
052: HttpWebResponse(WebConversation client, FrameSelector frame,
053: URL url, URLConnection connection,
054: boolean throwExceptionOnError) throws IOException {
055: super (client, frame, url);
056: if (HttpUnitOptions.isLoggingHttpHeaders())
057: System.out.println("\nReceived from " + url);
058: readHeaders(connection);
059:
060: /** make sure that any IO exception for HTML received page happens here, not later. **/
061: if (_responseCode < HttpURLConnection.HTTP_BAD_REQUEST
062: || !throwExceptionOnError) {
063: defineRawInputStream(new BufferedInputStream(
064: getInputStream(connection)));
065: if (getContentType().startsWith("text"))
066: loadResponseText();
067: }
068: }
069:
070: HttpWebResponse(WebConversation client, FrameSelector frame,
071: WebRequest request, URLConnection connection,
072: boolean throwExceptionOnError) throws IOException {
073: this (client, frame, request.getURL(), connection,
074: throwExceptionOnError);
075: _referer = request.getReferer();
076: }
077:
078: private InputStream getInputStream(URLConnection connection)
079: throws IOException {
080: return isResponseOnErrorStream(connection) ? ((HttpURLConnection) connection)
081: .getErrorStream()
082: : connection.getInputStream();
083: }
084:
085: private boolean isResponseOnErrorStream(URLConnection connection) {
086: return _responseCode >= HttpURLConnection.HTTP_BAD_REQUEST
087: && ((HttpURLConnection) connection).getErrorStream() != null;
088: }
089:
090: /**
091: * Returns the response code associated with this response.
092: **/
093: public int getResponseCode() {
094: return _responseCode;
095: }
096:
097: /**
098: * Returns the response message associated with this response.
099: **/
100: public String getResponseMessage() {
101: return _responseMessage;
102: }
103:
104: public String[] getHeaderFieldNames() {
105: Vector names = new Vector();
106: for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
107: names.addElement(e.nextElement());
108: }
109: String[] result = new String[names.size()];
110: names.copyInto(result);
111: return result;
112: }
113:
114: /**
115: * Returns the value for the specified header field. If no such field is defined, will return null.
116: **/
117: public String getHeaderField(String fieldName) {
118: String[] fields = (String[]) _headers.get(fieldName
119: .toUpperCase());
120: return fields == null ? null : fields[0];
121: }
122:
123: public String[] getHeaderFields(String fieldName) {
124: String[] fields = (String[]) _headers.get(fieldName
125: .toUpperCase());
126: return fields == null ? new String[0] : fields;
127: }
128:
129: public String toString() {
130: StringBuffer sb = new StringBuffer("HttpWebResponse [url=");
131: sb.append(getURL()).append("; headers=");
132: for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
133: Object key = e.nextElement();
134: String[] values = (String[]) _headers.get(key);
135: for (int i = 0; i < values.length; i++) {
136: sb.append("\n ").append(key).append(": ").append(
137: values[i]);
138: }
139: }
140: sb.append(" ]");
141: return sb.toString();
142: }
143:
144: String getReferer() {
145: return _referer;
146: }
147:
148: //------------------------------------- private members -------------------------------------
149:
150: private final static String FILE_ENCODING = System
151: .getProperty("file.encoding");
152:
153: private int _responseCode = HttpURLConnection.HTTP_OK;
154: private String _responseMessage = "OK";
155:
156: private Hashtable _headers = new Hashtable();
157:
158: private void readResponseHeader(HttpURLConnection connection)
159: throws IOException {
160: if (!needStatusWorkaround()) {
161: _responseCode = connection.getResponseCode();
162: _responseMessage = connection.getResponseMessage();
163: } else {
164: if (connection.getHeaderField(0) == null)
165: throw new UnknownHostException(connection.getURL()
166: .toExternalForm());
167:
168: StringTokenizer st = new StringTokenizer(connection
169: .getHeaderField(0));
170: st.nextToken();
171: if (!st.hasMoreTokens()) {
172: _responseCode = HttpURLConnection.HTTP_OK;
173: _responseMessage = "OK";
174: } else
175: try {
176: _responseCode = Integer.parseInt(st.nextToken());
177: _responseMessage = getRemainingTokens(st);
178: } catch (NumberFormatException e) {
179: _responseCode = HttpURLConnection.HTTP_INTERNAL_ERROR;
180: _responseMessage = "Cannot parse response header";
181: }
182: }
183: }
184:
185: private boolean needStatusWorkaround() {
186: final String jdkVersion = System.getProperty("java.version");
187: return jdkVersion.startsWith("1.2")
188: || jdkVersion.startsWith("1.3");
189: }
190:
191: private String getRemainingTokens(StringTokenizer st) {
192: StringBuffer messageBuffer = new StringBuffer(st
193: .hasMoreTokens() ? st.nextToken() : "");
194: while (st.hasMoreTokens()) {
195: messageBuffer.append(' ').append(st.nextToken());
196: }
197: return messageBuffer.toString();
198: }
199:
200: private void readHeaders(URLConnection connection)
201: throws IOException {
202: loadHeaders(connection);
203: if (connection instanceof HttpURLConnection) {
204: readResponseHeader((HttpURLConnection) connection);
205: } else {
206: _responseCode = HttpURLConnection.HTTP_OK;
207: _responseMessage = "OK";
208: if (connection.getContentType().startsWith("text")) {
209: setContentTypeHeader(connection.getContentType()
210: + "; charset=" + FILE_ENCODING);
211: }
212: }
213: }
214:
215: private void loadHeaders(URLConnection connection) {
216: if (HttpUnitOptions.isLoggingHttpHeaders()) {
217: System.out.println("Header:: "
218: + connection.getHeaderField(0));
219: }
220: for (int i = 1; true; i++) {
221: String headerFieldKey = connection.getHeaderFieldKey(i);
222: String headerField = connection.getHeaderField(i);
223: if (headerFieldKey == null || headerField == null)
224: break;
225: if (HttpUnitOptions.isLoggingHttpHeaders()) {
226: System.out.println("Header:: " + headerFieldKey + ": "
227: + headerField);
228: }
229: addHeader(headerFieldKey.toUpperCase(), headerField);
230: }
231:
232: if (connection.getContentType() != null) {
233: setContentTypeHeader(connection.getContentType());
234: }
235: }
236:
237: private void addHeader(String key, String field) {
238: _headers.put(key, HttpUnitUtils.withNewValue(
239: (String[]) _headers.get(key), field));
240: }
241:
242: }
|