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