/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.transport.http.server; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HeaderIterator; import org.apache.http.HttpConnectionMetrics; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; import org.apache.http.entity.ContentLengthStrategy; import org.apache.http.impl.DefaultHttpRequestFactory; import org.apache.http.impl.entity.StrictContentLengthStrategy; import org.apache.http.impl.io.ChunkedInputStream; import org.apache.http.impl.io.ChunkedOutputStream; import org.apache.http.impl.io.ContentLengthInputStream; import org.apache.http.impl.io.ContentLengthOutputStream; import org.apache.http.impl.io.HttpRequestParser; import org.apache.http.impl.io.HttpResponseWriter; import org.apache.http.impl.io.IdentityInputStream; import org.apache.http.impl.io.IdentityOutputStream; import org.apache.http.impl.io.SocketInputBuffer; import org.apache.http.impl.io.SocketOutputBuffer; import org.apache.http.io.HttpMessageParser; import org.apache.http.io.HttpMessageWriter; import org.apache.http.io.SessionInputBuffer; import org.apache.http.io.SessionOutputBuffer; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; public class AxisHttpConnectionImpl implements AxisHttpConnection { private static final Log HEADERLOG = LogFactory.getLog("org.apache.axis2.transport.http.server.wire"); private final Socket socket; private final SessionOutputBuffer outbuffer; private final SessionInputBuffer inbuffer; private final HttpMessageParser requestParser; private final HttpMessageWriter responseWriter; private final ContentLengthStrategy contentLenStrategy; private OutputStream out = null; private InputStream in = null; public AxisHttpConnectionImpl(final Socket socket, final HttpParams params) throws IOException { super(); if (socket == null) { throw new IllegalArgumentException("Socket may not be null"); } if (params == null) { throw new IllegalArgumentException("HTTP parameters may not be null"); } socket.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params)); socket.setSoTimeout(HttpConnectionParams.getSoTimeout(params)); int linger = HttpConnectionParams.getLinger(params); if (linger >= 0) { socket.setSoLinger(linger > 0, linger); } int buffersize = HttpConnectionParams.getSocketBufferSize(params); this.socket = socket; this.outbuffer = new SocketOutputBuffer(socket, buffersize, params); this.inbuffer = new SocketInputBuffer(socket, buffersize, params); this.contentLenStrategy = new StrictContentLengthStrategy(); this.requestParser = new HttpRequestParser( this.inbuffer, null, new DefaultHttpRequestFactory(), params); this.responseWriter = new HttpResponseWriter( this.outbuffer, null, params); } public void close() throws IOException { this.outbuffer.flush(); try { this.socket.shutdownOutput(); } catch (IOException ignore) { } try { this.socket.shutdownInput(); } catch (IOException ignore) { } this.socket.close(); } public boolean isOpen() { return !this.socket.isClosed(); } public boolean isStale() { try { this.inbuffer.isDataAvailable(1); return false; } catch (IOException ex) { return true; } } public void shutdown() throws IOException { Socket tmpsocket = this.socket; if (tmpsocket != null) { tmpsocket.close(); } } public HttpRequest receiveRequest() throws HttpException, IOException { HttpRequest request = (HttpRequest) this.requestParser.parse(); if (HEADERLOG.isDebugEnabled()) { HEADERLOG.debug(">> " + request.getRequestLine().toString()); for (HeaderIterator it = request.headerIterator(); it.hasNext(); ) { HEADERLOG.debug(">> " + it.nextHeader().toString()); } } // Prepare input stream this.in = null; if (request instanceof HttpEntityEnclosingRequest) { long len = this.contentLenStrategy.determineLength(request); if (len == ContentLengthStrategy.CHUNKED) { this.in = new ChunkedInputStream(this.inbuffer); } else if (len == ContentLengthStrategy.IDENTITY) { this.in = new IdentityInputStream(this.inbuffer); } else { this.in = new ContentLengthInputStream(inbuffer, len); } } return request; } public void sendResponse(final HttpResponse response) throws HttpException, IOException { if (response == null) { throw new IllegalArgumentException("HTTP response may not be null"); } if (HEADERLOG.isDebugEnabled()) { HEADERLOG.debug("<< " + response.getStatusLine().toString()); for (HeaderIterator it = response.headerIterator(); it.hasNext(); ) { HEADERLOG.debug("<< " + it.nextHeader().toString()); } } this.responseWriter.write(response); // Prepare output stream this.out = null; ProtocolVersion ver = response.getStatusLine().getProtocolVersion(); HttpEntity entity = response.getEntity(); if (entity != null) { long len = entity.getContentLength(); if (entity.isChunked() && ver.greaterEquals(HttpVersion.HTTP_1_1)) { this.out = new ChunkedOutputStream(this.outbuffer); } else if (len >= 0) { this.out = new ContentLengthOutputStream(this.outbuffer, len); } else { this.out = new IdentityOutputStream(this.outbuffer); } } else { this.outbuffer.flush(); } } public InputStream getInputStream() { return this.in; } public OutputStream getOutputStream() { return this.out; } public void flush() throws IOException { if (this.out != null) { this.out.flush(); } else { this.outbuffer.flush(); } } public void reset() throws IOException { if (this.in != null) { this.in.close(); this.in = null; } if (this.out != null) { this.out.flush(); this.out.close(); this.out = null; } } public int getSocketTimeout() { try { return this.socket.getSoTimeout(); } catch (SocketException ex) { return -1; } } public void setSocketTimeout(int timeout) { try { this.socket.setSoTimeout(timeout); } catch (SocketException ex) { } } public InetAddress getLocalAddress() { if (this.socket != null) { return this.socket.getLocalAddress(); } else { return null; } } public int getLocalPort() { if (this.socket != null) { return this.socket.getLocalPort(); } else { return -1; } } public InetAddress getRemoteAddress() { if (this.socket != null) { return this.socket.getInetAddress(); } else { return null; } } public int getRemotePort() { if (this.socket != null) { return this.socket.getPort(); } else { return -1; } } public HttpConnectionMetrics getMetrics() { return null; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("["); if (isOpen()) { buffer.append(this.socket.getInetAddress()); } else { buffer.append("closed"); } buffer.append("]"); return buffer.toString(); } }