michael@0: /*
michael@0: * ====================================================================
michael@0: * Licensed to the Apache Software Foundation (ASF) under one
michael@0: * or more contributor license agreements. See the NOTICE file
michael@0: * distributed with this work for additional information
michael@0: * regarding copyright ownership. The ASF licenses this file
michael@0: * to you under the Apache License, Version 2.0 (the
michael@0: * "License"); you may not use this file except in compliance
michael@0: * with the License. You may obtain a copy of the License at
michael@0: *
michael@0: * http://www.apache.org/licenses/LICENSE-2.0
michael@0: *
michael@0: * Unless required by applicable law or agreed to in writing,
michael@0: * software distributed under the License is distributed on an
michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
michael@0: * KIND, either express or implied. See the License for the
michael@0: * specific language governing permissions and limitations
michael@0: * under the License.
michael@0: * ====================================================================
michael@0: *
michael@0: * This software consists of voluntary contributions made by many
michael@0: * individuals on behalf of the Apache Software Foundation. For more
michael@0: * information on the Apache Software Foundation, please see
michael@0: *
michael@0: * The following parameters can be used to customize the behavior of this michael@0: * class: michael@0: *
michael@0: * This constructor will invoke {@link #createEntityDeserializer()} michael@0: * and {@link #createEntitySerializer()} methods in order to initialize michael@0: * HTTP entity serializer and deserializer implementations for this michael@0: * connection. michael@0: */ michael@0: public AbstractHttpServerConnection() { michael@0: super(); michael@0: this.entityserializer = createEntitySerializer(); michael@0: this.entitydeserializer = createEntityDeserializer(); michael@0: } michael@0: michael@0: /** michael@0: * Asserts if the connection is open. michael@0: * michael@0: * @throws IllegalStateException if the connection is not open. michael@0: */ michael@0: protected abstract void assertOpen() throws IllegalStateException; michael@0: michael@0: /** michael@0: * Creates an instance of {@link EntityDeserializer} with the michael@0: * {@link LaxContentLengthStrategy} implementation to be used for michael@0: * de-serializing entities received over this connection. michael@0: *
michael@0: * This method can be overridden in a super class in order to create michael@0: * instances of {@link EntityDeserializer} using a custom michael@0: * {@link ContentLengthStrategy}. michael@0: * michael@0: * @return HTTP entity deserializer michael@0: */ michael@0: protected EntityDeserializer createEntityDeserializer() { michael@0: return new EntityDeserializer(new LaxContentLengthStrategy()); michael@0: } michael@0: michael@0: /** michael@0: * Creates an instance of {@link EntitySerializer} with the michael@0: * {@link StrictContentLengthStrategy} implementation to be used for michael@0: * serializing HTTP entities sent over this connection. michael@0: *
michael@0: * This method can be overridden in a super class in order to create michael@0: * instances of {@link EntitySerializer} using a custom michael@0: * {@link ContentLengthStrategy}. michael@0: * michael@0: * @return HTTP entity serialzier. michael@0: */ michael@0: protected EntitySerializer createEntitySerializer() { michael@0: return new EntitySerializer(new StrictContentLengthStrategy()); michael@0: } michael@0: michael@0: /** michael@0: * Creates an instance of {@link DefaultHttpRequestFactory} to be used michael@0: * for creating {@link HttpRequest} objects received by over this michael@0: * connection. michael@0: *
michael@0: * This method can be overridden in a super class in order to provide michael@0: * a different implementation of the {@link HttpRequestFactory} interface. michael@0: * michael@0: * @return HTTP request factory. michael@0: */ michael@0: protected HttpRequestFactory createHttpRequestFactory() { michael@0: return new DefaultHttpRequestFactory(); michael@0: } michael@0: michael@0: /** michael@0: * Creates an instance of {@link HttpMessageParser} to be used for parsing michael@0: * HTTP requests received over this connection. michael@0: *
michael@0: * This method can be overridden in a super class in order to provide michael@0: * a different implementation of the {@link HttpMessageParser} interface or michael@0: * to pass a different implementation of {@link LineParser} to the michael@0: * the default implementation {@link HttpRequestParser}. michael@0: * michael@0: * @param buffer the session input buffer. michael@0: * @param requestFactory the HTTP request factory. michael@0: * @param params HTTP parameters. michael@0: * @return HTTP message parser. michael@0: */ michael@0: protected HttpMessageParser createRequestParser( michael@0: final SessionInputBuffer buffer, michael@0: final HttpRequestFactory requestFactory, michael@0: final HttpParams params) { michael@0: return new HttpRequestParser(buffer, null, requestFactory, params); michael@0: } michael@0: michael@0: /** michael@0: * Creates an instance of {@link HttpMessageWriter} to be used for michael@0: * writing out HTTP responses sent over this connection. michael@0: *
michael@0: * This method can be overridden in a super class in order to provide michael@0: * a different implementation of the {@link HttpMessageWriter} interface or michael@0: * to pass a different implementation of {@link LineFormatter} to the michael@0: * the default implementation {@link HttpResponseWriter}. michael@0: * michael@0: * @param buffer the session output buffer michael@0: * @param params HTTP parameters michael@0: * @return HTTP message writer michael@0: */ michael@0: protected HttpMessageWriter createResponseWriter( michael@0: final SessionOutputBuffer buffer, michael@0: final HttpParams params) { michael@0: return new HttpResponseWriter(buffer, null, params); michael@0: } michael@0: michael@0: /** michael@0: * @since 4.1 michael@0: */ michael@0: protected HttpConnectionMetricsImpl createConnectionMetrics( michael@0: final HttpTransportMetrics inTransportMetric, michael@0: final HttpTransportMetrics outTransportMetric) { michael@0: return new HttpConnectionMetricsImpl(inTransportMetric, outTransportMetric); michael@0: } michael@0: michael@0: /** michael@0: * Initializes this connection object with {@link SessionInputBuffer} and michael@0: * {@link SessionOutputBuffer} instances to be used for sending and michael@0: * receiving data. These session buffers can be bound to any arbitrary michael@0: * physical output medium. michael@0: *
michael@0: * This method will invoke {@link #createHttpRequestFactory}, michael@0: * {@link #createRequestParser(SessionInputBuffer, HttpRequestFactory, HttpParams)} michael@0: * and {@link #createResponseWriter(SessionOutputBuffer, HttpParams)} michael@0: * methods to initialize HTTP request parser and response writer for this michael@0: * connection. michael@0: * michael@0: * @param inbuffer the session input buffer. michael@0: * @param outbuffer the session output buffer. michael@0: * @param params HTTP parameters. michael@0: */ michael@0: protected void init( michael@0: final SessionInputBuffer inbuffer, michael@0: final SessionOutputBuffer outbuffer, michael@0: final HttpParams params) { michael@0: if (inbuffer == null) { michael@0: throw new IllegalArgumentException("Input session buffer may not be null"); michael@0: } michael@0: if (outbuffer == null) { michael@0: throw new IllegalArgumentException("Output session buffer may not be null"); michael@0: } michael@0: this.inbuffer = inbuffer; michael@0: this.outbuffer = outbuffer; michael@0: if (inbuffer instanceof EofSensor) { michael@0: this.eofSensor = (EofSensor) inbuffer; michael@0: } michael@0: this.requestParser = createRequestParser( michael@0: inbuffer, michael@0: createHttpRequestFactory(), michael@0: params); michael@0: this.responseWriter = createResponseWriter( michael@0: outbuffer, params); michael@0: this.metrics = createConnectionMetrics( michael@0: inbuffer.getMetrics(), michael@0: outbuffer.getMetrics()); michael@0: } michael@0: michael@0: public HttpRequest receiveRequestHeader() michael@0: throws HttpException, IOException { michael@0: assertOpen(); michael@0: HttpRequest request = (HttpRequest) this.requestParser.parse(); michael@0: this.metrics.incrementRequestCount(); michael@0: return request; michael@0: } michael@0: michael@0: public void receiveRequestEntity(final HttpEntityEnclosingRequest request) michael@0: throws HttpException, IOException { michael@0: if (request == null) { michael@0: throw new IllegalArgumentException("HTTP request may not be null"); michael@0: } michael@0: assertOpen(); michael@0: HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, request); michael@0: request.setEntity(entity); michael@0: } michael@0: michael@0: protected void doFlush() throws IOException { michael@0: this.outbuffer.flush(); michael@0: } michael@0: michael@0: public void flush() throws IOException { michael@0: assertOpen(); michael@0: doFlush(); michael@0: } michael@0: michael@0: public void sendResponseHeader(final HttpResponse response) michael@0: throws HttpException, IOException { michael@0: if (response == null) { michael@0: throw new IllegalArgumentException("HTTP response may not be null"); michael@0: } michael@0: assertOpen(); michael@0: this.responseWriter.write(response); michael@0: if (response.getStatusLine().getStatusCode() >= 200) { michael@0: this.metrics.incrementResponseCount(); michael@0: } michael@0: } michael@0: michael@0: public void sendResponseEntity(final HttpResponse response) michael@0: throws HttpException, IOException { michael@0: if (response.getEntity() == null) { michael@0: return; michael@0: } michael@0: this.entityserializer.serialize( michael@0: this.outbuffer, michael@0: response, michael@0: response.getEntity()); michael@0: } michael@0: michael@0: protected boolean isEof() { michael@0: return this.eofSensor != null && this.eofSensor.isEof(); michael@0: } michael@0: michael@0: public boolean isStale() { michael@0: if (!isOpen()) { michael@0: return true; michael@0: } michael@0: if (isEof()) { michael@0: return true; michael@0: } michael@0: try { michael@0: this.inbuffer.isDataAvailable(1); michael@0: return isEof(); michael@0: } catch (IOException ex) { michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: public HttpConnectionMetrics getMetrics() { michael@0: return this.metrics; michael@0: } michael@0: michael@0: }