com.smartitengineering.util.rest.client.jersey.cache.CustomApacheHttpClientResponseResolver.java Source code

Java tutorial

Introduction

Here is the source code for com.smartitengineering.util.rest.client.jersey.cache.CustomApacheHttpClientResponseResolver.java

Source

/*
 * This is a utility project for wide range of applications
 *
 * Copyright (C) 2010  Imran M Yousuf (imyousuf@smartitengineering.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  10-1  USA
 */
package com.smartitengineering.util.rest.client.jersey.cache;

import org.apache.commons.lang.StringUtils;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.client.apache.ApacheHttpMethodExecutor;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import org.apache.commons.httpclient.ConnectMethod;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.OptionsMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.TraceMethod;
import org.codehaus.httpcache4j.HTTPException;
import org.codehaus.httpcache4j.HTTPMethod;
import org.codehaus.httpcache4j.HTTPRequest;
import org.codehaus.httpcache4j.HTTPResponse;
import org.codehaus.httpcache4j.HTTPVersion;
import org.codehaus.httpcache4j.Headers;
import org.codehaus.httpcache4j.Status;
import org.codehaus.httpcache4j.StatusLine;
import org.codehaus.httpcache4j.payload.DelegatingInputStream;
import org.codehaus.httpcache4j.resolver.ResponseCreator;
import org.codehaus.httpcache4j.resolver.ResponseResolver;
import static org.codehaus.httpcache4j.HTTPMethod.*;

/**
 *
 * @author hamnis
 * @author imyousuf
 */
public class CustomApacheHttpClientResponseResolver implements ResponseResolver {

    private ResponseCreator responseCreator = new ResponseCreator();
    private ApacheHttpMethodExecutor methodProcessor;
    private final ThreadLocal<ClientRequest> request;

    public CustomApacheHttpClientResponseResolver(ApacheHttpMethodExecutor methodProcessor,
            ThreadLocal<ClientRequest> reqLocal) {
        this.methodProcessor = methodProcessor;
        this.request = reqLocal;
    }

    @Override
    public void shutdown() {
        //Nothing to implement
        //TODO Here the connection managers should be shutdown
    }

    @Override
    public HTTPResponse resolve(HTTPRequest httpr) throws IOException {
        HttpMethod method = convertRequest(httpr);
        methodProcessor.executeMethod(method, request.get());
        return convertResponse(method);
    }

    private HttpMethod convertRequest(HTTPRequest request) {
        URI requestURI = request.getRequestURI();
        HttpMethod method = getMethod(request.getMethod(), requestURI);
        Headers requestHeaders = request.getAllHeaders();
        addHeaders(requestHeaders, method);
        method.setDoAuthentication(true);
        if (method instanceof EntityEnclosingMethod && request.hasPayload()) {
            InputStream payload = request.getPayload().getInputStream();
            EntityEnclosingMethod carrier = (EntityEnclosingMethod) method;
            if (payload != null) {
                carrier.setRequestEntity(new InputStreamRequestEntity(payload));
            }
        }

        return method;
    }

    private void addHeaders(Headers headers, HttpMethod method) {
        if (!headers.isEmpty()) {
            for (org.codehaus.httpcache4j.Header header : headers) {
                method.addRequestHeader(header.getName(), header.getValue());
            }
        }
    }

    private HTTPResponse convertResponse(HttpMethod method) {
        Headers headers = new Headers();
        for (Header header : method.getResponseHeaders()) {
            headers = headers.add(header.getName(), header.getValue());
        }
        InputStream stream = null;
        HTTPResponse response;
        try {
            stream = getInputStream(method);
            StatusLine line = new StatusLine(HTTPVersion.get(method.getStatusLine().getHttpVersion()),
                    Status.valueOf(method.getStatusCode()), method.getStatusText());
            response = responseCreator.createResponse(line, headers, stream);
        } finally {
            if (stream == null) {
                method.releaseConnection();
            }
        }
        return response;
    }

    private InputStream getInputStream(HttpMethod method) {
        try {
            return method.getResponseBodyAsStream() != null ? new HttpMethodStream(method) : null;
        } catch (IOException e) {
            method.releaseConnection();
            throw new HTTPException("Unable to get InputStream from HttpClient", e);
        }
    }

    /**
     * Determines the HttpClient's request method from the HTTPMethod enum.
     *
     * @param method     the HTTPCache enum that determines
     * @param requestURI the request URI.
     * @return a new HttpMethod subclass.
     */
    protected HttpMethod getMethod(HTTPMethod method, URI requestURI) {
        if (CONNECT.equals(method)) {
            HostConfiguration config = new HostConfiguration();
            config.setHost(requestURI.getHost(), requestURI.getPort(), requestURI.getScheme());
            return new ConnectMethod(config);
        } else if (DELETE.equals(method)) {
            return new CustomHttpMethod(HTTPMethod.DELETE.name(), requestURI.toString());
        } else if (GET.equals(method)) {
            return new GetMethod(requestURI.toString());
        } else if (HEAD.equals(method)) {
            return new HeadMethod(requestURI.toString());
        } else if (OPTIONS.equals(method)) {
            return new OptionsMethod(requestURI.toString());
        } else if (POST.equals(method)) {
            return new PostMethod(requestURI.toString());
        } else if (PUT.equals(method)) {
            return new PutMethod(requestURI.toString());
        } else if (TRACE.equals(method)) {
            return new TraceMethod(requestURI.toString());
        } else {
            return new CustomHttpMethod(method.name(), requestURI.toString());
        }
    }

    private static class CustomHttpMethod extends EntityEnclosingMethod {

        private final String name;

        public CustomHttpMethod(String name, String uri) {
            super(uri);
            if (StringUtils.isBlank(name)) {
                throw new IllegalArgumentException("Name can not be blank!");
            }
            this.name = name;
        }

        @Override
        public String getName() {
            return name;
        }
    }

    private static class HttpMethodStream extends DelegatingInputStream {

        private final HttpMethod method;

        public HttpMethodStream(final HttpMethod method) throws IOException {
            super(method.getResponseBodyAsStream());
            this.method = method;
        }

        @Override
        public void close() throws IOException {
            method.releaseConnection();
        }
    }
}