package com.fanfou.app.opensource.http.support; import java.io.IOException; import java.io.InterruptedIOException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.HashSet; import javax.net.ssl.SSLHandshakeException; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import android.os.SystemClock; import com.fanfou.app.opensource.AppContext; public class RequestRetryHandler implements HttpRequestRetryHandler { private static final int RETRY_SLEEP_TIME_MILLIS = 1500; private static HashSet<Class<?>> exceptionWhitelist = new HashSet<Class<?>>(); private static HashSet<Class<?>> exceptionBlacklist = new HashSet<Class<?>>(); static { // Retry if the server dropped connection on us RequestRetryHandler.exceptionWhitelist .add(NoHttpResponseException.class); // retry-this, since it may happens as part of a Wi-Fi to 3G failover RequestRetryHandler.exceptionWhitelist.add(UnknownHostException.class); // retry-this, since it may happens as part of a Wi-Fi to 3G failover RequestRetryHandler.exceptionWhitelist.add(SocketException.class); // never retry timeouts RequestRetryHandler.exceptionBlacklist .add(InterruptedIOException.class); // never retry SSL handshake failures RequestRetryHandler.exceptionBlacklist.add(SSLHandshakeException.class); } private final int maxRetries; public RequestRetryHandler(final int maxRetries) { this.maxRetries = maxRetries; } @Override public boolean retryRequest(final IOException exception, final int executionCount, final HttpContext context) { boolean retry; final Boolean b = (Boolean) context .getAttribute(ExecutionContext.HTTP_REQ_SENT); final boolean sent = ((b != null) && b.booleanValue()); if (executionCount > this.maxRetries) { // Do not retry if over max retry count retry = false; } else if (RequestRetryHandler.exceptionBlacklist.contains(exception .getClass())) { // immediately cancel retry if the error is blacklisted retry = false; } else if (RequestRetryHandler.exceptionWhitelist.contains(exception .getClass())) { // immediately retry if error is whitelisted retry = true; } else if (!sent) { // for most other errors, retry only if request hasn't been fully // sent yet retry = true; } else { // resend all idempotent requests final HttpUriRequest currentReq = (HttpUriRequest) context .getAttribute(ExecutionContext.HTTP_REQUEST); final String requestType = currentReq.getMethod(); if (!requestType.equals("POST")) { retry = true; } else { retry = false; } } if (retry) { SystemClock.sleep(RequestRetryHandler.RETRY_SLEEP_TIME_MILLIS); } else { if (AppContext.DEBUG) { exception.printStackTrace(); } } return retry; } }