HttpTask.java
/*
* Decompiled with CFR 0_132.
*
* Could not load the following classes:
* android.text.TextUtils
*/
package org.xutils.http;
import android.text.TextUtils;
import java.io.Closeable;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import org.xutils.common.Callback;
import org.xutils.common.task.AbsTask;
import org.xutils.common.task.Priority;
import org.xutils.common.task.PriorityExecutor;
import org.xutils.common.util.IOUtil;
import org.xutils.common.util.LogUtil;
import org.xutils.common.util.ParameterizedTypeUtil;
import org.xutils.ex.HttpException;
import org.xutils.ex.HttpRedirectException;
import org.xutils.http.HttpMethod;
import org.xutils.http.ProgressHandler;
import org.xutils.http.RequestParams;
import org.xutils.http.RequestTrackerWrapper;
import org.xutils.http.app.HttpRetryHandler;
import org.xutils.http.app.RedirectHandler;
import org.xutils.http.app.RequestInterceptListener;
import org.xutils.http.app.RequestTracker;
import org.xutils.http.request.UriRequest;
import org.xutils.http.request.UriRequestFactory;
import org.xutils.x;
public class HttpTask<ResultType>
extends AbsTask<ResultType>
implements ProgressHandler {
private RequestParams params;
private UriRequest request;
private HttpTask<ResultType> requestWorker;
private final Executor executor;
private volatile boolean hasException = false;
private final Callback.CommonCallback<ResultType> callback;
private Object rawResult = null;
private volatile Boolean trustCache = null;
private final Object cacheLock = new Object();
private Callback.CacheCallback<ResultType> cacheCallback;
private Callback.PrepareCallback prepareCallback;
private Callback.ProgressCallback progressCallback;
private RequestInterceptListener requestInterceptListener;
private RequestTracker tracker;
private Type loadType;
private static final int MAX_FILE_LOAD_WORKER = 3;
private static final AtomicInteger sCurrFileLoadCount = new AtomicInteger(0);
private static final HashMap<String, WeakReference<HttpTask<?>>> DOWNLOAD_TASK = new HashMap(1);
private static final PriorityExecutor HTTP_EXECUTOR = new PriorityExecutor(5, true);
private static final PriorityExecutor CACHE_EXECUTOR = new PriorityExecutor(5, true);
private static final int FLAG_REQUEST_CREATED = 1;
private static final int FLAG_CACHE = 2;
private static final int FLAG_PROGRESS = 3;
private long lastUpdateTime;
private long loadingUpdateMaxTimeSpan = 300L;
public HttpTask(RequestParams params, Callback.Cancelable cancelHandler, Callback.CommonCallback<ResultType> callback) {
RequestTracker customTracker;
super(cancelHandler);
assert (params != null);
assert (callback != null);
this.params = params;
this.callback = callback;
if (callback instanceof Callback.CacheCallback) {
this.cacheCallback = (Callback.CacheCallback)callback;
}
if (callback instanceof Callback.PrepareCallback) {
this.prepareCallback = (Callback.PrepareCallback)callback;
}
if (callback instanceof Callback.ProgressCallback) {
this.progressCallback = (Callback.ProgressCallback)callback;
}
if (callback instanceof RequestInterceptListener) {
this.requestInterceptListener = (RequestInterceptListener)((Object)callback);
}
if ((customTracker = params.getRequestTracker()) == null) {
customTracker = callback instanceof RequestTracker ? (RequestTracker)((Object)callback) : UriRequestFactory.getDefaultTracker();
}
if (customTracker != null) {
this.tracker = new RequestTrackerWrapper(customTracker);
}
this.executor = params.getExecutor() != null ? params.getExecutor() : (this.cacheCallback != null ? CACHE_EXECUTOR : HTTP_EXECUTOR);
}
private void resolveLoadType() {
Class<?> callBackType = this.callback.getClass();
this.loadType = this.callback instanceof Callback.TypedCallback ? ((Callback.TypedCallback)this.callback).getLoadType() : (this.callback instanceof Callback.PrepareCallback ? ParameterizedTypeUtil.getParameterizedType(callBackType, Callback.PrepareCallback.class, 0) : ParameterizedTypeUtil.getParameterizedType(callBackType, Callback.CommonCallback.class, 0));
}
private UriRequest createNewRequest() throws Throwable {
this.params.init();
UriRequest result = UriRequestFactory.getUriRequest(this.params, this.loadType);
result.setCallingClassLoader(this.callback.getClass().getClassLoader());
result.setProgressHandler(this);
this.loadingUpdateMaxTimeSpan = this.params.getLoadingUpdateMaxTimeSpan();
this.update(1, result);
return result;
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
private void checkDownloadTask() {
if (File.class == this.loadType) {
HashMap<String, WeakReference<HttpTask<?>>> hashMap = DOWNLOAD_TASK;
synchronized (hashMap) {
String downloadTaskKey = this.params.getSaveFilePath();
if (!TextUtils.isEmpty((CharSequence)downloadTaskKey)) {
WeakReference<HttpTask<?>> taskRef = DOWNLOAD_TASK.get(downloadTaskKey);
if (taskRef != null) {
HttpTask<?> task = taskRef.get();
if (task != null) {
task.cancel();
HttpTask.super.closeRequestSync();
}
DOWNLOAD_TASK.remove(downloadTaskKey);
}
DOWNLOAD_TASK.put(downloadTaskKey, new WeakReference<HttpTask>(this));
}
if (DOWNLOAD_TASK.size() > 3) {
Iterator<Map.Entry<String, WeakReference<HttpTask<?>>>> entryItr = DOWNLOAD_TASK.entrySet().iterator();
while (entryItr.hasNext()) {
Map.Entry<String, WeakReference<HttpTask<?>>> next = entryItr.next();
WeakReference<HttpTask<?>> value = next.getValue();
if (value != null && value.get() != null) continue;
entryItr.remove();
}
}
}
}
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
@Override
protected ResultType doBackground() throws Throwable {
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request");
}
Object result = null;
this.resolveLoadType();
this.request = this.createNewRequest();
this.checkDownloadTask();
boolean retry = true;
int retryCount = 0;
Throwable exception = null;
HttpRetryHandler retryHandler = this.params.getHttpRetryHandler();
if (retryHandler == null) {
retryHandler = new HttpRetryHandler();
}
retryHandler.setMaxRetryCount(this.params.getMaxRetryCount());
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request");
}
Object cacheResult = null;
if (this.cacheCallback != null && HttpMethod.permitsCache(this.params.getMethod())) {
try {
this.clearRawResult();
LogUtil.d("load cache: " + this.request.getRequestUri());
this.rawResult = this.request.loadResultFromCache();
}
catch (Throwable ex) {
LogUtil.w("load disk cache error", ex);
}
if (this.isCancelled()) {
this.clearRawResult();
throw new Callback.CancelledException("cancelled before request");
}
if (this.rawResult != null) {
if (this.prepareCallback != null) {
try {
cacheResult = this.prepareCallback.prepare(this.rawResult);
}
catch (Throwable ex) {
cacheResult = null;
LogUtil.w("prepare disk cache error", ex);
}
finally {
this.clearRawResult();
}
} else {
cacheResult = this.rawResult;
}
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request");
}
if (cacheResult != null) {
this.update(2, cacheResult);
Object ex = this.cacheLock;
synchronized (ex) {
while (this.trustCache == null) {
try {
this.cacheLock.wait();
}
catch (InterruptedException iex2) {
throw new Callback.CancelledException("cancelled before request");
}
catch (Throwable iex2) {
}
}
}
if (this.trustCache.booleanValue()) {
return null;
}
}
}
}
if (this.trustCache == null) {
this.trustCache = false;
}
if (cacheResult == null) {
this.request.clearCacheHeader();
}
if (this.callback instanceof Callback.ProxyCacheCallback && ((Callback.ProxyCacheCallback)this.callback).onlyCache()) {
return null;
}
retry = true;
while (retry) {
retry = false;
try {
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request");
}
this.request.close();
try {
this.clearRawResult();
LogUtil.d("load: " + this.request.getRequestUri());
this.requestWorker = new RequestWorker();
this.requestWorker.request();
if (this.requestWorker.ex != null) {
throw this.requestWorker.ex;
}
this.rawResult = this.requestWorker.result;
}
catch (Throwable ex) {
this.clearRawResult();
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled during request");
}
throw ex;
}
if (this.prepareCallback != null) {
if (this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request");
}
try {
result = this.prepareCallback.prepare(this.rawResult);
}
finally {
this.clearRawResult();
}
} else {
result = this.rawResult;
}
if (this.cacheCallback != null && HttpMethod.permitsCache(this.params.getMethod())) {
this.request.save2Cache();
}
if (!this.isCancelled()) continue;
throw new Callback.CancelledException("cancelled after request");
}
catch (HttpRedirectException redirectEx) {
retry = true;
LogUtil.w("Http Redirect:" + this.params.getUri());
}
catch (Throwable ex) {
switch (this.request.getResponseCode()) {
case 204:
case 205:
case 304: {
return null;
}
}
exception = ex;
if (this.isCancelled() && !(exception instanceof Callback.CancelledException)) {
exception = new Callback.CancelledException("canceled by user");
}
retry = retryHandler.canRetry(this.request, exception, ++retryCount);
}
}
if (exception != null && result == null && !this.trustCache.booleanValue()) {
this.hasException = true;
throw exception;
}
return (ResultType)result;
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
@Override
protected /* varargs */ void onUpdate(int flag, Object ... args) {
switch (flag) {
case 1: {
if (this.tracker == null) break;
this.tracker.onRequestCreated((UriRequest)args[0]);
break;
}
case 2: {
Object object = this.cacheLock;
synchronized (object) {
try {
Object result = args[0];
if (this.tracker != null) {
this.tracker.onCache(this.request, result);
}
this.trustCache = this.cacheCallback.onCache(result);
}
catch (Throwable ex) {
this.trustCache = false;
this.callback.onError(ex, true);
}
finally {
this.cacheLock.notifyAll();
}
break;
}
}
case 3: {
if (this.progressCallback == null || args.length != 3) break;
try {
this.progressCallback.onLoading(((Number)args[0]).longValue(), ((Number)args[1]).longValue(), (Boolean)args[2]);
break;
}
catch (Throwable ex) {
this.callback.onError(ex, true);
break;
}
}
}
}
@Override
protected void onWaiting() {
if (this.tracker != null) {
this.tracker.onWaiting(this.params);
}
if (this.progressCallback != null) {
this.progressCallback.onWaiting();
}
}
@Override
protected void onStarted() {
if (this.tracker != null) {
this.tracker.onStart(this.params);
}
if (this.progressCallback != null) {
this.progressCallback.onStarted();
}
}
@Override
protected void onSuccess(ResultType result) {
if (this.hasException) {
return;
}
if (this.tracker != null) {
this.tracker.onSuccess(this.request, result);
}
this.callback.onSuccess(result);
}
@Override
protected void onError(Throwable ex, boolean isCallbackError) {
if (this.tracker != null) {
this.tracker.onError(this.request, ex, isCallbackError);
}
this.callback.onError(ex, isCallbackError);
}
@Override
protected void onCancelled(Callback.CancelledException cex) {
if (this.tracker != null) {
this.tracker.onCancelled(this.request);
}
this.callback.onCancelled(cex);
}
@Override
protected void onFinished() {
if (this.tracker != null) {
this.tracker.onFinished(this.request);
}
x.task().run(new Runnable(){
@Override
public void run() {
HttpTask.this.closeRequestSync();
}
});
this.callback.onFinished();
}
private void clearRawResult() {
if (this.rawResult instanceof Closeable) {
IOUtil.closeQuietly((Closeable)this.rawResult);
}
this.rawResult = null;
}
@Override
protected void cancelWorks() {
x.task().run(new Runnable(){
@Override
public void run() {
HttpTask.this.closeRequestSync();
}
});
}
@Override
protected boolean isCancelFast() {
return this.params.isCancelFast();
}
private void closeRequestSync() {
this.clearRawResult();
IOUtil.closeQuietly(this.request);
}
@Override
public Executor getExecutor() {
return this.executor;
}
@Override
public Priority getPriority() {
return this.params.getPriority();
}
@Override
public boolean updateProgress(long total, long current, boolean forceUpdateUI) {
if (this.isCancelled() || this.isFinished()) {
return false;
}
if (this.progressCallback != null && this.request != null && total > 0L) {
if (total < current) {
total = current;
}
if (forceUpdateUI) {
this.lastUpdateTime = System.currentTimeMillis();
this.update(3, total, current, this.request.isLoading());
} else {
long currTime = System.currentTimeMillis();
if (currTime - this.lastUpdateTime >= this.loadingUpdateMaxTimeSpan) {
this.lastUpdateTime = currTime;
this.update(3, total, current, this.request.isLoading());
}
}
}
return !this.isCancelled() && !this.isFinished();
}
public String toString() {
return this.params.toString();
}
private final class RequestWorker {
Object result;
Throwable ex;
private RequestWorker() {
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
public void request() {
block31 : {
try {
boolean interrupted = false;
if (File.class == HttpTask.this.loadType) {
AtomicInteger atomicInteger = sCurrFileLoadCount;
synchronized (atomicInteger) {
while (sCurrFileLoadCount.get() >= 3 && !HttpTask.this.isCancelled()) {
try {
sCurrFileLoadCount.wait(10L);
}
catch (InterruptedException iex2) {
interrupted = true;
break;
}
catch (Throwable iex2) {
}
}
}
sCurrFileLoadCount.incrementAndGet();
}
if (interrupted || HttpTask.this.isCancelled()) {
throw new Callback.CancelledException("cancelled before request" + (interrupted ? "(interrupted)" : ""));
}
try {
HttpTask.this.request.setRequestInterceptListener(HttpTask.this.requestInterceptListener);
this.result = HttpTask.this.request.loadResult();
}
catch (Throwable ex) {
this.ex = ex;
}
if (this.ex != null) {
throw this.ex;
}
}
catch (Throwable ex) {
HttpException httpEx;
int errorCode;
RedirectHandler redirectHandler;
this.ex = ex;
if (!(ex instanceof HttpException) || (errorCode = (httpEx = (HttpException)ex).getCode()) != 301 && errorCode != 302 || (redirectHandler = HttpTask.this.params.getRedirectHandler()) == null) break block31;
try {
RequestParams redirectParams = redirectHandler.getRedirectParams(HttpTask.this.request);
if (redirectParams != null) {
if (redirectParams.getMethod() == null) {
redirectParams.setMethod(HttpTask.this.params.getMethod());
}
HttpTask.this.params = redirectParams;
HttpTask.this.request = HttpTask.this.createNewRequest();
this.ex = new HttpRedirectException(errorCode, httpEx.getMessage(), httpEx.getResult());
}
}
catch (Throwable throwable) {
this.ex = ex;
}
}
finally {
if (File.class == HttpTask.this.loadType) {
AtomicInteger interrupted = sCurrFileLoadCount;
synchronized (interrupted) {
sCurrFileLoadCount.decrementAndGet();
sCurrFileLoadCount.notifyAll();
}
}
}
}
}
}
}