001: package pygmy.core;
002:
003: import java.io.*;
004: import java.net.HttpURLConnection;
005:
006: /**
007: * This holds the response data for the http response.
008: */
009: public class HttpResponse extends Response {
010:
011: private int statusCode = HttpURLConnection.HTTP_OK;
012:
013: private String mimeType = "text/html";
014:
015: private HttpHeaders responseHeaders;
016:
017: private InternetOutputStream stream;
018:
019: private ResponseDataList dataStreamList;
020:
021: private HttpRequest request;
022:
023: private boolean keepConnectionOpen;
024:
025: private ResponseListener responseListener;
026:
027: public HttpResponse(HttpRequest request, OutputStream aStream) {
028: this (request, aStream, null);
029: }
030:
031: public HttpResponse(HttpRequest request, OutputStream aStream,
032: ResponseListener listener) {
033: this .stream = new InternetOutputStream(aStream);
034: this .request = request;
035: this .dataStreamList = new ResponseDataList();
036: this .responseHeaders = new HttpHeaders();
037: this .keepConnectionOpen = request.isKeepAlive();
038: this .responseListener = listener;
039: }
040:
041: public boolean isKeepAlive() {
042: return (keepConnectionOpen && request.isKeepAlive());
043: }
044:
045: public void addHeader(String key, String value) {
046: responseHeaders.put(key, value);
047: }
048:
049: public PrintWriter getPrintWriter() {
050: return dataStreamList.addPrintWriter();
051: }
052:
053: public void setMimeType(String aMimeType) {
054: mimeType = aMimeType;
055: }
056:
057: public void sendError(int statusCode, String errorMessage) {
058: sendError(statusCode, errorMessage, null);
059: }
060:
061: public void sendError(int statusCode, String errorMessage,
062: Exception e) {
063: keepConnectionOpen = false;
064: String body = "<html>\n<head>\n"
065: + "<title>Error: "
066: + statusCode
067: + "</title>\n"
068: + "<body>\n<h1>"
069: + statusCode
070: + " <b>"
071: + Http.getStatusPhrase(statusCode)
072: + "</b></h1><br>\nThe requested URL <b>"
073: + ((request.getUrl() == null) ? "<i>unknown URL</i>"
074: : Http.encodeHtml(request.getUrl()))
075: + "</b>\n " + Http.encodeHtml(errorMessage) + "\n<hr>";
076: if (e != null) {
077: StringWriter writer = new StringWriter();
078: writer.write("<pre>");
079: e.printStackTrace(new PrintWriter(writer));
080: writer.write("</pre>");
081: body += writer.toString();
082: }
083: body += "</body>\n</html>";
084:
085: this .dataStreamList.reset();
086: this .statusCode = statusCode;
087: this .mimeType = "text/html";
088: PrintWriter out = getPrintWriter();
089: out.write(body);
090: }
091:
092: public void sendResponse(InputStream is, int length)
093: throws IOException {
094: this .dataStreamList.addResponse(is, length);
095: }
096:
097: public void sendResponse(InputStream is, long beginning, long ending)
098: throws IOException {
099: this .dataStreamList.addResponse(is, beginning, ending
100: - beginning);
101: }
102:
103: public void setStatusCode(int statusCode) {
104: this .statusCode = statusCode;
105: }
106:
107: public void commitResponse() throws IOException {
108: try {
109: startTransfer();
110: sendHttpReply(statusCode);
111: sendHeaders(mimeType, dataStreamList.getTotalLength());
112: if (!isHeadMethod()) {
113: sendBody();
114: }
115: endTransfer();
116: } catch (IOException e) {
117: endTransfer(e);
118: throw e;
119: }
120: }
121:
122: private void sendBody() throws IOException {
123: dataStreamList.sendData(stream, !request
124: .isProtocolVersionLessThan(1, 1));
125: }
126:
127: private void sendHttpReply(int code) throws IOException {
128: StringBuffer buffer = new StringBuffer(request.getProtocol());
129: buffer.append(" ");
130: buffer.append(code);
131: buffer.append(" ");
132: buffer.append(Http.getStatusPhrase(code));
133: buffer.append(Http.CRLF);
134: stream.write(buffer.toString().getBytes());
135: }
136:
137: private void sendHeaders(String mimeType, long contentLength)
138: throws IOException {
139: responseHeaders.put("Date", Http.getCurrentTime());
140: responseHeaders.put("Server", "Pygmy");
141: String str = request.isKeepAlive() ? "Keep-Alive" : "close";
142: responseHeaders.put(request.getConnectionHeader(), str);
143: if (contentLength >= 0) {
144: responseHeaders.put("Content-Length", Long
145: .toString(contentLength));
146: } else if (!request.isProtocolVersionLessThan(1, 1)) {
147: responseHeaders.put("Transfer-Encoding", "chunked");
148: }
149:
150: if (mimeType != null) {
151: responseHeaders.put("Content-Type", mimeType);
152: }
153: responseHeaders.print(stream);
154: }
155:
156: private boolean isHeadMethod() {
157: return "HEAD".equalsIgnoreCase(request.getMethod());
158: }
159:
160: public OutputStream getOutputStream() {
161: return stream;
162: }
163:
164: protected void startTransfer() {
165: if (responseListener != null) {
166: responseListener.startTransfer(request);
167: }
168: }
169:
170: protected void notifyListeners(int bytesSent, int length)
171: throws IOException {
172: if (responseListener != null) {
173: responseListener.notify(request, bytesSent, length);
174: }
175: }
176:
177: protected void endTransfer() {
178: endTransfer(null);
179: }
180:
181: protected void endTransfer(Exception e) {
182: if (responseListener != null) {
183: responseListener.endTransfer(request, e);
184: }
185: }
186: }
|