001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.http;
004:
005: import java.io.*;
006: import java.util.*;
007: import java.util.regex.*;
008: import java.net.Socket;
009: import fitnesse.util.StreamReader;
010:
011: public class ResponseParser {
012: private int status;
013:
014: private String body;
015:
016: private HashMap headers = new HashMap();
017:
018: private StreamReader input;
019:
020: private static final Pattern statusLinePattern = Pattern
021: .compile("HTTP/\\d.\\d (\\d\\d\\d) ");
022:
023: private static final Pattern headerPattern = Pattern
024: .compile("([^:]*): (.*)");
025:
026: public ResponseParser(InputStream input) throws Exception {
027: this .input = new StreamReader(input);
028: parseStatusLine();
029: parseHeaders();
030: if (isChuncked()) {
031: parseChunks();
032: parseHeaders();
033: } else
034: parseBody();
035: }
036:
037: private boolean isChuncked() {
038: String encoding = getHeader("Transfer-Encoding");
039: return encoding != null
040: && "chunked".equals(encoding.toLowerCase());
041: }
042:
043: private void parseStatusLine() throws Exception {
044: String statusLine = input.readLine();
045: Matcher match = statusLinePattern.matcher(statusLine);
046: if (match.find()) {
047: String status = match.group(1);
048: this .status = Integer.parseInt(status);
049: } else
050: throw new Exception("Could not parse Response");
051: }
052:
053: private void parseHeaders() throws Exception {
054: String line = input.readLine();
055: while (!"".equals(line)) {
056: Matcher match = headerPattern.matcher(line);
057: if (match.find()) {
058: String key = match.group(1);
059: String value = match.group(2);
060: headers.put(key, value);
061: }
062: line = input.readLine();
063: }
064: }
065:
066: private void parseBody() throws Exception {
067: String lengthHeader = "Content-Length";
068: if (hasHeader(lengthHeader)) {
069: int bytesToRead = Integer.parseInt(getHeader(lengthHeader));
070: body = input.read(bytesToRead);
071: }
072: }
073:
074: private void parseChunks() throws Exception {
075: StringBuffer bodyBuffer = new StringBuffer();
076: int chunkSize = readChunkSize();
077: while (chunkSize != 0) {
078: bodyBuffer.append(input.read(chunkSize));
079: readCRLF();
080: chunkSize = readChunkSize();
081: }
082: body = bodyBuffer.toString();
083:
084: }
085:
086: private int readChunkSize() throws Exception {
087: String sizeLine = input.readLine();
088: return Integer.parseInt(sizeLine, 16);
089: }
090:
091: private void readCRLF() throws Exception {
092: input.read(2);
093: }
094:
095: public int getStatus() {
096: return status;
097: }
098:
099: public String getBody() {
100: return body;
101: }
102:
103: public String getHeader(String key) {
104: return (String) headers.get(key);
105: }
106:
107: public boolean hasHeader(String key) {
108: return headers.containsKey(key);
109: }
110:
111: public String toString() {
112: StringBuffer buffer = new StringBuffer();
113: buffer.append("Status: ").append(status).append("\n");
114: buffer.append("Headers: ").append("\n");
115: for (Iterator iterator = headers.keySet().iterator(); iterator
116: .hasNext();) {
117: String key = (String) iterator.next();
118: buffer.append("\t").append(key).append(": ").append(
119: headers.get(key)).append("\n");
120:
121: }
122: buffer.append("Body: ").append("\n");
123: buffer.append(body);
124: return buffer.toString();
125: }
126:
127: public static ResponseParser performHttpRequest(String hostname,
128: int hostPort, RequestBuilder builder) throws Exception {
129: Socket socket = new Socket(hostname, hostPort);
130: OutputStream socketOut = socket.getOutputStream();
131: InputStream socketIn = socket.getInputStream();
132: builder.send(socketOut);
133: socketOut.flush();
134: ResponseParser parser = new ResponseParser(socketIn);
135: socket.close();
136: return parser;
137: }
138: }
|