mixedserver.protocol.jsonrpc.client.HTTPSession.java Source code

Java tutorial

Introduction

Here is the source code for mixedserver.protocol.jsonrpc.client.HTTPSession.java

Source

/*
 * jabsorb - a Java to JavaScript Advanced Object Request Broker
 * http://www.jabsorb.org
 *
 * Copyright 2007-2009 The jabsorb team
 *
 * based on original code from
 * JSON-RPC-Client, a Java client extension to JSON-RPC-Java
 * (C) Copyright CodeBistro 2007, Sasha Ovsankin <sasha at codebistro dot com>
 *
 * Licensed 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 mixedserver.protocol.jsonrpc.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.zip.GZIPInputStream;

import mixedserver.protocol.RPCException;
import mixedserver.protocol.jsonrpc.client.TransportRegistry.SessionFactory;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Transport session straightforwardly implemented in HTTP. As compared to the
 * built-in URLConnectionSession, it allows more control over HTTP transport
 * parameters, for example, proxies and the support for HTTPS.
 * 
 * <p>
 * To use this transport you need to first register it in the TransportRegistry,
 * for example:
 * <p>
 * <code>
 *       HTTPSession.register(TransportRegistry.i());
 * </code>
 */
public class HTTPSession implements Session {
    private final static Logger logger = LoggerFactory.getLogger(HTTPSession.class);

    protected HttpClient client;

    protected URI uri;

    private int soTimeout = 3 * 60 * 1000; // 3

    private int connectionTimeout = 30 * 1000; // 30

    private Hashtable attributes;

    CookieStore cookieStore;

    HttpContext localContext;

    public HTTPSession(URI uri) {
        this.uri = uri;
        attributes = new Hashtable();

        cookieStore = new BasicCookieStore();
        localContext = new BasicHttpContext();

        // 
        localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
    }

    /**
     * As per JSON-RPC Working Draft
     * http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#RequestHeaders
     */
    static final String JSON_CONTENT_TYPE = "application/json";

    public String sendAndReceive(String message) throws RPCException {

        String responseString;
        HttpEntity entity;
        try {
            entity = new JSONEntity(message, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            throw new RPCException("Unsupported encoding");
        }

        responseString = sendEntity(entity);
        return responseString;
    }

    private String sendEntity(HttpEntity entity) throws RPCException {
        HttpPost request = new HttpPost(this.uri);
        request.setEntity(entity);

        HttpResponse response;
        String responseString = null;
        try {
            Date before = new Date();
            response = http().execute(request, localContext);
            Date after = new Date();

            logger.debug("" + (after.getTime() - before.getTime()));

            responseString = EntityUtils.toString(response.getEntity());
            responseString = responseString.trim();

        } catch (ClientProtocolException e) {
            throw new RPCException("???");
        } catch (IOException e) {
            throw new RPCException("", RPCException.ERROR_CODE_NETWORK_ERROR);
        } catch (Exception e) {
            if (e.getClass().getName().equals("NetworkOnMainThreadException")) {
                throw new RPCException("????");
            }

            throw new RPCException("http:" + e.getMessage());
        }

        return responseString;
    }

    HttpClient http() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException,
            KeyStoreException, CertificateException, IOException {
        if (client == null) {
            HttpParams params = new BasicHttpParams();

            HttpConnectionParams.setConnectionTimeout(params, getConnectionTimeout());
            HttpConnectionParams.setSoTimeout(params, getSoTimeout());
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new EasySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));

            /*
             * ClientConnectionManager mgr = new ThreadSafeClientConnManager(
             * params, registry);
             */

            ClientConnectionManager mgr = new ThreadSafeClientConnManager(params, registry);

            DefaultHttpClient defaultHttpClient = new DefaultHttpClient(mgr, params);

            // gzip?
            defaultHttpClient.addRequestInterceptor(new HttpRequestInterceptor() {

                public void process(final HttpRequest request, final HttpContext context)
                        throws HttpException, IOException {
                    if (!request.containsHeader("Accept-Encoding")) {
                        request.addHeader("Accept-Encoding", "gzip");
                    }
                }

            });

            defaultHttpClient.addResponseInterceptor(new HttpResponseInterceptor() {

                public void process(final HttpResponse response, final HttpContext context)
                        throws HttpException, IOException {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        Header ceheader = entity.getContentEncoding();
                        if (ceheader != null) {
                            HeaderElement[] codecs = ceheader.getElements();
                            for (int i = 0; i < codecs.length; i++) {
                                if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                                    response.setEntity(new GzipDecompressingEntity(response.getEntity()));
                                    return;
                                }
                            }
                        }
                    }
                }

            });
            client = defaultHttpClient;
        }
        return client;
    }

    public void close() {
        //
    }

    static class Factory implements SessionFactory {
        public Session newSession(URI uri) {
            return new HTTPSession(uri);
        }
    }

    /**
     * Register this transport in 'registry'
     */
    public static void register(TransportRegistry registry) {
        Factory f = new Factory();
        registry.registerTransport("http", f);
        registry.registerTransport("https", f);
    }

    /*
     * @Override public String login(String username, String password) { try {
     * 
     * JSONObject jsonRequest = new JSONObject(); jsonRequest.put("method",
     * "authority.login"); jsonRequest.put("jsonrpc", "2.0");
     * 
     * JSONArray params = new JSONArray(); params.put(username);
     * params.put(password); jsonRequest.put("params", params);
     * 
     * // ? JSONObject jsonObj = sendAndReceive(jsonRequest);
     * 
     * if (jsonObj.has("error")) { throw new ClientError("??"); } else {
     * return jsonObj.getString("result"); } } catch (JSONException e) { throw
     * new ClientError(e); }
     * 
     * }
     */

    /**
     * Get the socket operation timeout in milliseconds
     */
    public int getSoTimeout() {
        return soTimeout;
    }

    /**
     * Set the socket operation timeout
     * 
     * @param soTimeout
     *            timeout in milliseconds
     */
    public void setSoTimeout(int soTimeout) {
        this.soTimeout = soTimeout;
    }

    /**
     * Get the connection timeout in milliseconds
     */
    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    /**
     * Set the connection timeout
     * 
     * @param connectionTimeout
     *            timeout in milliseconds
     */
    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    @Override
    public void setAttribute(String key, Object value) {
        this.attributes.put(key, value);
    }

    @Override
    public Object getAttribute(String key) {
        return this.attributes.get(key);
    }

    @Override
    public String getSessionId() {
        List<Cookie> cookies = cookieStore.getCookies();
        for (int i = 0; i < cookies.size(); i++) {
            Cookie c = cookies.get(i);
            if (c.getName().equals(getSessionKey())) {
                return c.getValue();
            }
        }

        return null;
    }

    @Override
    public String getSessionKey() {
        return "JSESSIONID";
    }

    @Override
    public void removeAttribute(String key) {
        attributes.remove(key);
    }

    @Override
    public void removeAllAttribute() {
        attributes.clear();
    }

    public void setCookie(String name, String value) {
        BasicClientCookie cookie = new BasicClientCookie(name, value);
        cookie.setDomain(uri.getHost());
        cookie.setPath(uri.getPath());
        cookieStore.addCookie(cookie);
    }

    public class GzipDecompressingEntity extends DecompressingEntity {

        /**
         * Creates a new {@link GzipDecompressingEntity} which will wrap the
         * specified {@link HttpEntity}.
         * 
         * @param entity
         *            the non-null {@link HttpEntity} to be wrapped
         */
        public GzipDecompressingEntity(final HttpEntity entity) {
            super(entity);
        }

        @Override
        InputStream decorate(final InputStream wrapped) throws IOException {
            return new GZIPInputStream(wrapped);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Header getContentEncoding() {
            /* This HttpEntityWrapper has dealt with the Content-Encoding. */
            return null;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public long getContentLength() {
            /* length of ungzipped content is not known */
            return -1;
        }
    }

    @Override
    public String getCookie(String name) {
        List<Cookie> cookies = cookieStore.getCookies();
        for (int i = 0; i < cookies.size(); i++) {
            Cookie c = cookies.get(i);
            if (c.getName().equals(name)) {
                return c.getValue();
            }
        }

        return null;
    }
}