me.xiaopan.android.gohttp.JsonHttpResponseHandler.java Source code

Java tutorial

Introduction

Here is the source code for me.xiaopan.android.gohttp.JsonHttpResponseHandler.java

Source

/*
 * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
 * 
 * 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 me.xiaopan.android.gohttp;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.CharArrayBuffer;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;

import me.xiaopan.android.gohttp.requestobject.ResponseBody;

/**
 * JSON Http??JSON??Java
 */
public class JsonHttpResponseHandler implements HttpResponseHandler {
    private Class<?> responseClass;
    private Type responseType;
    private boolean excludeFieldsWithoutExposeAnnotation;

    public JsonHttpResponseHandler(Class<?> responseClass, boolean excludeFieldsWithoutExposeAnnotation) {
        if (responseClass == null) {
            throw new IllegalArgumentException("responseClass cannot be null");
        }

        this.responseClass = responseClass;
        this.excludeFieldsWithoutExposeAnnotation = excludeFieldsWithoutExposeAnnotation;
    }

    public JsonHttpResponseHandler(Type responseType, boolean excludeFieldsWithoutExposeAnnotation) {
        if (responseType == null) {
            throw new IllegalArgumentException("responseType cannot be null");
        }

        this.responseType = responseType;
        this.excludeFieldsWithoutExposeAnnotation = excludeFieldsWithoutExposeAnnotation;
    }

    public JsonHttpResponseHandler(Class<?> responseClass) {
        this(responseClass, false);
    }

    public JsonHttpResponseHandler(Type responseType) {
        this(responseType, false);
    }

    @Override
    public boolean canCache(HttpResponse httpResponse) {
        return httpResponse.getStatusLine().getStatusCode() >= 200
                && httpResponse.getStatusLine().getStatusCode() < 300;
    }

    @Override
    public Object handleResponse(HttpRequest httpRequest, HttpResponse httpResponse) throws Throwable {
        if (!(httpResponse.getStatusLine().getStatusCode() > 100
                && httpResponse.getStatusLine().getStatusCode() < 300)) {
            throw new HttpResponseException(httpResponse.getStatusLine().getStatusCode(),
                    httpResponse.getStatusLine().getStatusCode() + "" + httpRequest.getUrl());
        }

        HttpEntity httpEntity = httpResponse.getEntity();
        if (httpEntity == null) {
            throw new HttpResponseException(httpResponse.getStatusLine().getStatusCode(), "HttpEntity is null");
        }

        String jsonString = toString(httpRequest, httpEntity, "UTF-8");

        if (httpRequest.isCanceled()) {
            return null;
        }

        if (jsonString == null || "".equals(jsonString)) {
            throw new Exception("?" + httpRequest.getUrl());
        }

        Gson gson;
        if (excludeFieldsWithoutExposeAnnotation) {
            gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        } else {
            gson = new Gson();
        }

        if (responseClass != null) { //???
            String readJson;
            String bodyName = parseResponseBodyAnnotation(httpRequest.getGoHttp().getContext(), responseClass);
            if (bodyName != null) {
                readJson = new JSONObject(jsonString).getString(bodyName);
            } else {
                readJson = jsonString;
            }
            return gson.fromJson(readJson, responseClass);
        } else if (responseType != null) { //????
            return gson.fromJson(jsonString, responseType);
        } else {
            throw new Exception("responseClassresponseType?null");
        }
    }

    private String toString(HttpRequest httpRequest, final HttpEntity entity, final String defaultCharset)
            throws IOException, ParseException {
        InputStream inputStream = entity.getContent();
        if (inputStream == null) {
            return "";
        }
        if (entity.getContentLength() > Integer.MAX_VALUE) {
            throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
        }
        int contentLength = (int) entity.getContentLength();
        if (contentLength < 0) {
            contentLength = 4096;
        }
        String charset = StringHttpResponseHandler.getContentCharSet(entity);
        if (charset == null) {
            charset = defaultCharset;
        }
        if (charset == null) {
            charset = HTTP.DEFAULT_CONTENT_CHARSET;
        }

        long averageLength = contentLength / httpRequest.getProgressCallbackNumber();
        int callbackNumber = 0;
        Reader reader = new InputStreamReader(inputStream, charset);
        CharArrayBuffer buffer = new CharArrayBuffer(contentLength);
        HttpRequest.ProgressListener progressListener = httpRequest.getProgressListener();
        try {
            char[] tmp = new char[1024];
            int readLength;
            long completedLength = 0;
            while (!httpRequest.isStopReadData() && (readLength = reader.read(tmp)) != -1) {
                buffer.append(tmp, 0, readLength);
                completedLength += readLength;
                if (progressListener != null && !httpRequest.isCanceled()
                        && (completedLength >= (callbackNumber + 1) * averageLength
                                || completedLength == contentLength)) {
                    callbackNumber++;
                    new HttpRequestHandler.UpdateProgressRunnable(httpRequest, contentLength, completedLength)
                            .execute();
                }
            }
        } finally {
            reader.close();
        }
        return buffer.toString();
    }

    /**
     * ??
     * @param context 
     * @param responseClass ?class
     */
    public static String parseResponseBodyAnnotation(Context context, Class<?> responseClass) {
        ResponseBody annotation = responseClass.getAnnotation(ResponseBody.class);
        if (annotation == null) {
            return null;
        }
        String annotationValue = annotation.value();
        if (annotationValue != null && !"".equals(annotationValue)) {
            return annotationValue;
        } else if (context != null && annotation.resId() > 0) {
            return context.getString(annotation.resId());
        } else {
            return null;
        }
    }
}