001: /*
002: * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0-beta1/module-main/src/main/java/org/apache/http/protocol/HttpService.java $
003: * $Revision: 610763 $
004: * $Date: 2008-01-10 13:01:13 +0100 (Thu, 10 Jan 2008) $
005: *
006: * ====================================================================
007: * Licensed to the Apache Software Foundation (ASF) under one
008: * or more contributor license agreements. See the NOTICE file
009: * distributed with this work for additional information
010: * regarding copyright ownership. The ASF licenses this file
011: * to you under the Apache License, Version 2.0 (the
012: * "License"); you may not use this file except in compliance
013: * with the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing,
018: * software distributed under the License is distributed on an
019: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020: * KIND, either express or implied. See the License for the
021: * specific language governing permissions and limitations
022: * under the License.
023: * ====================================================================
024: *
025: * This software consists of voluntary contributions made by many
026: * individuals on behalf of the Apache Software Foundation. For more
027: * information on the Apache Software Foundation, please see
028: * <http://www.apache.org/>.
029: *
030: */
031:
032: package org.apache.http.protocol;
033:
034: import java.io.IOException;
035:
036: import org.apache.http.ConnectionReuseStrategy;
037: import org.apache.http.HttpEntity;
038: import org.apache.http.HttpEntityEnclosingRequest;
039: import org.apache.http.HttpException;
040: import org.apache.http.HttpRequest;
041: import org.apache.http.HttpResponse;
042: import org.apache.http.HttpResponseFactory;
043: import org.apache.http.HttpServerConnection;
044: import org.apache.http.HttpStatus;
045: import org.apache.http.HttpVersion;
046: import org.apache.http.MethodNotSupportedException;
047: import org.apache.http.ProtocolException;
048: import org.apache.http.ProtocolVersion;
049: import org.apache.http.UnsupportedHttpVersionException;
050: import org.apache.http.entity.ByteArrayEntity;
051: import org.apache.http.params.HttpParams;
052: import org.apache.http.params.DefaultedHttpParams;
053: import org.apache.http.util.EncodingUtils;
054:
055: /**
056: * Minimalistic server-side implementation of an HTTP processor.
057: *
058: * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
059: *
060: * @version $Revision: 610763 $
061: */
062: public class HttpService {
063:
064: private HttpParams params = null;
065: private HttpProcessor processor = null;
066: private HttpRequestHandlerResolver handlerResolver = null;
067: private ConnectionReuseStrategy connStrategy = null;
068: private HttpResponseFactory responseFactory = null;
069: private HttpExpectationVerifier expectationVerifier = null;
070:
071: /**
072: * Create a new HTTP service.
073: *
074: * @param proc the processor to use on requests and responses
075: * @param connStrategy the connection reuse strategy
076: * @param responseFactory the response factory
077: */
078: public HttpService(final HttpProcessor proc,
079: final ConnectionReuseStrategy connStrategy,
080: final HttpResponseFactory responseFactory) {
081: super ();
082: setHttpProcessor(proc);
083: setConnReuseStrategy(connStrategy);
084: setResponseFactory(responseFactory);
085: }
086:
087: public void setHttpProcessor(final HttpProcessor processor) {
088: if (processor == null) {
089: throw new IllegalArgumentException(
090: "HTTP processor may not be null.");
091: }
092: this .processor = processor;
093: }
094:
095: public void setConnReuseStrategy(
096: final ConnectionReuseStrategy connStrategy) {
097: if (connStrategy == null) {
098: throw new IllegalArgumentException(
099: "Connection reuse strategy may not be null");
100: }
101: this .connStrategy = connStrategy;
102: }
103:
104: public void setResponseFactory(
105: final HttpResponseFactory responseFactory) {
106: if (responseFactory == null) {
107: throw new IllegalArgumentException(
108: "Response factory may not be null");
109: }
110: this .responseFactory = responseFactory;
111: }
112:
113: public void setHandlerResolver(
114: final HttpRequestHandlerResolver handlerResolver) {
115: this .handlerResolver = handlerResolver;
116: }
117:
118: public void setExpectationVerifier(
119: final HttpExpectationVerifier expectationVerifier) {
120: this .expectationVerifier = expectationVerifier;
121: }
122:
123: public HttpParams getParams() {
124: return this .params;
125: }
126:
127: public void setParams(final HttpParams params) {
128: this .params = params;
129: }
130:
131: public void handleRequest(final HttpServerConnection conn,
132: final HttpContext context) throws IOException,
133: HttpException {
134:
135: context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
136:
137: HttpResponse response = null;
138:
139: try {
140:
141: HttpRequest request = conn.receiveRequestHeader();
142: request.setParams(new DefaultedHttpParams(request
143: .getParams(), this .params));
144:
145: ProtocolVersion ver = request.getRequestLine()
146: .getProtocolVersion();
147: if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
148: // Downgrade protocol version if greater than HTTP/1.1
149: ver = HttpVersion.HTTP_1_1;
150: }
151:
152: if (request instanceof HttpEntityEnclosingRequest) {
153:
154: if (((HttpEntityEnclosingRequest) request)
155: .expectContinue()) {
156: response = this .responseFactory.newHttpResponse(
157: ver, HttpStatus.SC_CONTINUE, context);
158: response.setParams(new DefaultedHttpParams(response
159: .getParams(), this .params));
160:
161: if (this .expectationVerifier != null) {
162: try {
163: this .expectationVerifier.verify(request,
164: response, context);
165: } catch (HttpException ex) {
166: response = this .responseFactory
167: .newHttpResponse(
168: HttpVersion.HTTP_1_0,
169: HttpStatus.SC_INTERNAL_SERVER_ERROR,
170: context);
171: response.setParams(new DefaultedHttpParams(
172: response.getParams(), this .params));
173: handleException(ex, response);
174: }
175: }
176: if (response.getStatusLine().getStatusCode() < 200) {
177: // Send 1xx response indicating the server expections
178: // have been met
179: conn.sendResponseHeader(response);
180: conn.flush();
181: response = null;
182: conn
183: .receiveRequestEntity((HttpEntityEnclosingRequest) request);
184: }
185: } else {
186: conn
187: .receiveRequestEntity((HttpEntityEnclosingRequest) request);
188: }
189: }
190:
191: if (response == null) {
192: response = this .responseFactory.newHttpResponse(ver,
193: HttpStatus.SC_OK, context);
194: response.setParams(new DefaultedHttpParams(response
195: .getParams(), this .params));
196:
197: context.setAttribute(ExecutionContext.HTTP_REQUEST,
198: request);
199: context.setAttribute(ExecutionContext.HTTP_RESPONSE,
200: response);
201:
202: this .processor.process(request, context);
203: doService(request, response, context);
204: }
205:
206: // Make sure the request content is fully consumed
207: if (request instanceof HttpEntityEnclosingRequest) {
208: HttpEntity entity = ((HttpEntityEnclosingRequest) request)
209: .getEntity();
210: if (entity != null) {
211: entity.consumeContent();
212: }
213: }
214:
215: } catch (HttpException ex) {
216: response = this .responseFactory.newHttpResponse(
217: HttpVersion.HTTP_1_0,
218: HttpStatus.SC_INTERNAL_SERVER_ERROR, context);
219: response.setParams(new DefaultedHttpParams(response
220: .getParams(), this .params));
221: handleException(ex, response);
222: }
223:
224: this .processor.process(response, context);
225: conn.sendResponseHeader(response);
226: conn.sendResponseEntity(response);
227: conn.flush();
228:
229: if (!this .connStrategy.keepAlive(response, context)) {
230: conn.close();
231: }
232: }
233:
234: protected void handleException(final HttpException ex,
235: final HttpResponse response) {
236: if (ex instanceof MethodNotSupportedException) {
237: response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
238: } else if (ex instanceof UnsupportedHttpVersionException) {
239: response
240: .setStatusCode(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED);
241: } else if (ex instanceof ProtocolException) {
242: response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
243: } else {
244: response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
245: }
246: byte[] msg = EncodingUtils.getAsciiBytes(ex.getMessage());
247: ByteArrayEntity entity = new ByteArrayEntity(msg);
248: entity.setContentType("text/plain; charset=US-ASCII");
249: response.setEntity(entity);
250: }
251:
252: protected void doService(final HttpRequest request,
253: final HttpResponse response, final HttpContext context)
254: throws HttpException, IOException {
255: HttpRequestHandler handler = null;
256: if (this .handlerResolver != null) {
257: String requestURI = request.getRequestLine().getUri();
258: handler = this.handlerResolver.lookup(requestURI);
259: }
260: if (handler != null) {
261: handler.handle(request, response, context);
262: } else {
263: response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
264: }
265: }
266:
267: }
|