com.polyvi.xface.http.XHttpWorker.java Source code

Java tutorial

Introduction

Here is the source code for com.polyvi.xface.http.XHttpWorker.java

Source

/*
 Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface)
 This program is distributed under the terms of the GNU General Public License.
    
 This file is part of xFace.
    
 xFace is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 xFace 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 General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with xFace.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.polyvi.xface.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
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.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
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.entity.HttpEntityWrapper;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.SyncBasicHttpContext;

import com.polyvi.xface.ssl.XSSLSocketFactory;
import com.polyvi.xface.util.XStringUtils;

/**
 * Http?
 *
 */
public class XHttpWorker {

    /**  */
    private static final int SERVER_CONNECT_TIMEOUT = 10000;
    private static final int DEFAULT_MAX_CONNECTIONS = 10;
    private static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000;
    private static int maxConnections = DEFAULT_MAX_CONNECTIONS;
    private static int socketTimeout = DEFAULT_SOCKET_TIMEOUT;
    private static final int DEFAULT_SOCKET_BUFFER_SIZE = 8192;
    private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
    private static final String ENCODING_GZIP = "gzip";

    /**url???*/
    private static final String TAG_URL_REGEX = "https?://([\\w]+\\.)+[\\w-]+(:\\d*)?(/[\\w-./?%&=]*)?$";
    private static final String TAG_URL_INVALID_MSG = "url is invalid";

    private AbstractHttpClient mHttpClient;
    private HttpContext mHttpContext;
    private Map<String, String> mClientHeaderMap;
    private ThreadPoolExecutor mThreadPool;
    /**  */
    private List<WeakReference<Future<?>>> mRequestList = new LinkedList<WeakReference<Future<?>>>();

    public XHttpWorker() {
        mThreadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        mClientHeaderMap = new HashMap<String, String>();
        initHttpClient();
    }

    /**
     * ?httpclient
     */
    private void initHttpClient() {
        BasicHttpParams httpParams = new BasicHttpParams();
        ConnManagerParams.setTimeout(httpParams, socketTimeout);
        ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections));
        ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);

        HttpConnectionParams.setSoTimeout(httpParams, socketTimeout);
        HttpConnectionParams.setConnectionTimeout(httpParams, socketTimeout);
        HttpConnectionParams.setTcpNoDelay(httpParams, true);
        HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

        HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setUserAgent(httpParams, "xface");

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", XSSLSocketFactory.getSocketFactory(), 443));
        schemeRegistry.register(new Scheme("https", XSSLSocketFactory.getSocketFactory(), 8443));
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
        mHttpClient = new DefaultHttpClient(cm, httpParams);
        mHttpClient.addRequestInterceptor(new HttpRequestInterceptor() {
            @Override
            public void process(HttpRequest request, HttpContext context) {
                if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
                    request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
                }
                for (String header : mClientHeaderMap.keySet()) {
                    request.addHeader(header, mClientHeaderMap.get(header));
                }
            }
        });

        mHttpClient.addResponseInterceptor(new HttpResponseInterceptor() {
            @Override
            public void process(HttpResponse response, HttpContext context) {
                final HttpEntity entity = response.getEntity();
                if (entity == null) {
                    return;
                }
                final Header encoding = entity.getContentEncoding();
                if (encoding != null) {
                    for (HeaderElement element : encoding.getElements()) {
                        if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
                            response.setEntity(new InflatingEntity(response.getEntity()));
                            break;
                        }
                    }
                }
            }
        });
        mHttpContext = new SyncBasicHttpContext(new BasicHttpContext());
    }

    /**
     * http post()
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param postData
     *            post??
     * @param contentType
     *            ?
     * @param handler
     *            http??
     */
    public void post(String url, Header[] headers, String postData, String contentType,
            XAsyncHttpResponseHandler handler) throws IllegalArgumentException, IOException {
        checkUrlValid(url);
        HttpEntity entity = null;
        if (postData != null) {
            try {
                entity = new StringEntity(postData);
            } catch (UnsupportedEncodingException e) {
                throw e;
            }
        }
        this.post(url, headers, entity, contentType, handler);
    }

    /**
     * http post()
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param postData
     *            post??
     * @param contentType
     *            ?
     * @param handler
     *            http??
     */
    public void post(String url, Header[] headers, HttpEntity postData, String contentType,
            XAsyncHttpResponseHandler handler) throws IllegalArgumentException, IOException {
        checkUrlValid(url);
        HttpPost post = new HttpPost(url);
        this.setHeader(post, headers);
        doHttpRequest(addEntityToRequestBase(post, postData), contentType, handler);

    }

    /**
     * http post(?)
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param postData
     *            post??
     * @param contentType
     *            ?
     * @param handler
     *            http??
     */
    public XSynHttpResponse post(String url, Header[] headers, String postData, String contentType)
            throws IllegalArgumentException, IOException {
        checkUrlValid(url);
        XSyncHttpResponseHandler handler = new XSyncHttpResponseHandler();
        this.post(url, headers, postData, contentType, handler);
        return handler.getHttpResponse();
    }

    /**
     * http post(?)
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param postData
     *            post??
     * @param contentType
     *            ?
     * @param handler
     *            http??
     */
    public XSynHttpResponse post(String url, Header[] headers, HttpEntity postData, String contentType)
            throws IllegalArgumentException, IOException {
        checkUrlValid(url);
        XSyncHttpResponseHandler handler = new XSyncHttpResponseHandler();
        this.post(url, headers, postData, contentType, handler);
        return handler.getHttpResponse();
    }

    /**
     * http get(?)
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param handler
     *            http??
     */
    public XSynHttpResponse get(String url, Header[] headers) throws IllegalArgumentException {
        checkUrlValid(url);
        XSyncHttpResponseHandler handler = new XSyncHttpResponseHandler();
        this.get(url, headers, handler);
        return handler.getHttpResponse();
    }

    /**
     * http get()
     *
     * @param url
     *            url?
     * @param headers
     *            
     * @param handler
     *            http??
     */
    public void get(String url, Header[] headers, XAsyncHttpResponseHandler handler)
            throws IllegalArgumentException {
        checkUrlValid(url);
        HttpGet get = new HttpGet(url);
        this.setHeader(get, headers);
        doHttpRequest(get, null, handler);
    }

    /**
     * ?
     *
     * @param mayInterruptIfRunning
     */
    public void cancelRequest(boolean mayInterruptIfRunning) {
        for (WeakReference<Future<?>> requestRef : mRequestList) {
            Future<?> request = requestRef.get();
            if (request != null) {
                request.cancel(mayInterruptIfRunning);
            }
        }
    }

    /**
     *  
     *
     * @param request
     * @param headers
     */
    private void setHeader(HttpUriRequest request, Header[] headers) {
        if (headers != null)
            request.setHeaders(headers);
    }

    /**
     * ??http
     *
     * @param request
     * @param contentType
     * @param handler
     */
    private void doHttpRequest(HttpUriRequest request, String contentType, XAsyncHttpResponseHandler handler) {
        if (contentType != null) {
            request.addHeader("Content-Type", contentType);
        }
        if (handler.isAsync()) {
            Future<?> task = mThreadPool.submit(new XAsyncHttpRequest(mHttpClient, mHttpContext, request, handler));
            mRequestList.add(new WeakReference<Future<?>>(task));
        } else {
            new XAsyncHttpRequest(mHttpClient, mHttpContext, request, handler).run();
        }

    }

    /**
     * httppost
     *
     * @param requestBase
     * @param entity
     * @return
     */
    private HttpEntityEnclosingRequestBase addEntityToRequestBase(HttpEntityEnclosingRequestBase requestBase,
            HttpEntity entity) {
        if (entity != null) {
            requestBase.setEntity(entity);
        }

        return requestBase;
    }

    /**
     *  http
     *
     * @param header
     * @param value
     */
    public void addHeader(String header, String value) {
        mClientHeaderMap.put(header, value);
    }

    /**
     * url???
     *
     * @param url
     *            [in]
     * @return
     */
    public static boolean isServerAccessable(String url) {
        boolean usable = false;
        try {
            URL urlCon = new URL(url);
            HttpURLConnection httpUrl = (HttpURLConnection) urlCon.openConnection();
            httpUrl.setConnectTimeout(SERVER_CONNECT_TIMEOUT);
            httpUrl.setReadTimeout(SERVER_CONNECT_TIMEOUT);
            if (httpUrl.getResponseCode() == HttpURLConnection.HTTP_OK) {
                usable = true;
                return usable;
            }
        } catch (IOException e) {
            usable = false;
            e.printStackTrace();
        }
        return usable;
    }

    /**
     * gzip??
     */
    private static class InflatingEntity extends HttpEntityWrapper {
        public InflatingEntity(HttpEntity wrapped) {
            super(wrapped);
        }

        @Override
        public InputStream getContent() throws IOException {
            return new GZIPInputStream(wrappedEntity.getContent());
        }

        @Override
        public long getContentLength() {
            return -1;
        }
    }

    /**
     * url?
     * @param url:?url
     * @throws IllegalArgumentException
     */
    private void checkUrlValid(String url) throws IllegalArgumentException {
        if (XStringUtils.isEmptyString(url) || !Pattern.matches(TAG_URL_REGEX, url)) {
            throw new IllegalArgumentException(TAG_URL_INVALID_MSG);
        }
    }
}