com.android.idtt.http.HttpHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.android.idtt.http.HttpHandler.java

Source

/*
 * Copyright (c) 2013. wyouflf (wyouflf@gmail.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 com.android.idtt.http;

import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.protocol.HttpContext;

import android.os.SystemClock;
import android.text.TextUtils;

import com.android.idtt.HttpUtils;
import com.android.idtt.exception.HttpException;
import com.android.idtt.http.client.HttpGetCache;
import com.android.idtt.http.client.HttpRequest;
import com.android.idtt.http.client.callback.DefaultDownloadRedirectHandler;
import com.android.idtt.http.client.callback.DownloadRedirectHandler;
import com.android.idtt.http.client.callback.FileDownloadHandler;
import com.android.idtt.http.client.callback.RequestCallBackHandler;
import com.android.idtt.http.client.callback.StringDownloadHandler;
import com.android.idtt.util.OtherUtils;
import com.android.idtt.util.core.CompatibleAsyncTask;

public class HttpHandler<T> extends CompatibleAsyncTask<Object, Object, Object> implements RequestCallBackHandler {

    private final AbstractHttpClient client;
    private final HttpContext context;

    private final StringDownloadHandler mStringDownloadHandler = new StringDownloadHandler();
    private final FileDownloadHandler mFileDownloadHandler = new FileDownloadHandler();

    private DownloadRedirectHandler downloadRedirectHandler;

    public void setDownloadRedirectHandler(DownloadRedirectHandler downloadRedirectHandler) {
        this.downloadRedirectHandler = downloadRedirectHandler;
    }

    private final RequestCallBack callback;

    private int retriedTimes = 0;
    private String fileSavePath = null; // 
    private boolean isDownloadingFile; // fileSavePath != null;
    private boolean autoResume = false; // ?
    private boolean autoRename = false; // ????
    private String charset; // charset

    public HttpHandler(AbstractHttpClient client, HttpContext context, String charset, RequestCallBack callback) {
        this.client = client;
        this.context = context;
        this.callback = callback;
        this.charset = charset;
    }

    private String _getRequestUrl;// if not get method, it will be null.
    private long expiry = HttpGetCache.getDefaultExpiryTime();

    public void setExpiry(long expiry) {
        this.expiry = expiry;
    }

    // 
    private Object sendRequest(HttpRequestBase request) throws HttpException {
        if (autoResume && isDownloadingFile) {
            File downloadFile = new File(fileSavePath);
            long fileLen = 0;
            if (downloadFile.isFile() && downloadFile.exists()) {
                fileLen = downloadFile.length();
            }
            if (fileLen > 0) {
                request.setHeader("RANGE", "bytes=" + fileLen + "-");
            }
        }

        boolean retry = true;
        HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();
        while (retry) {
            IOException exception = null;
            try {
                if (request.getMethod().equals(HttpRequest.HttpMethod.GET.toString())) {
                    _getRequestUrl = request.getURI().toString();
                } else {
                    _getRequestUrl = null;
                }
                if (_getRequestUrl != null) {
                    String result = HttpUtils.sHttpGetCache.get(_getRequestUrl);
                    if (result != null) { // get
                        return result;
                    }
                }

                Object responseBody = null;
                if (!isCancelled()) {
                    HttpResponse response = client.execute(request, context);
                    responseBody = handleResponse(response);
                }
                return responseBody;
            } catch (UnknownHostException e) {
                exception = e;
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (IOException e) {
                exception = e;
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (NullPointerException e) {
                exception = new IOException(e);
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } catch (HttpException e) {
                throw e;
            } catch (Exception e) {
                exception = new IOException(e);
                retry = retryHandler.retryRequest(exception, ++retriedTimes, context);
            } finally {
                if (!retry && exception != null) {
                    throw new HttpException(exception);
                }
            }
        }
        return null;
    }

    @Override
    protected Object doInBackground(Object... params) {
        if (params != null && params.length > 3) {
            fileSavePath = String.valueOf(params[1]);
            isDownloadingFile = fileSavePath != null;
            autoResume = (Boolean) params[2];
            autoRename = (Boolean) params[3];
        }
        try {
            publishProgress(UPDATE_START);
            Object responseBody = sendRequest((HttpRequestBase) params[0]);
            publishProgress(UPDATE_SUCCESS, responseBody);
        } catch (HttpException e) {
            publishProgress(UPDATE_FAILURE, e, e.getMessage());
        }

        return null;
    }

    private final static int UPDATE_START = 1;
    private final static int UPDATE_LOADING = 2;
    private final static int UPDATE_FAILURE = 3;
    private final static int UPDATE_SUCCESS = 4;

    @SuppressWarnings("unchecked")
    @Override
    protected void onProgressUpdate(Object... values) {
        int update = Integer.valueOf(String.valueOf(values[0]));
        switch (update) {
        case UPDATE_START:
            if (callback != null) {
                callback.onStart();
            }
            break;
        case UPDATE_LOADING:
            if (callback != null) {
                callback.onLoading(Long.valueOf(String.valueOf(values[1])),
                        Long.valueOf(String.valueOf(values[2])));
            }
            break;
        case UPDATE_FAILURE:
            if (callback != null) {
                callback.onFailure((HttpException) values[1], (String) values[2]);
            }
            break;
        case UPDATE_SUCCESS:
            if (callback != null) {
                callback.onSuccess((T) values[1]);
            }
            break;
        default:
            break;
        }
        super.onProgressUpdate(values);
    }

    private Object handleResponse(HttpResponse response) throws HttpException, IOException {
        if (response == null) {
            throw new HttpException("response is null");
        }
        StatusLine status = response.getStatusLine();
        int statusCode = status.getStatusCode();
        if (statusCode < 300) {
            HttpEntity entity = response.getEntity();
            Object responseBody = null;
            if (entity != null) {
                lastUpdateTime = SystemClock.uptimeMillis();
                if (isDownloadingFile) {
                    String responseFileName = autoRename ? OtherUtils.getFileNameFromHttpResponse(response) : null;
                    responseBody = mFileDownloadHandler.handleEntity(entity, this, fileSavePath, autoResume,
                            responseFileName);
                } else {

                    // charset
                    String responseCharset = OtherUtils.getCharsetFromHttpResponse(response);
                    charset = TextUtils.isEmpty(responseCharset) ? charset : responseCharset;

                    responseBody = mStringDownloadHandler.handleEntity(entity, this, charset);
                    HttpUtils.sHttpGetCache.put(_getRequestUrl, (String) responseBody, expiry);
                }
            }
            return responseBody;
        } else if (statusCode == 301 || statusCode == 302) {
            if (downloadRedirectHandler == null) {
                downloadRedirectHandler = new DefaultDownloadRedirectHandler();
            }
            HttpRequestBase request = downloadRedirectHandler.getDirectRequest(response);
            if (request != null) {
                return this.sendRequest(request);
            }
        } else if (statusCode == 416) {
            throw new HttpException(statusCode, "maybe the file has downloaded completely");
        } else {
            throw new HttpException(statusCode, status.getReasonPhrase());
        }
        return null;
    }

    private boolean mStop = false;

    /**
     * ?
     */
    @Override
    public void stop() {
        this.mStop = true;
        this.cancel(true);
    }

    public boolean isStop() {
        return mStop;
    }

    private long lastUpdateTime;

    @Override
    public boolean updateProgress(long total, long current, boolean forceUpdateUI) {
        if (mStop) {
            return !mStop;
        }
        if (callback != null && callback.isProgress()) {
            if (forceUpdateUI) {
                publishProgress(UPDATE_LOADING, total, current);
            } else {
                long currTime = SystemClock.uptimeMillis();
                if (currTime - lastUpdateTime >= callback.getRate()) {
                    lastUpdateTime = currTime;
                    publishProgress(UPDATE_LOADING, total, current);
                }
            }
        }
        return !mStop;
    }

}