![JAR search and dependency download from the Maven repository](/logo.png)
co.easimart.EasimartHttpClient Maven / Gradle / Ivy
package co.easimart;
import android.net.SSLSessionCache;
import android.os.Build;
import co.easimart.http.EasimartHttpRequest;
import co.easimart.http.EasimartHttpResponse;
import co.easimart.http.EasimartNetworkInterceptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* The base class of a httpclient. It takes an http request, sends it to the server
* and gets response. It can be implemented by different http library such as Apache http,
* Android URLConnection, Square OKHttp and so on.
*/
/** package */ abstract class EasimartHttpClient {
private static final String TAG = "co.easimart.EasimartHttpClient";
private static final String APACHE_HTTPCLIENT_NAME = "org.apache.http";
private static final String URLCONNECTION_NAME = "net.java.URLConnection";
private static final String OKHTTP_NAME = "com.squareup.okhttp";
private static final String OKHTTPCLIENT_PATH = "com.squareup.okhttp.OkHttpClient";
private static final String MAX_CONNECTIONS_PROPERTY_NAME = "http.maxConnections";
private static final String KEEP_ALIVE_PROPERTY_NAME = "http.keepAlive";
public static EasimartHttpClient createClient(int socketOperationTimeout,
SSLSessionCache sslSessionCache) {
String httpClientLibraryName;
EasimartHttpClient httpClient;
if (hasOkHttpOnClasspath()) {
httpClientLibraryName = OKHTTP_NAME;
httpClient = new EasimartOkHttpClient(socketOperationTimeout, sslSessionCache);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
httpClientLibraryName = URLCONNECTION_NAME;
httpClient = new EasimartURLConnectionHttpClient(socketOperationTimeout, sslSessionCache);
} else {
httpClientLibraryName = APACHE_HTTPCLIENT_NAME;
httpClient = new EasimartApacheHttpClient(socketOperationTimeout, sslSessionCache);
}
EasimartLog.i(TAG, "Using " + httpClientLibraryName + " library for networking communication.");
return httpClient;
}
public static void setMaxConnections(int maxConnections) {
if (maxConnections <= 0) {
throw new IllegalArgumentException("Max connections should be large than 0");
}
System.setProperty(MAX_CONNECTIONS_PROPERTY_NAME, String.valueOf(maxConnections));
}
public static void setKeepAlive(boolean isKeepAlive) {
System.setProperty(KEEP_ALIVE_PROPERTY_NAME, String.valueOf(isKeepAlive));
}
private static boolean hasOkHttpOnClasspath() {
try {
Class.forName(OKHTTPCLIENT_PATH);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private boolean hasExecuted;
// There is no need to keep locks for interceptor lists since they will only be changed before
// we make network request
private List internalInterceptors;
private List externalInterceptors;
/* package */ abstract EasimartHttpResponse executeInternal(EasimartHttpRequest request)
throws IOException;
/* package */ abstract LibraryRequest getRequest(EasimartHttpRequest httpRequest)
throws IOException;
/* package */ abstract EasimartHttpResponse getResponse(LibraryResponse okHttpResponse)
throws IOException;
/* package */ void addInternalInterceptor(EasimartNetworkInterceptor interceptor) {
// If we do not have the restriction, we may have read/write conflict on the interceptorList
// and need to add lock to protect it. If in the future we need to add interceptor after
// httpclient start to execute, it is safe to remove this check and add lock.
if (hasExecuted) {
throw new IllegalStateException(
"`EasimartHttpClient#addInternalInterceptor(EasimartNetworkInterceptor)` can only be invoked " +
"before `EasimartHttpClient` execute any request");
}
if (internalInterceptors == null) {
internalInterceptors = new ArrayList<>();
}
internalInterceptors.add(interceptor);
}
/* package */ void addExternalInterceptor(EasimartNetworkInterceptor interceptor) {
// No need to check hasExecuted since this method will only be called before Easimart.initialize()
if (externalInterceptors == null) {
externalInterceptors = new ArrayList<>();
}
externalInterceptors.add(interceptor);
}
public final EasimartHttpResponse execute(EasimartHttpRequest request) throws IOException {
if (!hasExecuted) {
hasExecuted = true;
}
EasimartNetworkInterceptor.Chain chain = new EasimartNetworkInterceptorChain(0, 0, request);
return chain.proceed(request);
}
private class EasimartNetworkInterceptorChain implements EasimartNetworkInterceptor.Chain {
private final int internalIndex;
private final int externalIndex;
private final EasimartHttpRequest request;
EasimartNetworkInterceptorChain(int internalIndex, int externalIndex, EasimartHttpRequest request) {
this.internalIndex = internalIndex;
this.externalIndex = externalIndex;
this.request = request;
}
@Override
public EasimartHttpRequest getRequest() {
return request;
}
@Override
public EasimartHttpResponse proceed(EasimartHttpRequest request) throws IOException {
if (internalInterceptors != null && internalIndex < internalInterceptors.size()) {
// There's another internal interceptor in the chain. Call that.
EasimartNetworkInterceptor.Chain chain =
new EasimartNetworkInterceptorChain(internalIndex + 1, externalIndex, request);
return internalInterceptors.get(internalIndex).intercept(chain);
}
if (externalInterceptors != null && externalIndex < externalInterceptors.size()) {
// There's another external interceptor in the chain. Call that.
EasimartNetworkInterceptor.Chain chain =
new EasimartNetworkInterceptorChain(internalIndex, externalIndex + 1, request);
return externalInterceptors.get(externalIndex).intercept(chain);
}
// No more interceptors. Do HTTP.
return executeInternal(request);
}
}
/**
* When we find developers use interceptors, since we need expose the raw
* response(ungziped response) to interceptors, we need to disable the transparent ungzip.
*
* @return {@code true} if we should disable the http library level auto decompress.
*/
/* package */ boolean disableHttpLibraryAutoDecompress() {
return externalInterceptors != null && externalInterceptors.size() > 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy