1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.danube.http;
14
15 import java.io.EOFException;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.net.Socket;
20 import java.text.SimpleDateFormat;
21 import java.util.Date;
22
23 import org.abstracthorizon.danube.connection.Connection;
24 import org.abstracthorizon.danube.connection.ConnectionHandler;
25 import org.abstracthorizon.danube.http.util.ErrorConnectionHandler;
26 import org.abstracthorizon.danube.http.util.MultiStringMap;
27 import org.abstracthorizon.danube.service.server.ServerConnectionHandler;
28 import org.abstracthorizon.danube.support.RuntimeIOException;
29
30
31
32
33
34
35
36
37
38 public class HTTPServerConnectionHandler extends ServerConnectionHandler {
39
40
41 public static final String VERSION_STRING = "1.0";
42
43
44 public static final String FULL_VERSION_STRING = "Danube/" + VERSION_STRING;
45
46
47 public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
48
49
50 public static final int DEFAULT_BUFFER_SIZE = 1024*8;
51
52
53 protected ConnectionHandler errorHandler;
54
55
56 protected int defaultBufferSize = DEFAULT_BUFFER_SIZE;
57
58
59 public HTTPServerConnectionHandler() {
60 }
61
62
63
64
65
66 public ConnectionHandler getErrorHandler() {
67 if (errorHandler == null) {
68 errorHandler = new ErrorConnectionHandler();
69 }
70 return errorHandler;
71 }
72
73
74
75
76
77 public void setErrorHandler(ConnectionHandler errorHandler) {
78 this.errorHandler = errorHandler;
79 }
80
81
82
83
84
85 public int getDefaultBufferSize() {
86 return defaultBufferSize;
87 }
88
89
90
91
92
93 public void setDefaultBufferSize(int defaultBufferSize) {
94 this.defaultBufferSize = defaultBufferSize;
95 }
96
97
98
99
100
101
102
103 protected void processConnection(Connection connection) {
104 HTTPConnectionImpl httpConnection = (HTTPConnectionImpl)connection;
105 try {
106 try {
107 httpConnection.processRequest();
108 } catch (EOFException eof) {
109 throw eof;
110 } catch (IOException e) {
111 throw new EOFException(e.getMessage());
112 }
113
114 MultiStringMap headers = httpConnection.getResponseHeaders();
115
116 headers.putOnly("Server", FULL_VERSION_STRING);
117
118
119 headers.putOnly("Content-Type", "text/html");
120
121
122 headers.putOnly("Date", DATE_FORMAT.format(new Date()));
123
124 try {
125 connectionHandler.handleConnection(httpConnection);
126
127 OutputStream out = (OutputStream)httpConnection.adapt(OutputStream.class);
128 try {
129 out.close();
130 } catch (IOException ignore) {
131 }
132 } catch (Throwable e) {
133 Socket socket = (Socket)httpConnection.adapt(Socket.class);
134 if ((socket != null) && (socket.isConnected() && !socket.isClosed() && !socket.isInputShutdown() && !socket.isOutputShutdown())) {
135 httpConnection.setResponseStatus(Status.INTERNAL_SERVER_ERROR);
136 ConnectionHandler connectionHandler = getErrorHandler();
137 httpConnection.getAttributes().put("_exception", e);
138 connectionHandler.handleConnection(httpConnection);
139 } else {
140 throw new EOFException();
141 }
142 } finally {
143 InputStream in = (InputStream)httpConnection.adapt(InputStream.class);
144 in.close();
145 }
146 } catch (IOException e) {
147 throw new RuntimeIOException(e);
148 }
149 }
150
151 protected Connection decorateConnection(Connection connection) {
152 return new HTTPConnectionImpl(connection, this, getDefaultBufferSize());
153 }
154
155 protected boolean postProcessing(Connection connection, boolean persistConnection) {
156 HTTPConnectionImpl httpConnection = (HTTPConnectionImpl)connection;
157 MultiStringMap headers = httpConnection.getResponseHeaders();
158
159 if (persistConnection) {
160 String code = httpConnection.getResponseStatus().getCode();
161
162
163
164
165
166
167 if (!code.startsWith("1")
168 && !"204".equals(code)
169 && !"304".equals(code)
170 && !headers.containsKey("Content-Length")
171 && !"chunked".equals(headers.getOnly("Transfer-Encoding"))) {
172
173 persistConnection = false;
174 }
175 }
176
177 if (persistConnection) {
178 if ("HTTP/1.1".equals(httpConnection.getRequestProtocol())) {
179 try {
180 if ("Close".equalsIgnoreCase(headers.getOnly("Connection"))) {
181 persistConnection = false;
182 }
183 } catch (IllegalStateException ignore) {
184 }
185 } else {
186 try {
187 if (!"Keep-Alive".equalsIgnoreCase(headers.getOnly("Connection"))) {
188 persistConnection = false;
189 }
190 } catch (IllegalStateException ignore) {
191 }
192 }
193 }
194 return persistConnection;
195 }
196
197 protected void finishConnection(Connection connnection) {
198 }
199
200 }