mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,375 @@
     1.4 +/*
     1.5 + * ====================================================================
     1.6 + * Licensed to the Apache Software Foundation (ASF) under one
     1.7 + * or more contributor license agreements.  See the NOTICE file
     1.8 + * distributed with this work for additional information
     1.9 + * regarding copyright ownership.  The ASF licenses this file
    1.10 + * to you under the Apache License, Version 2.0 (the
    1.11 + * "License"); you may not use this file except in compliance
    1.12 + * with the License.  You may obtain a copy of the License at
    1.13 + *
    1.14 + *   http://www.apache.org/licenses/LICENSE-2.0
    1.15 + *
    1.16 + * Unless required by applicable law or agreed to in writing,
    1.17 + * software distributed under the License is distributed on an
    1.18 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    1.19 + * KIND, either express or implied.  See the License for the
    1.20 + * specific language governing permissions and limitations
    1.21 + * under the License.
    1.22 + * ====================================================================
    1.23 + *
    1.24 + * This software consists of voluntary contributions made by many
    1.25 + * individuals on behalf of the Apache Software Foundation.  For more
    1.26 + * information on the Apache Software Foundation, please see
    1.27 + * <http://www.apache.org/>.
    1.28 + *
    1.29 + */
    1.30 +
    1.31 +package ch.boye.httpclientandroidlib.protocol;
    1.32 +
    1.33 +import java.io.IOException;
    1.34 +
    1.35 +import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
    1.36 +import ch.boye.httpclientandroidlib.HttpEntity;
    1.37 +import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
    1.38 +import ch.boye.httpclientandroidlib.HttpException;
    1.39 +import ch.boye.httpclientandroidlib.HttpRequest;
    1.40 +import ch.boye.httpclientandroidlib.HttpResponse;
    1.41 +import ch.boye.httpclientandroidlib.HttpResponseFactory;
    1.42 +import ch.boye.httpclientandroidlib.HttpServerConnection;
    1.43 +import ch.boye.httpclientandroidlib.HttpStatus;
    1.44 +import ch.boye.httpclientandroidlib.HttpVersion;
    1.45 +import ch.boye.httpclientandroidlib.MethodNotSupportedException;
    1.46 +import ch.boye.httpclientandroidlib.ProtocolException;
    1.47 +import ch.boye.httpclientandroidlib.ProtocolVersion;
    1.48 +import ch.boye.httpclientandroidlib.UnsupportedHttpVersionException;
    1.49 +import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
    1.50 +import ch.boye.httpclientandroidlib.params.HttpParams;
    1.51 +import ch.boye.httpclientandroidlib.params.DefaultedHttpParams;
    1.52 +import ch.boye.httpclientandroidlib.util.EncodingUtils;
    1.53 +import ch.boye.httpclientandroidlib.util.EntityUtils;
    1.54 +
    1.55 +/**
    1.56 + * HttpService is a server side HTTP protocol handler based in the blocking
    1.57 + * I/O model that implements the essential requirements of the HTTP protocol
    1.58 + * for the server side message processing as described by RFC 2616.
    1.59 + * <br>
    1.60 + * HttpService relies on {@link HttpProcessor} to generate mandatory protocol
    1.61 + * headers for all outgoing messages and apply common, cross-cutting message
    1.62 + * transformations to all incoming and outgoing messages, whereas individual
    1.63 + * {@link HttpRequestHandler}s are expected to take care of application specific
    1.64 + * content generation and processing.
    1.65 + * <br>
    1.66 + * HttpService relies on {@link HttpRequestHandler} to resolve matching request
    1.67 + * handler for a particular request URI of an incoming HTTP request.
    1.68 + * <br>
    1.69 + * HttpService can use optional {@link HttpExpectationVerifier} to ensure that
    1.70 + * incoming requests meet server's expectations.
    1.71 + *
    1.72 + * @since 4.0
    1.73 + */
    1.74 +public class HttpService {
    1.75 +
    1.76 +    /**
    1.77 +     * TODO: make all variables final in the next major version
    1.78 +     */
    1.79 +    private volatile HttpParams params = null;
    1.80 +    private volatile HttpProcessor processor = null;
    1.81 +    private volatile HttpRequestHandlerResolver handlerResolver = null;
    1.82 +    private volatile ConnectionReuseStrategy connStrategy = null;
    1.83 +    private volatile HttpResponseFactory responseFactory = null;
    1.84 +    private volatile HttpExpectationVerifier expectationVerifier = null;
    1.85 +
    1.86 +    /**
    1.87 +     * Create a new HTTP service.
    1.88 +     *
    1.89 +     * @param processor            the processor to use on requests and responses
    1.90 +     * @param connStrategy         the connection reuse strategy
    1.91 +     * @param responseFactory      the response factory
    1.92 +     * @param handlerResolver      the handler resolver. May be null.
    1.93 +     * @param expectationVerifier  the expectation verifier. May be null.
    1.94 +     * @param params               the HTTP parameters
    1.95 +     *
    1.96 +     * @since 4.1
    1.97 +     */
    1.98 +    public HttpService(
    1.99 +            final HttpProcessor processor,
   1.100 +            final ConnectionReuseStrategy connStrategy,
   1.101 +            final HttpResponseFactory responseFactory,
   1.102 +            final HttpRequestHandlerResolver handlerResolver,
   1.103 +            final HttpExpectationVerifier expectationVerifier,
   1.104 +            final HttpParams params) {
   1.105 +        super();
   1.106 +        if (processor == null) {
   1.107 +            throw new IllegalArgumentException("HTTP processor may not be null");
   1.108 +        }
   1.109 +        if (connStrategy == null) {
   1.110 +            throw new IllegalArgumentException("Connection reuse strategy may not be null");
   1.111 +        }
   1.112 +        if (responseFactory == null) {
   1.113 +            throw new IllegalArgumentException("Response factory may not be null");
   1.114 +        }
   1.115 +        if (params == null) {
   1.116 +            throw new IllegalArgumentException("HTTP parameters may not be null");
   1.117 +        }
   1.118 +        this.processor = processor;
   1.119 +        this.connStrategy = connStrategy;
   1.120 +        this.responseFactory = responseFactory;
   1.121 +        this.handlerResolver = handlerResolver;
   1.122 +        this.expectationVerifier = expectationVerifier;
   1.123 +        this.params = params;
   1.124 +    }
   1.125 +
   1.126 +    /**
   1.127 +     * Create a new HTTP service.
   1.128 +     *
   1.129 +     * @param processor            the processor to use on requests and responses
   1.130 +     * @param connStrategy         the connection reuse strategy
   1.131 +     * @param responseFactory      the response factory
   1.132 +     * @param handlerResolver      the handler resolver. May be null.
   1.133 +     * @param params               the HTTP parameters
   1.134 +     *
   1.135 +     * @since 4.1
   1.136 +     */
   1.137 +    public HttpService(
   1.138 +            final HttpProcessor processor,
   1.139 +            final ConnectionReuseStrategy connStrategy,
   1.140 +            final HttpResponseFactory responseFactory,
   1.141 +            final HttpRequestHandlerResolver handlerResolver,
   1.142 +            final HttpParams params) {
   1.143 +        this(processor, connStrategy, responseFactory, handlerResolver, null, params);
   1.144 +    }
   1.145 +
   1.146 +    /**
   1.147 +     * Create a new HTTP service.
   1.148 +     *
   1.149 +     * @param proc             the processor to use on requests and responses
   1.150 +     * @param connStrategy     the connection reuse strategy
   1.151 +     * @param responseFactory  the response factory
   1.152 +     *
   1.153 +     * @deprecated use {@link HttpService#HttpService(HttpProcessor,
   1.154 +     *  ConnectionReuseStrategy, HttpResponseFactory, HttpRequestHandlerResolver, HttpParams)}
   1.155 +     */
   1.156 +    public HttpService(
   1.157 +            final HttpProcessor proc,
   1.158 +            final ConnectionReuseStrategy connStrategy,
   1.159 +            final HttpResponseFactory responseFactory) {
   1.160 +        super();
   1.161 +        setHttpProcessor(proc);
   1.162 +        setConnReuseStrategy(connStrategy);
   1.163 +        setResponseFactory(responseFactory);
   1.164 +    }
   1.165 +
   1.166 +    /**
   1.167 +     * @deprecated set {@link HttpProcessor} using constructor
   1.168 +     */
   1.169 +    public void setHttpProcessor(final HttpProcessor processor) {
   1.170 +        if (processor == null) {
   1.171 +            throw new IllegalArgumentException("HTTP processor may not be null");
   1.172 +        }
   1.173 +        this.processor = processor;
   1.174 +    }
   1.175 +
   1.176 +    /**
   1.177 +     * @deprecated set {@link ConnectionReuseStrategy} using constructor
   1.178 +     */
   1.179 +    public void setConnReuseStrategy(final ConnectionReuseStrategy connStrategy) {
   1.180 +        if (connStrategy == null) {
   1.181 +            throw new IllegalArgumentException("Connection reuse strategy may not be null");
   1.182 +        }
   1.183 +        this.connStrategy = connStrategy;
   1.184 +    }
   1.185 +
   1.186 +    /**
   1.187 +     * @deprecated set {@link HttpResponseFactory} using constructor
   1.188 +     */
   1.189 +    public void setResponseFactory(final HttpResponseFactory responseFactory) {
   1.190 +        if (responseFactory == null) {
   1.191 +            throw new IllegalArgumentException("Response factory may not be null");
   1.192 +        }
   1.193 +        this.responseFactory = responseFactory;
   1.194 +    }
   1.195 +
   1.196 +    /**
   1.197 +     * @deprecated set {@link HttpResponseFactory} using constructor
   1.198 +     */
   1.199 +    public void setParams(final HttpParams params) {
   1.200 +        this.params = params;
   1.201 +    }
   1.202 +
   1.203 +    /**
   1.204 +     * @deprecated set {@link HttpRequestHandlerResolver} using constructor
   1.205 +     */
   1.206 +    public void setHandlerResolver(final HttpRequestHandlerResolver handlerResolver) {
   1.207 +        this.handlerResolver = handlerResolver;
   1.208 +    }
   1.209 +
   1.210 +    /**
   1.211 +     * @deprecated set {@link HttpExpectationVerifier} using constructor
   1.212 +     */
   1.213 +    public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
   1.214 +        this.expectationVerifier = expectationVerifier;
   1.215 +    }
   1.216 +
   1.217 +    public HttpParams getParams() {
   1.218 +        return this.params;
   1.219 +    }
   1.220 +
   1.221 +    /**
   1.222 +     * Handles receives one HTTP request over the given connection within the
   1.223 +     * given execution context and sends a response back to the client.
   1.224 +     *
   1.225 +     * @param conn the active connection to the client
   1.226 +     * @param context the actual execution context.
   1.227 +     * @throws IOException in case of an I/O error.
   1.228 +     * @throws HttpException in case of HTTP protocol violation or a processing
   1.229 +     *   problem.
   1.230 +     */
   1.231 +    public void handleRequest(
   1.232 +            final HttpServerConnection conn,
   1.233 +            final HttpContext context) throws IOException, HttpException {
   1.234 +
   1.235 +        context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
   1.236 +
   1.237 +        HttpResponse response = null;
   1.238 +
   1.239 +        try {
   1.240 +
   1.241 +            HttpRequest request = conn.receiveRequestHeader();
   1.242 +            request.setParams(
   1.243 +                    new DefaultedHttpParams(request.getParams(), this.params));
   1.244 +
   1.245 +            ProtocolVersion ver =
   1.246 +                request.getRequestLine().getProtocolVersion();
   1.247 +            if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
   1.248 +                // Downgrade protocol version if greater than HTTP/1.1
   1.249 +                ver = HttpVersion.HTTP_1_1;
   1.250 +            }
   1.251 +
   1.252 +            if (request instanceof HttpEntityEnclosingRequest) {
   1.253 +
   1.254 +                if (((HttpEntityEnclosingRequest) request).expectContinue()) {
   1.255 +                    response = this.responseFactory.newHttpResponse(ver,
   1.256 +                            HttpStatus.SC_CONTINUE, context);
   1.257 +                    response.setParams(
   1.258 +                            new DefaultedHttpParams(response.getParams(), this.params));
   1.259 +
   1.260 +                    if (this.expectationVerifier != null) {
   1.261 +                        try {
   1.262 +                            this.expectationVerifier.verify(request, response, context);
   1.263 +                        } catch (HttpException ex) {
   1.264 +                            response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0,
   1.265 +                                    HttpStatus.SC_INTERNAL_SERVER_ERROR, context);
   1.266 +                            response.setParams(
   1.267 +                                    new DefaultedHttpParams(response.getParams(), this.params));
   1.268 +                            handleException(ex, response);
   1.269 +                        }
   1.270 +                    }
   1.271 +                    if (response.getStatusLine().getStatusCode() < 200) {
   1.272 +                        // Send 1xx response indicating the server expections
   1.273 +                        // have been met
   1.274 +                        conn.sendResponseHeader(response);
   1.275 +                        conn.flush();
   1.276 +                        response = null;
   1.277 +                        conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
   1.278 +                    }
   1.279 +                } else {
   1.280 +                    conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
   1.281 +                }
   1.282 +            }
   1.283 +
   1.284 +            if (response == null) {
   1.285 +                response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_OK, context);
   1.286 +                response.setParams(
   1.287 +                        new DefaultedHttpParams(response.getParams(), this.params));
   1.288 +
   1.289 +                context.setAttribute(ExecutionContext.HTTP_REQUEST, request);
   1.290 +                context.setAttribute(ExecutionContext.HTTP_RESPONSE, response);
   1.291 +
   1.292 +                this.processor.process(request, context);
   1.293 +                doService(request, response, context);
   1.294 +            }
   1.295 +
   1.296 +            // Make sure the request content is fully consumed
   1.297 +            if (request instanceof HttpEntityEnclosingRequest) {
   1.298 +                HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
   1.299 +                EntityUtils.consume(entity);
   1.300 +            }
   1.301 +
   1.302 +        } catch (HttpException ex) {
   1.303 +            response = this.responseFactory.newHttpResponse
   1.304 +                (HttpVersion.HTTP_1_0, HttpStatus.SC_INTERNAL_SERVER_ERROR,
   1.305 +                 context);
   1.306 +            response.setParams(
   1.307 +                    new DefaultedHttpParams(response.getParams(), this.params));
   1.308 +            handleException(ex, response);
   1.309 +        }
   1.310 +
   1.311 +        this.processor.process(response, context);
   1.312 +        conn.sendResponseHeader(response);
   1.313 +        conn.sendResponseEntity(response);
   1.314 +        conn.flush();
   1.315 +
   1.316 +        if (!this.connStrategy.keepAlive(response, context)) {
   1.317 +            conn.close();
   1.318 +        }
   1.319 +    }
   1.320 +
   1.321 +    /**
   1.322 +     * Handles the given exception and generates an HTTP response to be sent
   1.323 +     * back to the client to inform about the exceptional condition encountered
   1.324 +     * in the course of the request processing.
   1.325 +     *
   1.326 +     * @param ex the exception.
   1.327 +     * @param response the HTTP response.
   1.328 +     */
   1.329 +    protected void handleException(final HttpException ex, final HttpResponse response) {
   1.330 +        if (ex instanceof MethodNotSupportedException) {
   1.331 +            response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
   1.332 +        } else if (ex instanceof UnsupportedHttpVersionException) {
   1.333 +            response.setStatusCode(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED);
   1.334 +        } else if (ex instanceof ProtocolException) {
   1.335 +            response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
   1.336 +        } else {
   1.337 +            response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
   1.338 +        }
   1.339 +        byte[] msg = EncodingUtils.getAsciiBytes(ex.getMessage());
   1.340 +        ByteArrayEntity entity = new ByteArrayEntity(msg);
   1.341 +        entity.setContentType("text/plain; charset=US-ASCII");
   1.342 +        response.setEntity(entity);
   1.343 +    }
   1.344 +
   1.345 +    /**
   1.346 +     * The default implementation of this method attempts to resolve an
   1.347 +     * {@link HttpRequestHandler} for the request URI of the given request
   1.348 +     * and, if found, executes its
   1.349 +     * {@link HttpRequestHandler#handle(HttpRequest, HttpResponse, HttpContext)}
   1.350 +     * method.
   1.351 +     * <p>
   1.352 +     * Super-classes can override this method in order to provide a custom
   1.353 +     * implementation of the request processing logic.
   1.354 +     *
   1.355 +     * @param request the HTTP request.
   1.356 +     * @param response the HTTP response.
   1.357 +     * @param context the execution context.
   1.358 +     * @throws IOException in case of an I/O error.
   1.359 +     * @throws HttpException in case of HTTP protocol violation or a processing
   1.360 +     *   problem.
   1.361 +     */
   1.362 +    protected void doService(
   1.363 +            final HttpRequest request,
   1.364 +            final HttpResponse response,
   1.365 +            final HttpContext context) throws HttpException, IOException {
   1.366 +        HttpRequestHandler handler = null;
   1.367 +        if (this.handlerResolver != null) {
   1.368 +            String requestURI = request.getRequestLine().getUri();
   1.369 +            handler = this.handlerResolver.lookup(requestURI);
   1.370 +        }
   1.371 +        if (handler != null) {
   1.372 +            handler.handle(request, response, context);
   1.373 +        } else {
   1.374 +            response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
   1.375 +        }
   1.376 +    }
   1.377 +
   1.378 +}

mercurial