001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.transport.http.server;
021:
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.OutputStream;
025: import java.net.InetAddress;
026: import java.net.Socket;
027: import java.net.SocketException;
028: import java.util.Iterator;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.apache.http.ConnectionClosedException;
033: import org.apache.http.Header;
034: import org.apache.http.HttpConnectionMetrics;
035: import org.apache.http.HttpEntity;
036: import org.apache.http.HttpEntityEnclosingRequest;
037: import org.apache.http.HttpException;
038: import org.apache.http.HttpRequest;
039: import org.apache.http.HttpRequestFactory;
040: import org.apache.http.HttpResponse;
041: import org.apache.http.HttpVersion;
042: import org.apache.http.RequestLine;
043: import org.apache.http.entity.ContentLengthStrategy;
044: import org.apache.http.impl.DefaultHttpRequestFactory;
045: import org.apache.http.impl.entity.StrictContentLengthStrategy;
046: import org.apache.http.impl.io.ChunkedInputStream;
047: import org.apache.http.impl.io.ChunkedOutputStream;
048: import org.apache.http.impl.io.ContentLengthInputStream;
049: import org.apache.http.impl.io.ContentLengthOutputStream;
050: import org.apache.http.impl.io.HttpDataInputStream;
051: import org.apache.http.impl.io.IdentityOutputStream;
052: import org.apache.http.impl.io.SocketHttpDataReceiver;
053: import org.apache.http.impl.io.SocketHttpDataTransmitter;
054: import org.apache.http.io.HttpDataReceiver;
055: import org.apache.http.io.HttpDataTransmitter;
056: import org.apache.http.message.BasicHeader;
057: import org.apache.http.message.BasicRequestLine;
058: import org.apache.http.message.BasicStatusLine;
059: import org.apache.http.message.BufferedHeader;
060: import org.apache.http.params.HttpConnectionParams;
061: import org.apache.http.params.HttpParams;
062: import org.apache.http.util.CharArrayBuffer;
063: import org.apache.http.util.HeaderUtils;
064:
065: public class AxisHttpConnectionImpl implements AxisHttpConnection {
066:
067: private static final Log HEADERLOG = LogFactory
068: .getLog("org.apache.axis2.transport.http.server.wire");
069:
070: private final Socket socket;
071: private final HttpDataTransmitter datatransmitter;
072: private final HttpDataReceiver datareceiver;
073: private final CharArrayBuffer charbuffer;
074: private final HttpRequestFactory requestfactory;
075: private final ContentLengthStrategy contentLenStrategy;
076: private final int maxHeaderCount;
077: private final int maxLineLen;
078:
079: private OutputStream out = null;
080: private InputStream in = null;
081:
082: public AxisHttpConnectionImpl(final Socket socket,
083: final HttpParams params) throws IOException {
084: super ();
085: if (socket == null) {
086: throw new IllegalArgumentException("Socket may not be null");
087: }
088: if (params == null) {
089: throw new IllegalArgumentException(
090: "HTTP parameters may not be null");
091: }
092: socket
093: .setTcpNoDelay(HttpConnectionParams
094: .getTcpNoDelay(params));
095: socket.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
096:
097: int linger = HttpConnectionParams.getLinger(params);
098: if (linger >= 0) {
099: socket.setSoLinger(linger > 0, linger);
100: }
101:
102: int buffersize = HttpConnectionParams
103: .getSocketBufferSize(params);
104: this .socket = socket;
105: this .datatransmitter = new SocketHttpDataTransmitter(socket,
106: buffersize, params);
107: this .datareceiver = new SocketHttpDataReceiver(socket,
108: buffersize, params);
109: this .charbuffer = new CharArrayBuffer(256);
110: this .requestfactory = new DefaultHttpRequestFactory();
111: this .contentLenStrategy = new StrictContentLengthStrategy();
112: this .maxHeaderCount = params.getIntParameter(
113: HttpConnectionParams.MAX_HEADER_COUNT, -1);
114: this .maxLineLen = params.getIntParameter(
115: HttpConnectionParams.MAX_LINE_LENGTH, -1);
116: }
117:
118: public void close() throws IOException {
119: this .datatransmitter.flush();
120: try {
121: this .socket.shutdownOutput();
122: } catch (IOException ignore) {
123: }
124: try {
125: this .socket.shutdownInput();
126: } catch (IOException ignore) {
127: }
128: this .socket.close();
129: }
130:
131: public boolean isOpen() {
132: return !this .socket.isClosed();
133: }
134:
135: public boolean isStale() {
136: try {
137: this .datareceiver.isDataAvailable(1);
138: return false;
139: } catch (IOException ex) {
140: return true;
141: }
142: }
143:
144: public void shutdown() throws IOException {
145: Socket tmpsocket = this .socket;
146: if (tmpsocket != null) {
147: tmpsocket.close();
148: }
149: }
150:
151: public HttpRequest receiveRequest() throws HttpException,
152: IOException {
153: this .charbuffer.clear();
154: int i = this .datareceiver.readLine(this .charbuffer);
155: if (i == -1) {
156: throw new ConnectionClosedException(
157: "Client closed connection");
158: }
159: RequestLine requestline = BasicRequestLine.parse(
160: this .charbuffer, 0, this .charbuffer.length());
161: HttpRequest request = this .requestfactory
162: .newHttpRequest(requestline);
163: Header[] headers = HeaderUtils.parseHeaders(this .datareceiver,
164: this .maxHeaderCount, this .maxLineLen);
165: request.setHeaders(headers);
166:
167: if (HEADERLOG.isDebugEnabled()) {
168: HEADERLOG
169: .debug(">> " + request.getRequestLine().toString());
170: for (i = 0; i < headers.length; i++) {
171: HEADERLOG.debug(">> " + headers[i].toString());
172: }
173: }
174:
175: // Prepare input stream
176: this .in = null;
177: if (request instanceof HttpEntityEnclosingRequest) {
178: long len = this .contentLenStrategy.determineLength(request);
179: if (len == ContentLengthStrategy.CHUNKED) {
180: this .in = new ChunkedInputStream(this .datareceiver);
181: } else if (len == ContentLengthStrategy.IDENTITY) {
182: this .in = new HttpDataInputStream(this .datareceiver);
183: } else {
184: this .in = new ContentLengthInputStream(datareceiver,
185: len);
186: }
187: }
188: return request;
189: }
190:
191: public void sendResponse(final HttpResponse response)
192: throws HttpException, IOException {
193: if (response == null) {
194: throw new IllegalArgumentException(
195: "HTTP response may not be null");
196: }
197:
198: if (HEADERLOG.isDebugEnabled()) {
199: HEADERLOG
200: .debug("<< " + response.getStatusLine().toString());
201: Header[] headers = response.getAllHeaders();
202: for (int i = 0; i < headers.length; i++) {
203: HEADERLOG.debug("<< " + headers[i].toString());
204: }
205: }
206:
207: this .charbuffer.clear();
208: BasicStatusLine.format(this .charbuffer, response
209: .getStatusLine());
210: this .datatransmitter.writeLine(this .charbuffer);
211: for (Iterator it = response.headerIterator(); it.hasNext();) {
212: Header header = (Header) it.next();
213: if (header instanceof BufferedHeader) {
214: this .datatransmitter
215: .writeLine(((BufferedHeader) header)
216: .getBuffer());
217: } else {
218: this .charbuffer.clear();
219: BasicHeader.format(this .charbuffer, header);
220: this .datatransmitter.writeLine(this .charbuffer);
221: }
222: }
223: this .charbuffer.clear();
224: this .datatransmitter.writeLine(this .charbuffer);
225:
226: // Prepare output stream
227: this .out = null;
228: HttpVersion ver = response.getStatusLine().getHttpVersion();
229: HttpEntity entity = response.getEntity();
230: if (entity != null) {
231: long len = entity.getContentLength();
232: if (entity.isChunked()
233: && ver.greaterEquals(HttpVersion.HTTP_1_1)) {
234: this .out = new ChunkedOutputStream(this .datatransmitter);
235: } else if (len >= 0) {
236: this .out = new ContentLengthOutputStream(
237: this .datatransmitter, len);
238: } else {
239: this .out = new IdentityOutputStream(
240: this .datatransmitter);
241: }
242: } else {
243: this .datatransmitter.flush();
244: }
245: }
246:
247: public InputStream getInputStream() {
248: return this .in;
249: }
250:
251: public OutputStream getOutputStream() {
252: return this .out;
253: }
254:
255: public void flush() throws IOException {
256: if (this .out != null) {
257: this .out.flush();
258: } else {
259: this .datatransmitter.flush();
260: }
261: }
262:
263: public void reset() throws IOException {
264: if (this .in != null) {
265: this .in.close();
266: this .in = null;
267: }
268: if (this .out != null) {
269: this .out.flush();
270: this .out.close();
271: this .out = null;
272: }
273: }
274:
275: public int getSocketTimeout() {
276: try {
277: return this .socket.getSoTimeout();
278: } catch (SocketException ex) {
279: return -1;
280: }
281: }
282:
283: public void setSocketTimeout(int timeout) {
284: try {
285: this .socket.setSoTimeout(timeout);
286: } catch (SocketException ex) {
287: }
288: }
289:
290: public InetAddress getLocalAddress() {
291: if (this .socket != null) {
292: return this .socket.getLocalAddress();
293: } else {
294: return null;
295: }
296: }
297:
298: public int getLocalPort() {
299: if (this .socket != null) {
300: return this .socket.getLocalPort();
301: } else {
302: return -1;
303: }
304: }
305:
306: public InetAddress getRemoteAddress() {
307: if (this .socket != null) {
308: return this .socket.getInetAddress();
309: } else {
310: return null;
311: }
312: }
313:
314: public int getRemotePort() {
315: if (this .socket != null) {
316: return this .socket.getPort();
317: } else {
318: return -1;
319: }
320: }
321:
322: public HttpConnectionMetrics getMetrics() {
323: return null;
324: }
325:
326: public String toString() {
327: StringBuffer buffer = new StringBuffer();
328: buffer.append("[");
329: if (isOpen()) {
330: buffer.append(this .socket.getInetAddress());
331: } else {
332: buffer.append("closed");
333: }
334: buffer.append("]");
335: return buffer.toString();
336: }
337:
338: }
|