com.bnrc.http.AbHttpClient.java Source code

Java tutorial

Introduction

Here is the source code for com.bnrc.http.AbHttpClient.java

Source

/*
 * Copyright (C) 2012 www.amsoft.cn
 * 
 * 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 com.bnrc.http;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
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.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.params.ConnRoutePNames;
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.scheme.SocketFactory;
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.ExecutionContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.bnrc.global.AbAppConfig;
import com.bnrc.global.AbAppException;
import com.bnrc.task.AbThreadFactory;
import com.bnrc.util.AbAppUtil;
import com.bnrc.util.AbFileUtil;
import com.bnrc.util.AbLogUtil;

// TODO: Auto-generated Javadoc
/**
 * ? 2012 amsoft.cn
 * ?bHttpClient.java 
 * ttp
 *
 * @author ?
 * @version v1.0
 * @date2013-11-13 ?9:00:52
 */
public class AbHttpClient {

    /** ??. */
    private static Context mContext;

    /** ?. */
    public static Executor mExecutorService = null;

    /** . */
    private String encode = HTTP.UTF_8;

    /** ?. */
    private String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 BIDUBrowser/6.x Safari/537.31";

    private static final String HTTP_GET = "GET";
    private static final String HTTP_POST = "POST";
    private static final String USER_AGENT = "User-Agent";
    private static final String ACCEPT_ENCODING = "Accept-Encoding";

    /** CookieStore. */
    private CookieStore mCookieStore;

    /** ?. */
    private static final int DEFAULT_MAX_CONNECTIONS = 10;

    /** ?. */
    public static final int DEFAULT_SOCKET_TIMEOUT = 10000;

    /** . */
    private static final int DEFAULT_MAX_RETRIES = 3;

    /** . */
    private static final int DEFAULT_SOCKET_BUFFER_SIZE = 8192;

    /** . */
    private static final int BUFFER_SIZE = 4096;

    /** . */
    protected static final int SUCCESS_MESSAGE = 0;

    /** . */
    protected static final int FAILURE_MESSAGE = 1;

    /** ????. */
    protected static final int FAILURE_MESSAGE_CONNECT = 2;

    /** ????. */
    protected static final int FAILURE_MESSAGE_SERVICE = 3;

    /** . */
    protected static final int START_MESSAGE = 4;

    /** . */
    protected static final int FINISH_MESSAGE = 5;

    /** ?. */
    protected static final int PROGRESS_MESSAGE = 6;

    /** . */
    protected static final int RETRY_MESSAGE = 7;

    /** ?. */
    private int mTimeout = DEFAULT_SOCKET_TIMEOUT;

    /** . ?HTTPS?SSL?*/
    private boolean mIsOpenEasySSL = true;

    /** HTTP Client*/
    private DefaultHttpClient mHttpClient = null;

    /** HTTP ??*/
    private HttpContext mHttpContext = null;

    /**
     * ????.
     *
     * @param context the context
     */
    public AbHttpClient(Context context) {
        mContext = context;
        mExecutorService = AbThreadFactory.getExecutorService();
        mHttpContext = new BasicHttpContext();
    }

    /**
     * ??et.
     *
     * @param url the url
     * @param params the params
     * @param responseListener the response listener
     */
    public void get(final String url, final AbRequestParams params, final AbHttpResponseListener responseListener) {

        responseListener.setHandler(new ResponderHandler(responseListener));
        mExecutorService.execute(new Runnable() {
            public void run() {
                try {
                    doGet(url, params, responseListener);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * ??ost.
     *
     * @param url the url
     * @param params the params
     * @param responseListener the response listener
     */
    public void post(final String url, final AbRequestParams params,
            final AbHttpResponseListener responseListener) {
        responseListener.setHandler(new ResponderHandler(responseListener));
        mExecutorService.execute(new Runnable() {
            public void run() {
                try {
                    doPost(url, params, responseListener);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * ?et.
     *
     * @param url the url
     * @param params the params
     * @param responseListener the response listener
     */
    private void doGet(String url, AbRequestParams params, AbHttpResponseListener responseListener) {
        try {

            responseListener.sendStartMessage();

            if (!AbAppUtil.isNetworkAvailable(mContext)) {
                responseListener.sendFailureMessage(AbHttpStatus.CONNECT_FAILURE_CODE,
                        AbAppConfig.CONNECT_EXCEPTION, new AbAppException(AbAppConfig.CONNECT_EXCEPTION));
                return;
            }

            //HttpGet?  
            if (params != null) {
                url += params.getParamString();
            }
            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader(USER_AGENT, userAgent);
            //?
            httpGet.addHeader(ACCEPT_ENCODING, "gzip");
            //??ttpClient
            HttpClient httpClient = getHttpClient();
            //?HttpResponse
            String response = httpClient.execute(httpGet, new RedirectionResponseHandler(url, responseListener),
                    mHttpContext);
            AbLogUtil.i(mContext, "[HTTP Request]:" + url + ",result" + response);
        } catch (Exception e) {
            e.printStackTrace();
            //???
            responseListener.sendFailureMessage(AbHttpStatus.UNTREATED_CODE, e.getMessage(), new AbAppException(e));
        } finally {
            responseListener.sendFinishMessage();
        }
    }

    /**
     * ?ost.
     *
     * @param url the url
     * @param params the params
     * @param responseListener the response listener
     */
    private void doPost(String url, AbRequestParams params, AbHttpResponseListener responseListener) {
        try {
            responseListener.sendStartMessage();

            if (!AbAppUtil.isNetworkAvailable(mContext)) {
                responseListener.sendFailureMessage(AbHttpStatus.CONNECT_FAILURE_CODE,
                        AbAppConfig.CONNECT_EXCEPTION, new AbAppException(AbAppConfig.CONNECT_EXCEPTION));
                return;
            }

            //HttpPost?  
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader(USER_AGENT, userAgent);
            //?
            httpPost.addHeader(ACCEPT_ENCODING, "gzip");
            //????
            boolean isContainFile = false;
            if (params != null) {
                //NameValuePair?Post??? 
                HttpEntity httpentity = params.getEntity(responseListener);
                //httpRequest  
                httpPost.setEntity(httpentity);
                if (params.getFileParams().size() > 0) {
                    isContainFile = true;
                }
            }
            String response = null;
            //??ttpClient
            DefaultHttpClient httpClient = getHttpClient();
            if (isContainFile) {
                AbLogUtil.i(mContext, "request" + url + ",???!");
            } else {
            }
            //?HttpResponse
            response = httpClient.execute(httpPost, new RedirectionResponseHandler(url, responseListener),
                    mHttpContext);
            AbLogUtil.i(mContext, "request" + url + ",result" + response);

        } catch (Exception e) {
            e.printStackTrace();
            AbLogUtil.i(mContext, "request" + url + ",error" + e.getMessage());
            //???
            responseListener.sendFailureMessage(AbHttpStatus.UNTREATED_CODE, e.getMessage(), new AbAppException(e));
        } finally {
            responseListener.sendFinishMessage();
        }
    }

    /**
     * ????.
     * 
     * @param context the context
     * @param entity the entity
     * @param name the name
     * @param responseListener the response listener
     */
    public void writeResponseData(Context context, HttpEntity entity, String name,
            AbFileHttpResponseListener responseListener) {

        if (entity == null) {
            return;
        }

        if (responseListener.getFile() == null) {
            //??
            responseListener.setFile(context, name);
        }

        InputStream inStream = null;
        FileOutputStream outStream = null;
        try {
            inStream = entity.getContent();
            long contentLength = entity.getContentLength();
            outStream = new FileOutputStream(responseListener.getFile());
            if (inStream != null) {

                byte[] tmp = new byte[BUFFER_SIZE];
                int l, count = 0;
                while ((l = inStream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) {
                    count += l;
                    outStream.write(tmp, 0, l);
                    responseListener.sendProgressMessage(count, (int) contentLength);
                }
            }
            responseListener.sendSuccessMessage(200);
        } catch (Exception e) {
            e.printStackTrace();
            //???
            responseListener.sendFailureMessage(AbHttpStatus.RESPONSE_TIMEOUT_CODE,
                    AbAppConfig.SOCKET_TIMEOUT_EXCEPTION, e);
        } finally {
            try {
                if (inStream != null) {
                    inStream.close();
                }
                if (outStream != null) {
                    outStream.flush();
                    outStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * ????.
     *
     * @param entity the entity
     * @param responseListener the response listener
     */
    public void readResponseData(HttpEntity entity, AbBinaryHttpResponseListener responseListener) {

        if (entity == null) {
            return;
        }

        InputStream inStream = null;
        ByteArrayOutputStream outSteam = null;

        try {
            inStream = entity.getContent();
            outSteam = new ByteArrayOutputStream();
            long contentLength = entity.getContentLength();
            if (inStream != null) {
                int l, count = 0;
                byte[] tmp = new byte[BUFFER_SIZE];
                while ((l = inStream.read(tmp)) != -1) {
                    count += l;
                    outSteam.write(tmp, 0, l);
                    responseListener.sendProgressMessage(count, (int) contentLength);

                }
            }
            responseListener.sendSuccessMessage(HttpStatus.SC_OK, outSteam.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
            //???
            responseListener.sendFailureMessage(AbHttpStatus.RESPONSE_TIMEOUT_CODE,
                    AbAppConfig.SOCKET_TIMEOUT_EXCEPTION, e);
        } finally {
            try {
                if (inStream != null) {
                    inStream.close();
                }
                if (outSteam != null) {
                    outSteam.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * ?.
     *
     * @param timeout ?
     */
    public void setTimeout(int timeout) {
        this.mTimeout = timeout;
    }

    /**
     * ? 2012 amsoft.cn
     * ?esponderHandler.java 
     * ??
     *
     * @author ?
     * @version v1.0
     * @date2013-11-13 ?3:22:30
     */
    private static class ResponderHandler extends Handler {

        /** ?????. */
        private Object[] response;

        /** ????. */
        private AbHttpResponseListener responseListener;

        /**
         * ??.
         *
         * @param responseListener the response listener
         */
        public ResponderHandler(AbHttpResponseListener responseListener) {
            this.responseListener = responseListener;
        }

        /* (non-Javadoc)
         * @see android.os.Handler#handleMessage(android.os.Message)
         */
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {

            case SUCCESS_MESSAGE:
                response = (Object[]) msg.obj;

                if (response != null) {
                    if (responseListener instanceof AbStringHttpResponseListener) {
                        if (response.length >= 2) {
                            ((AbStringHttpResponseListener) responseListener).onSuccess((Integer) response[0],
                                    (String) response[1]);
                        } else {
                            AbLogUtil.e(mContext, "SUCCESS_MESSAGE " + AbAppConfig.MISSING_PARAMETERS);
                        }

                    } else if (responseListener instanceof AbBinaryHttpResponseListener) {
                        if (response.length >= 2) {
                            ((AbBinaryHttpResponseListener) responseListener).onSuccess((Integer) response[0],
                                    (byte[]) response[1]);
                        } else {
                            AbLogUtil.e(mContext, "SUCCESS_MESSAGE " + AbAppConfig.MISSING_PARAMETERS);
                        }
                    } else if (responseListener instanceof AbFileHttpResponseListener) {

                        if (response.length >= 1) {
                            AbFileHttpResponseListener mAbFileHttpResponseListener = ((AbFileHttpResponseListener) responseListener);
                            mAbFileHttpResponseListener.onSuccess((Integer) response[0],
                                    mAbFileHttpResponseListener.getFile());
                        } else {
                            AbLogUtil.e(mContext, "SUCCESS_MESSAGE " + AbAppConfig.MISSING_PARAMETERS);
                        }

                    }
                }
                break;
            case FAILURE_MESSAGE:
                response = (Object[]) msg.obj;
                if (response != null && response.length >= 3) {
                    //????
                    AbAppException exception = new AbAppException((Exception) response[2]);
                    responseListener.onFailure((Integer) response[0], (String) response[1], exception);
                } else {
                    AbLogUtil.e(mContext, "FAILURE_MESSAGE " + AbAppConfig.MISSING_PARAMETERS);
                }
                break;
            case START_MESSAGE:
                responseListener.onStart();
                break;
            case FINISH_MESSAGE:
                responseListener.onFinish();
                break;
            case PROGRESS_MESSAGE:
                response = (Object[]) msg.obj;
                if (response != null && response.length >= 2) {
                    responseListener.onProgress((Integer) response[0], (Integer) response[1]);
                } else {
                    AbLogUtil.e(mContext, "PROGRESS_MESSAGE " + AbAppConfig.MISSING_PARAMETERS);
                }
                break;
            case RETRY_MESSAGE:
                responseListener.onRetry();
                break;
            default:
                break;
            }
        }

    }

    /**
     * HTTP?
     * @return
     */
    public BasicHttpParams getHttpParams() {

        BasicHttpParams httpParams = new BasicHttpParams();

        // ??
        ConnPerRouteBean connPerRoute = new ConnPerRouteBean(30);
        ConnManagerParams.setMaxConnectionsPerRoute(httpParams, connPerRoute);
        HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);
        // ??????1
        ConnManagerParams.setTimeout(httpParams, mTimeout);
        ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_MAX_CONNECTIONS));
        ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);
        // ???
        HttpConnectionParams.setSoTimeout(httpParams, mTimeout);
        HttpConnectionParams.setConnectionTimeout(httpParams, mTimeout);
        HttpConnectionParams.setTcpNoDelay(httpParams, true);
        HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

        HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setUserAgent(httpParams, userAgent);
        //?
        HttpClientParams.setRedirecting(httpParams, false);
        HttpClientParams.setCookiePolicy(httpParams, CookiePolicy.BROWSER_COMPATIBILITY);
        httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, null);
        return httpParams;

    }

    /**
     * HttpClient?????uthSSLProtocolSocketFactory
     * @return
     */
    public DefaultHttpClient getHttpClient() {

        if (mHttpClient != null) {
            return mHttpClient;
        } else {
            return createHttpClient();
        }
    }

    /**
     * HttpClient?????uthSSLProtocolSocketFactory
     * @param httpParams
     * @return
     */
    public DefaultHttpClient createHttpClient() {
        BasicHttpParams httpParams = getHttpParams();
        if (mIsOpenEasySSL) {
            // ?https?   SSL??
            EasySSLProtocolSocketFactory easySSLProtocolSocketFactory = new EasySSLProtocolSocketFactory();
            SchemeRegistry supportedSchemes = new SchemeRegistry();
            SocketFactory socketFactory = PlainSocketFactory.getSocketFactory();
            supportedSchemes.register(new Scheme("http", socketFactory, 80));
            supportedSchemes.register(new Scheme("https", easySSLProtocolSocketFactory, 443));
            //???hreadSafeClientConnManager????ttpClient
            ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams,
                    supportedSchemes);
            //?HttpClient ThreadSafeClientConnManager
            mHttpClient = new DefaultHttpClient(connectionManager, httpParams);
        } else {
            //???ttpClient
            mHttpClient = new DefaultHttpClient(httpParams);
        }
        //?
        mHttpClient.setHttpRequestRetryHandler(mRequestRetryHandler);
        mHttpClient.setCookieStore(mCookieStore);
        return mHttpClient;
    }

    /**
     * ??ssl ??
     */
    public boolean isOpenEasySSL() {
        return mIsOpenEasySSL;
    }

    /**
     * ssl ??
     * @param isOpenEasySSL
     */
    public void setOpenEasySSL(boolean isOpenEasySSL) {
        this.mIsOpenEasySSL = isOpenEasySSL;
    }

    /**
     * ResponseHandler??,??
     */
    private class RedirectionResponseHandler implements ResponseHandler<String> {

        private AbHttpResponseListener mResponseListener = null;
        private String mUrl = null;

        public RedirectionResponseHandler(String url, AbHttpResponseListener responseListener) {
            super();
            this.mUrl = url;
            this.mResponseListener = responseListener;
        }

        @Override
        public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
            HttpUriRequest request = (HttpUriRequest) mHttpContext.getAttribute(ExecutionContext.HTTP_REQUEST);
            //  
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            String responseBody = null;
            //200????
            if (statusCode == HttpStatus.SC_OK) {

                // ??esponse body   
                // request?bort?  
                // request.abort();  

                if (entity != null) {
                    if (mResponseListener instanceof AbStringHttpResponseListener) {
                        //entity?????,?Content has been consumed
                        //???
                        Header header = entity.getContentEncoding();
                        if (header != null) {
                            String contentEncoding = header.getValue();
                            if (contentEncoding != null) {
                                if (contentEncoding.contains("gzip")) {
                                    entity = new AbGzipDecompressingEntity(entity);
                                }
                            }
                        }
                        String charset = EntityUtils.getContentCharSet(entity) == null ? encode
                                : EntityUtils.getContentCharSet(entity);
                        responseBody = new String(EntityUtils.toByteArray(entity), charset);

                        ((AbStringHttpResponseListener) mResponseListener).sendSuccessMessage(statusCode,
                                responseBody);
                    } else if (mResponseListener instanceof AbBinaryHttpResponseListener) {
                        responseBody = "Binary";
                        readResponseData(entity, ((AbBinaryHttpResponseListener) mResponseListener));
                    } else if (mResponseListener instanceof AbFileHttpResponseListener) {
                        //??
                        String fileName = AbFileUtil.getCacheFileNameFromUrl(mUrl, response);
                        writeResponseData(mContext, entity, fileName,
                                ((AbFileHttpResponseListener) mResponseListener));
                    }
                    //?!!!
                    try {
                        entity.consumeContent();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return responseBody;
                }

            }
            //301 302??
            else if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY
                    || statusCode == HttpStatus.SC_MOVED_PERMANENTLY) {
                // ?????
                Header locationHeader = response.getLastHeader("location");
                String location = locationHeader.getValue();
                if (request.getMethod().equalsIgnoreCase(HTTP_POST)) {
                    doPost(location, null, mResponseListener);
                } else if (request.getMethod().equalsIgnoreCase(HTTP_GET)) {
                    doGet(location, null, mResponseListener);
                }
            } else if (statusCode == HttpStatus.SC_NOT_FOUND) {
                //404
                mResponseListener.sendFailureMessage(statusCode, AbAppConfig.NOT_FOUND_EXCEPTION,
                        new AbAppException(AbAppConfig.NOT_FOUND_EXCEPTION));
            } else {
                mResponseListener.sendFailureMessage(statusCode, AbAppConfig.REMOTE_SERVICE_EXCEPTION,
                        new AbAppException(AbAppConfig.REMOTE_SERVICE_EXCEPTION));
            }
            return null;
        }
    }

    /**
     * ?
     */
    private HttpRequestRetryHandler mRequestRetryHandler = new HttpRequestRetryHandler() {

        // ??
        public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
            // ??????DEFAULT_MAX_RETRIES
            if (executionCount >= DEFAULT_MAX_RETRIES) {
                // ??????????
                AbLogUtil.d(mContext, "????");
                return false;
            }
            if (exception instanceof NoHttpResponseException) {
                // ??????
                AbLogUtil.d(mContext, "???");
                return true;
            }
            if (exception instanceof SSLHandshakeException) {
                // SSL
                AbLogUtil.d(mContext, "ssl  ");
                return false;
            }
            HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
            boolean idempotent = (request instanceof HttpEntityEnclosingRequest);
            if (!idempotent) {
                // ????????
                AbLogUtil.d(mContext, "???");
                return true;
            }
            if (exception != null) {
                return true;
            }
            return false;
        }
    };

    /**
     * ?
     * @return
     */
    public String getUserAgent() {
        return userAgent;
    }

    /**
     * ??
     * @param userAgent
     */
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }

    /**
      * 
      * @return
      */
    public String getEncode() {
        return encode;
    }

    /**
     * ?
     * @param encode
     */
    public void setEncode(String encode) {
        this.encode = encode;
    }

    /**
     * ??HttpClient
     */
    public void shutdown() {
        if (mHttpClient != null && mHttpClient.getConnectionManager() != null) {
            mHttpClient.getConnectionManager().shutdown();
        }
    }

    public CookieStore getCookieStore() {
        if (mHttpClient != null) {
            mCookieStore = mHttpClient.getCookieStore();
        }
        return mCookieStore;
    }

    public void setCookieStore(CookieStore cookieStore) {
        this.mCookieStore = cookieStore;
    }

}