package com.litesuits.http.impl.huc;
import android.content.Context;
import com.litesuits.http.exception.HttpNetException;
import com.litesuits.http.exception.NetException;
import com.litesuits.http.log.HttpLog;
import com.litesuits.http.network.Network;
import javax.net.ssl.SSLException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.*;
import java.util.HashSet;
/**
* determine whether to send request try again.
* 试验发现,当url非法时,{@link HttpURLConnection}报MalformedURLException异常,
* 而apache httpclient会报IllegalStateException异常。
* 当url非法,和ssl错误时,不用重试。 当有可用网络但连接不稳定时,一般会报IO异常,此种情况尝试重试,以提高成功率。
* 继承StandardHttpRequestRetryHandler因用到其判断请求方式是否幂等和连接是否取消等方法。
*
* @author MaTianyu
* 2014-1-1下午5:03:46
*/
public class RetryHandler {
public static final String TAG = RetryHandler.class.getSimpleName();
private HashSet<Class<?>> whitelist = new HashSet<Class<?>>();
private HashSet<Class<?>> blacklist = new HashSet<Class<?>>();
private int retrySleepTimeMS;
/**
* @param retrySleepTimeMS if the network is unstable, wait retrySleepTimeMS then start retry.
*/
public RetryHandler(int retrySleepTimeMS) {
this.retrySleepTimeMS = retrySleepTimeMS;
whitelist.add(SocketException.class);
whitelist.add(SocketTimeoutException.class);
blacklist.add(MalformedURLException.class);
blacklist.add(UnknownHostException.class);
blacklist.add(FileNotFoundException.class);
blacklist.add(SSLException.class);
}
public RetryHandler setRetrySleepTimeMS(int retrySleepTimeMS) {
this.retrySleepTimeMS = retrySleepTimeMS;
return this;
}
public boolean retryRequest(IOException exception, int retryCount, int maxRetries,
Context appContext) throws HttpNetException, InterruptedException {
boolean retry = true;
if (retryCount > maxRetries) {
if (HttpLog.isPrint) {
HttpLog.w(TAG, "retry count > max retry times..");
}
throw new HttpNetException(exception);
} else if (isInList(blacklist, exception)) {
if (HttpLog.isPrint) {
HttpLog.w(TAG, "exception in blacklist..");
}
retry = false;
} else if (isInList(whitelist, exception)) {
if (HttpLog.isPrint) {
HttpLog.w(TAG, "exception in whitelist..");
}
retry = true;
}
if (retry) {
if (appContext != null) {
if (Network.isConnected(appContext)) {
HttpLog.d(TAG, "Network isConnected, retry now");
} else if (Network.isConnectedOrConnecting(appContext)) {
if (HttpLog.isPrint) {
HttpLog.v(TAG, "Network is Connected Or Connecting, wait for retey : "
+ retrySleepTimeMS + " ms");
}
Thread.sleep(retrySleepTimeMS);
} else {
HttpLog.d(TAG, "Without any Network , immediately cancel retry");
throw new HttpNetException(NetException.NetworkNotAvilable);
}
} else {
if (HttpLog.isPrint) {
HttpLog.v(TAG, "app context is null..");
HttpLog.v(TAG, "wait for retry : " + retrySleepTimeMS + " ms");
}
Thread.sleep(retrySleepTimeMS);
}
}
if (HttpLog.isPrint) {
HttpLog.i(TAG, "retry: " + retry + " , retryCount: " + retryCount + " , exception: " + exception);
}
return retry;
}
protected boolean isInList(HashSet<Class<?>> list, Throwable error) {
for (Class<?> aList : list) {
if (aList.isInstance(error)) {
return true;
}
}
return false;
}
}