[Gradle] Extract mhttp dependency.

This commit is contained in:
Kuba Szczodrzyński 2021-03-20 21:34:14 +01:00
parent 15f9db5ca6
commit 0615593d94
53 changed files with 2 additions and 4379 deletions

View File

@ -170,7 +170,7 @@ dependencies {
implementation project(":agendacalendarview")
implementation "eu.szkolny:cafebar:5bf0c618de"
implementation "eu.szkolny:material-about-library:0534abf316"
implementation project(":mhttp")
implementation "eu.szkolny:mhttp:af4b62e6e9"
implementation "eu.szkolny:nachos:0e5dfcaceb"
//implementation project(":Navigation")
implementation project(":szkolny-font")

View File

@ -1,51 +0,0 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion setup.compileSdk
defaultConfig {
minSdkVersion 9
targetSdkVersion setup.targetSdk
consumerProguardFiles 'proguard-rules.pro'
versionCode 1
versionName PROJ_VERSION
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath = true
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debugMinify {
debuggable = true
minifyEnabled = true
proguardFiles 'proguard-android.txt'
}
}
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
textReport true
textOutput 'stdout'
}
}
dependencies {
compileOnly "androidx.appcompat:appcompat:${versions.appcompat}"
compileOnly 'io.reactivex.rxjava2:rxjava:2.1.3'
api 'com.squareup.okhttp3:okhttp:3.12.0'
api 'com.google.code.gson:gson:2.8.5'
//api deps.mhttpannotations
// implementation project(':mhttp-annotations')
}
//apply from: 'https://raw.githubusercontent.com/motcwang/Utils/master/bintray-publish/bintray.gradle'

View File

@ -1,31 +0,0 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
PROJ_GROUP=im.wangchao
PROJ_VERSION=1.10.1
PROJ_NAME=mhttp
PROJ_WEBSITEURL=http://wangchao.im/2015/11/22/mhttpadapter-post.html
PROJ_ISSUETRACKERURL=https://github.com/motcwang/MHttp/issues
PROJ_VCSURL=git@github.com:motcwang/MHttp.git
PROJ_DESCRIPTION=
PROJ_ARTIFACTID=mhttp
PROJ_PACKAGING=aar
DEVELOPER_ID=mot
DEVELOPER_NAME=Wang Chao
DEVELOPER_EMAIL=magician.of.technique@aliyun.com

View File

@ -1,4 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="im.wangchao.mhttp">
</manifest>

View File

@ -1,256 +0,0 @@
package im.wangchao.mhttp;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import im.wangchao.mhttp.internal.exception.ParserException;
import im.wangchao.mhttp.internal.exception.ResponseFailException;
import okhttp3.Call;
import okhttp3.internal.Util;
import static im.wangchao.mhttp.Response.IO_EXCEPTION_CODE;
/**
* <p>Description : AbsResponseHandler.
* Callback lifecycle as follow:
* onStart()
* -------------------------------------------------------
* |
* |
* is canceled --- Y --- onCancel()
* |
* N
* |
* onFinish()
* |
* |
* is successful --- N --- onFailure() ------------------
* | |
* Y |
* | |
* backgroundParser() --is download-- onProgress() |
* | | |
* | | |
* onSuccess() onSuccess() |
* | | |
* | | |
* ---------------------------------------------------------
* onFinally()
* </p>
* <p>Author : wangchao.</p>
* <p>Date : 15/8/17.</p>
* <p>Time : 下午5:56.</p>
*/
public abstract class AbsCallbackHandler<Parser_Type> implements Callback, Converter<Response, Parser_Type>{
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool(Util.threadFactory("OkHttp", false));
public final static String DEFAULT_CHARSET = "UTF-8";
private Request request;
private String responseCharset = DEFAULT_CHARSET;
private boolean isFinished;
private boolean isCanceled;
private Executor mExecutor;
/** Working thread depends on {@link #mExecutor}, default UI. */
public abstract void onSuccess(Parser_Type data, Response response);
/** Working thread depends on {@link #mExecutor}, default UI. */
public abstract void onFailure(Response response, Throwable throwable);
/** Work on the request thread, that is okhttp thread. */
@Deprecated
public Parser_Type backgroundParser(Response response) throws Exception{
return null;
}
/** Work on the request thread, that is okhttp thread. */
@Override public Parser_Type apply(Response response) throws Exception {
return backgroundParser(response);
}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onStart(){}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onCancel(){}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onProgress(long bytesWritten, long bytesTotal){}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onUploadProgress(int bytesWritten, int bytesTotal){}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onFinish(){}
/** Working thread depends on {@link #mExecutor}, default UI. */
public void onFinally(Response response){}
@Override final public void onFailure(@NonNull Call call, @NonNull IOException e) {
if (call.isCanceled()){
sendCancelEvent();
return;
}
sendFinishEvent();
final Request req = request;
Response response = Response.error(req,
IO_EXCEPTION_CODE,
e.getMessage());
sendFailureEvent(response, e);
sendFinallyEvent(response);
}
@Override final public void onResponse(@NonNull Call call, @NonNull okhttp3.Response response) throws IOException {
if (call.isCanceled()){
response.close();
sendCancelEvent();
return;
}
sendFinishEvent();
final Request req = request;
Response okResponse;
if (response.isSuccessful() || response.isRedirect()
|| req.allowedErrorCodes().contains(response.code())) {
try {
okResponse = Response.newResponse(req, response);
Parser_Type data = apply(okResponse);
sendSuccessEvent(data, okResponse);
} catch (Exception e) {
sendFailureEvent(okResponse = Response.newResponse(req, response), e);
}
} else {
sendFailureEvent(okResponse = Response.newResponse(req, response), new ResponseFailException());
}
// todo response.close()
sendFinallyEvent(okResponse);
}
public AbsCallbackHandler(){}
@Override public void initialize(Request request){
isFinished = false;
isCanceled = false;
this.request = request;
this.mExecutor = request.callbackExecutor();
if (this.mExecutor == null){
this.mExecutor = request.callbackThreadMode().executor();
}
}
public final boolean isFinished(){
return isFinished;
}
/**
* Sets the charset for the response string. If not set, the default is UTF-8.
*/
public final void setCharset(@NonNull final String charset) {
this.responseCharset = charset;
}
/**
* subclass can override this method to change charset.
*/
public String charset() {
return TextUtils.isEmpty(responseCharset) ? DEFAULT_CHARSET : responseCharset;
}
/**
* @return request accept
*/
@Override public String accept(){
return Accept.EMPTY;
}
protected final void print(String message){
Log.d(AbsCallbackHandler.class.getSimpleName(), message);
}
@Nullable protected final String byteArrayToString(byte[] bytes){
try {
return bytes == null ? null : new String(bytes, charset());
} catch (UnsupportedEncodingException e) {
return null;
}
}
protected final Request getRequest(){
return this.request;
}
public final void sendUploadProgressEvent(final int bytesWritten, final int bytesTotal) {
execute(()->{
try {
onUploadProgress(bytesWritten, bytesTotal);
} catch (Throwable t) {
//Silent
}
});
}
public final void sendProgressEvent(final long bytesWritten, final long bytesTotal) {
execute(()->{
try {
onProgress(bytesWritten, bytesTotal);
} catch (Throwable t) {
//Silent
}
});
}
/*package*/ final void sendSuccessEvent(final Parser_Type data, final Response response) {
execute(() -> onSuccess(data, response));
}
/*package*/ final void sendFailureEvent(final Response response, @Nullable final Throwable throwable) {
execute(() -> onFailure(response, throwable));
}
/*package*/ final void sendStartEvent() {
if (request.callbackThreadMode() == ThreadMode.BACKGROUND){
DEFAULT_EXECUTOR_SERVICE.execute(this::onStart);
} else {
execute(this::onStart);
}
}
/*package*/ final void sendFinishEvent() {
execute(() -> {
AbsCallbackHandler.this.isFinished = true;
onFinish();
});
}
/*package*/ final void sendFinallyEvent(final Response response) {
execute(() -> onFinally(response));
}
/*package*/ final synchronized void sendCancelEvent() {
if (isCanceled){
return;
}
execute(() -> {
AbsCallbackHandler.this.isCanceled = true;
onCancel();
});
}
private void execute(Runnable command){
if (mExecutor == null || threadInterrupted()){
return;
}
mExecutor.execute(command);
}
private boolean threadInterrupted(){
return Thread.currentThread().isInterrupted();
}
}

View File

@ -1,33 +0,0 @@
package im.wangchao.mhttp;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <p>Description : Accept.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/4/25.</p>
* <p>Time : 上午11:06.</p>
*/
public interface Accept {
String EMPTY = "";
String ACCEPT_JSON = "application/json;charset=utf-8";
String ACCEPT_TEXT = "text/html;charset=utf-8";
String ACCEPT_DATA = "application/octet-stream";
String ACCEPT_IMAGE = "image/png,image/jpeg,image/*";
String ACCEPT_FILE = "application/octet-stream";
@Retention(RetentionPolicy.SOURCE)
@StringDef({
Accept.EMPTY,
Accept.ACCEPT_JSON,
Accept.ACCEPT_TEXT,
Accept.ACCEPT_DATA,
Accept.ACCEPT_IMAGE,
Accept.ACCEPT_FILE
})
public @interface $Accept {
}
}

View File

@ -1,149 +0,0 @@
package im.wangchao.mhttp;
import android.os.Build;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
/**
* <p>Description : Android5SSL.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/19.</p>
* <p>Time : 上午11:09.</p>
*/
/*package*/ class Android5SSL extends SSLSocketFactory {
private SSLSocketFactory defaultFactory;
// Android 5.0+ (API level21) provides reasonable default settings
// but it still allows SSLv3
// https://developer.android.com/about/versions/android-5.0-changes.html#ssl
static String protocols[] = null, cipherSuites[] = null;
static {
try {
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
if (socket != null) {
/* set reasonable protocol versions */
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
// - remove all SSL versions (especially SSLv3) because they're insecure now
List<String> protocols = new LinkedList<>();
for (String protocol : socket.getSupportedProtocols())
if (!protocol.toUpperCase().contains("SSL"))
protocols.add(protocol);
Android5SSL.protocols = protocols.toArray(new String[protocols.size()]);
/* set up reasonable cipher suites */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// choose known secure cipher suites
List<String> allowedCiphers = Arrays.asList(
// TLS 1.2
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256",
// maximum interoperability
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
// additionally
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
// take all allowed ciphers that are available and put them into preferredCiphers
HashSet<String> preferredCiphers = new HashSet<>(allowedCiphers);
preferredCiphers.retainAll(availableCiphers);
/* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling
* ciphers which are enabled by default, but have become unsecure), but I guess for
* the security level of DAVdroid and maximum compatibility, disabling of insecure
* ciphers should be a server-side task */
// add preferred ciphers to enabled ciphers
HashSet<String> enabledCiphers = preferredCiphers;
enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites())));
Android5SSL.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Android5SSL(X509TrustManager tm) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null);
defaultFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
private void upgradeTLS(SSLSocket ssl) {
// Android 5.0+ (API level21) provides reasonable default settings
// but it still allows SSLv3
// https://developer.android.com/about/versions/android-5.0-changes.html#ssl
if (protocols != null) {
ssl.setEnabledProtocols(protocols);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) {
ssl.setEnabledCipherSuites(cipherSuites);
}
}
@Override public String[] getDefaultCipherSuites() {
return cipherSuites;
}
@Override public String[] getSupportedCipherSuites() {
return cipherSuites;
}
@Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
Socket ssl = defaultFactory.createSocket(s, host, port, autoClose);
if (ssl instanceof SSLSocket)
upgradeTLS((SSLSocket) ssl);
return ssl;
}
@Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
Socket ssl = defaultFactory.createSocket(host, port);
if (ssl instanceof SSLSocket)
upgradeTLS((SSLSocket) ssl);
return ssl;
}
@Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort);
if (ssl instanceof SSLSocket)
upgradeTLS((SSLSocket) ssl);
return ssl;
}
@Override public Socket createSocket(InetAddress host, int port) throws IOException {
Socket ssl = defaultFactory.createSocket(host, port);
if (ssl instanceof SSLSocket)
upgradeTLS((SSLSocket) ssl);
return ssl;
}
@Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort);
if (ssl instanceof SSLSocket)
upgradeTLS((SSLSocket) ssl);
return ssl;
}
}

View File

@ -1,28 +0,0 @@
package im.wangchao.mhttp;
import android.util.Log;
/**
* <p>Description : BindApi.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/19.</p>
* <p>Time : 上午8:23.</p>
*/
final class BindApi {
/** HttpProcessor.SUFFIX */
private static final String SUFFIX = "_HttpBinder";
@SuppressWarnings("unchecked") public static <T> T bind(Class<T> type) {
String name = type.getName() + SUFFIX;
T obj = null;
try {
obj = (T)Class.forName(name).newInstance();
} catch (Exception e) {
Log.e(BindApi.class.getSimpleName(), e.getMessage(), e);
}
return obj;
}
}

View File

@ -1,40 +0,0 @@
package im.wangchao.mhttp;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Response;
/**
* <p>Description : OkCallback.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/6/3.</p>
* <p>Time : 上午10:16.</p>
*/
public interface Callback extends okhttp3.Callback {
Callback EMPTY = new Callback() {
@Override public void initialize(Request request) {}
@Override public String accept() {
return Accept.EMPTY;
}
@Override public void onFailure(Call call, IOException e) {}
@Override public void onResponse(Call call, Response response) throws IOException {
response.close();
}
};
/**
* Initialize the callback.
*/
void initialize(Request request);
/**
* Request accept.
*/
String accept();
}

View File

@ -1,12 +0,0 @@
package im.wangchao.mhttp;
/**
* <p>Description : Converter.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/20.</p>
* <p>Time : 下午10:26.</p>
*/
public interface Converter<T, R> {
R apply(T t) throws Exception;
}

View File

@ -1,179 +0,0 @@
package im.wangchao.mhttp;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import okhttp3.internal.Util;
/**
* <p>Description : HTTPS.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/9/2.</p>
* <p>Time : 下午3:58.</p>
*/
/*package*/ final class HTTPS {
// 信任所有证书的 TrustManager
private static X509TrustManager TrustAllCertificate = new X509TrustManager() {
@Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
};
/**
* Trust all certificate for debug
*/
/*package*/ static void trustAllCertificate(OkHttpClient.Builder builder) {
builder.sslSocketFactory(new Android5SSL(TrustAllCertificate), TrustAllCertificate);
}
/**
* Set Certificate
*/
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
InputStream... certificates) throws Exception {
setCertificates(builder, null, certificates, null, null);
}
/**
* Set Certificate
*/
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
X509TrustManager trustManager,
InputStream bksFile,
String password) throws Exception {
setCertificates(builder, trustManager, null, bksFile, password);
}
/**
* Set Certificate
*/
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
InputStream[] certificates,
InputStream bksFile,
String password) throws Exception {
setCertificates(builder, null, certificates, bksFile, password);
}
/**
* Set Certificate
*/
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
X509TrustManager trustManager,
InputStream[] certificates,
InputStream bksFile,
String password) throws Exception {
TrustManager[] trustManagers = prepareTrustManager(certificates);
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
X509TrustManager manager;
if (trustManager != null) {
manager = trustManager;
} else if (trustManagers != null) {
manager = chooseTrustManager(trustManagers);
} else {
manager = TrustAllCertificate;
}
// 创建TLS类型的SSLContext对象 that uses our finalTrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
// 用上面得到的trustManagers初始化SSLContext这样sslContext就会信任keyStore中的证书
// 第一个参数是授权的密钥管理器用来授权验证比如授权自签名的证书验证第二个是被授权的证书管理器用来验证服务器端的证书
sslContext.init(keyManagers, new TrustManager[]{manager}, new SecureRandom());
builder.sslSocketFactory(sslContext.getSocketFactory(), manager);
}
/*package*/ static TrustManager[] prepareTrustManager(InputStream... certificates) throws Exception {
if (certificates == null || certificates.length <= 0) return null;
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 创建一个默认类型的KeyStore存储我们信任的证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
Util.closeQuietly(certificate);
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.
getInstance(TrustManagerFactory.getDefaultAlgorithm());
//用我们之前的keyStore实例初始化TrustManagerFactory使TrustManagerFactory信任keyStore中的证书
trustManagerFactory.init(keyStore);
return trustManagerFactory.getTrustManagers();
}
/*package*/ static KeyManager[] prepareKeyManager(InputStream bksFile, String password) throws Exception{
if (bksFile == null || password == null) return null;
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bksFile, password.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, password.toCharArray());
return keyManagerFactory.getKeyManagers();
}
/*package*/ static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
/* X509TrustManager */
/*package*/ static class MyTrustManager implements X509TrustManager {
private X509TrustManager defaultTrustManager;
private X509TrustManager localTrustManager;
/*package*/ MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
var4.init((KeyStore) null);
defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
this.localTrustManager = localTrustManager;
}
@Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// try {
// defaultTrustManager.checkClientTrusted(chain, authType);
// } catch (CertificateException e) {
// localTrustManager.checkClientTrusted(chain, authType);
// }
}
@Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
defaultTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
localTrustManager.checkServerTrusted(chain, authType);
}
}
@Override public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}

View File

@ -1,252 +0,0 @@
package im.wangchao.mhttp;
import android.content.Context;
import android.os.Build;
import android.os.StatFs;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.X509TrustManager;
import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor;
import im.wangchao.mhttp.internal.interceptor.MBridgeInterceptor;
import im.wangchao.mhttp.internal.log.LoggerImpl;
import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
/**
* <p>Description : MHttp.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/6/2.</p>
* <p>Time : 上午8:40.</p>
*/
public final class MHttp {
private static volatile MHttp instance;
private OkHttpClient.Builder mOkBuilder;
private OkHttpClient mInnerClient;
private URLInterceptor mURLInterceptor;
private final HttpLoggingInterceptor mLoggingInterceptor = new HttpLoggingInterceptor(LoggerImpl.instance.get());
public static MHttp instance(){
if (instance == null) {
synchronized (MHttp.class){
instance = new MHttp();
}
}
return instance;
}
/**
* Create annotation api
*/
public static <T> T create(Class<T> api){
return BindApi.bind(api);
}
/**
* OkHttpClient
*/
public MHttp customOkHttpClient(@NonNull OkHttpClient client){
mOkBuilder = client.newBuilder()
.addInterceptor(MBridgeInterceptor.instance.get());
return this;
}
/**
* Set logging level
*/
public MHttp loggingLevel(HttpLoggingInterceptor.Level level){
mLoggingInterceptor.setLevel(level);
LoggerImpl.instance.get().setLevel(level);
if (!mOkBuilder.interceptors().contains(mLoggingInterceptor)) {
mOkBuilder.addInterceptor(mLoggingInterceptor);
}
return this;
}
/**
* Set cache Dir
*/
public MHttp cache(Context context, String dirName) {
File cache = new File(context.getApplicationContext().getCacheDir(), dirName);
if (!cache.exists()) {
//noinspection ResultOfMethodCallIgnored
cache.mkdirs();
}
long size = 5 * 1024 * 1024;
try {
StatFs statFs = new StatFs(cache.getAbsolutePath());
long count, blockSize;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1){
count = statFs.getBlockCountLong();
blockSize = statFs.getBlockSizeLong();
} else {
count = statFs.getBlockCount();
blockSize = statFs.getBlockSize();
}
long available = count * blockSize;
// Target 2% of the total space.
size = available / 50;
} catch (IllegalArgumentException ignored) {
}
// Bound inside min/max size for disk cache.
size = Math.max(Math.min(size, size * 10), size);
mOkBuilder.cache(new Cache(cache, size));
return this;
}
/**
* Set connect, read and write time with {@link TimeUnit#SECONDS}
*/
public MHttp timeout(int timeout){
timeout(timeout, TimeUnit.SECONDS);
return this;
}
public MHttp timeout(int timeout, TimeUnit unit){
connectTimeout(timeout, unit);
readTimeout(timeout, unit);
writeTimeout(timeout, unit);
return this;
}
public MHttp connectTimeout(long timeout, TimeUnit unit){
mOkBuilder.connectTimeout(timeout, unit);
return this;
}
public MHttp readTimeout(long timeout, TimeUnit unit){
mOkBuilder.readTimeout(timeout, unit);
return this;
}
public MHttp writeTimeout(long timeout, TimeUnit unit){
mOkBuilder.writeTimeout(timeout, unit);
return this;
}
public MHttp setURLInterceptor(URLInterceptor interceptor){
this.mURLInterceptor = interceptor;
return this;
}
/**
* Trust all certificate for debug
*/
public MHttp trustAllCertificate(){
HTTPS.trustAllCertificate(mOkBuilder);
return this;
}
/**
* Set Certificate
*/
public MHttp setCertificates(InputStream... certificates){
return setCertificates(certificates, null, null);
}
/**
* Set Certificate
*/
public MHttp setCertificates(X509TrustManager trustManager, InputStream bksFile, String password) {
try {
HTTPS.setCertificates(mOkBuilder, trustManager, null, bksFile, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
return this;
}
/**
* Set Certificate
*/
public MHttp setCertificates(InputStream[] certificates, InputStream bksFile, String password) {
try {
HTTPS.setCertificates(mOkBuilder, null, certificates, bksFile, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
return this;
}
public MHttp hostnameVerifier(HostnameVerifier hostnameVerifier){
mOkBuilder.hostnameVerifier(hostnameVerifier);
return this;
}
/**
* @return Current client.
*/
public OkHttpClient client(){
if (mOkBuilder == null){
throw new IllegalArgumentException("OkHttpClient cannot be null, please call the MHttp#client(OkHttpClient client) method first.");
}
if (mInnerClient == null){
mInnerClient = mOkBuilder.build();
}
return mInnerClient;
}
/**
* Cancel all request.
*/
public MHttp cancelAll(){
client().dispatcher().cancelAll();
return this;
}
/**
* Cancel request with {@code tag}
*/
public MHttp cancel(Object tag){
for (Call call : client().dispatcher().queuedCalls()) {
if (tag.equals(call.request().tag())) {
call.cancel();
}
}
for (Call call : client().dispatcher().runningCalls()) {
if (tag.equals(call.request().tag())) {
call.cancel();
}
}
return this;
}
/*package*/ String proceedURL(String url){
if (mURLInterceptor != null){
return mURLInterceptor.interceptor(url);
}
return url;
}
/*package*/ HttpUrl proceedURL(HttpUrl url){
if (mURLInterceptor != null){
return mURLInterceptor.interceptor(url);
}
return url;
}
/*package*/ URL proceedURL(URL url){
if (mURLInterceptor != null){
return mURLInterceptor.interceptor(url);
}
return url;
}
//@private
private MHttp(){
//default instance
mOkBuilder = new OkHttpClient.Builder()
.addInterceptor(MBridgeInterceptor.instance.get());
}
}

View File

@ -1,25 +0,0 @@
package im.wangchao.mhttp;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <p>Description : Method.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/8.</p>
* <p>Time : 下午4:08.</p>
*/
public interface Method {
String POST = "POST";
String GET = "GET";
String HEAD = "HEAD";
String DELETE = "DELETE";
String PUT = "PUT";
String PATCH = "PATCH";
@Retention(RetentionPolicy.SOURCE)
@StringDef({Method.POST, Method.GET, Method.HEAD, Method.DELETE, Method.PUT, Method.PATCH})
@interface MethodType{}
}

View File

@ -1,503 +0,0 @@
package im.wangchao.mhttp;
import androidx.annotation.NonNull;
import android.util.Pair;
import android.util.Log;
import com.google.gson.JsonObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import im.wangchao.mhttp.body.JSONBody;
import im.wangchao.mhttp.body.MediaTypeUtils;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
/**
* <p>Description : MRequest.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/6/2.</p>
* <p>Time : 下午4:16.</p>
*/
public final class Request {
public static Builder builder(){
return new Builder();
}
private final okhttp3.Request mRawRequest;
private final RequestParams mRequestParams;
private final Callback mCallback;
private final MediaType mMediaType;
private final Executor mExecutor;
private final ThreadMode mThreadMode;
private final JsonObject mJsonBody;
private final okhttp3.OkHttpClient mOkHttpClient;
private final List<Integer> mAllowedErrorCodes;
private final String mTextBody;
private okhttp3.Call mRawCall;
private Request(Builder builder){
mRawRequest = builder.mRawRequest;
mRequestParams = builder.mRequestParams;
mCallback = builder.mCallback;
mMediaType = builder.mMediaType;
mExecutor = builder.mExecutor;
mThreadMode = builder.mThreadMode;
mJsonBody = builder.mJsonBody;
mOkHttpClient = builder.mOkHttpClient;
mAllowedErrorCodes = builder.mAllowedErrorCodes;
mTextBody = builder.mTextBody;
}
public okhttp3.Request raw() {
return mRawRequest;
}
public HttpUrl url() {
return mRawRequest.url();
}
public String method() {
return mRawRequest.method();
}
public Headers headers() {
return mRawRequest.headers();
}
public String header(String name) {
return mRawRequest.header(name);
}
public List<String> headers(String name) {
return mRawRequest.headers(name);
}
public RequestBody body() {
return mRawRequest.body();
}
public String bodyToString(){
try {
final Buffer buffer = new Buffer();
body().writeTo(buffer);
return buffer.readUtf8();
} catch (final Exception e) {
return "did not work. "+e.getMessage();
}
}
public Object tag() {
return mRawRequest.tag();
}
public Builder newBuilder() {
return new Builder(this);
}
public Callback callback() {
return mCallback;
}
public JsonObject jsonBody() {
return mJsonBody;
}
public String textBody() {
return mTextBody;
}
public OkHttpClient okHttpClient() {
return mOkHttpClient;
}
public List<Integer> allowedErrorCodes() {
return mAllowedErrorCodes;
}
/**
* Returns the cache control directives for this response. This is never null, even if this
* response contains no {@code Cache-Control} header.
*/
public CacheControl cacheControl() {
return mRawRequest.cacheControl();
}
public boolean isHttps() {
return mRawRequest.isHttps();
}
/**
* The executor used for {@link Callback} methods on which thread work.
*/
public Executor callbackExecutor() {
return mExecutor;
}
/**
* {@link Callback} methods on which thread work.
*/
public ThreadMode callbackThreadMode() {
return mThreadMode;
}
public RequestParams requestParams(){
return mRequestParams;
}
/**
* Send the async request.
*/
public Request enqueue(){
Callback callback = callback();
callback.initialize(this);
if (callback instanceof AbsCallbackHandler){
((AbsCallbackHandler) callback).sendStartEvent();
}
rawCall().enqueue(callback);
return this;
}
/**
* Send the sync request.
*/
public Response execute() throws IOException {
return Response.newResponse(this, rawCall().execute());
}
/**
* Cancel this request
*/
public Request cancel(){
if (rawCall().isCanceled()){
return this;
}
rawCall().cancel();
return this;
}
private Call rawCall(){
if (mRawCall == null){
OkHttpClient client;
if (mOkHttpClient == null) {
client = MHttp.instance().client();
}
else {
client = mOkHttpClient;
}
mRawCall = client.newCall(raw());
}
return mRawCall;
}
@Override public String toString() {
return mRawRequest.toString();
}
public static class Builder {
private static final String TAG = Builder.class.getSimpleName();
okhttp3.Request mRawRequest;
okhttp3.Request.Builder mRawBuilder;
RequestParams mRequestParams;
Callback mCallback;
String mMethod;
MediaType mMediaType;
Executor mExecutor;
ThreadMode mThreadMode;
JsonObject mJsonBody;
OkHttpClient mOkHttpClient;
List<Integer> mAllowedErrorCodes;
String mTextBody;
public Builder() {
mCallback = Callback.EMPTY;
mMethod = Method.GET;
mRawBuilder = new okhttp3.Request.Builder();
mRequestParams = new RequestParams();
mThreadMode = ThreadMode.BACKGROUND;
mJsonBody = null;
mOkHttpClient = null;
mAllowedErrorCodes = new ArrayList<>();
mTextBody = null;
}
private Builder(Request request) {
mCallback = request.mCallback;
mMethod = request.method();
mRequestParams = request.mRequestParams;
mRawBuilder = request.mRawRequest.newBuilder();
mExecutor = request.mExecutor;
mThreadMode = request.mThreadMode;
mMediaType = request.mMediaType;
mJsonBody = request.mJsonBody;
mOkHttpClient = request.mOkHttpClient;
mAllowedErrorCodes = request.mAllowedErrorCodes;
mTextBody = request.mTextBody;
}
public Builder url(HttpUrl url) {
mRawBuilder.url(MHttp.instance().proceedURL(url));
return this;
}
public Builder url(String url) {
mRawBuilder.url(MHttp.instance().proceedURL(url));
return this;
}
public Builder url(URL url) {
mRawBuilder.url(MHttp.instance().proceedURL(url));
return this;
}
public Builder header(String name, String value) {
mRawBuilder.header(name, value);
return this;
}
public Builder addHeader(String name, String value) {
mRawBuilder.addHeader(name, value);
return this;
}
public Builder removeHeader(String name) {
mRawBuilder.removeHeader(name);
return this;
}
public Builder headers(Headers headers) {
mRawBuilder.headers(headers);
return this;
}
public Builder cacheControl(CacheControl cacheControl) {
mRawBuilder.cacheControl(cacheControl);
return this;
}
public Builder withClient(OkHttpClient okHttpClient) {
mOkHttpClient = okHttpClient;
return this;
}
public Builder get() {
return method(Method.GET);
}
public Builder head() {
return method(Method.HEAD);
}
public Builder post() {
return method(Method.POST);
}
public Builder postJson() {
return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON);
}
public Builder delete() {
return method(Method.DELETE);
}
public Builder put() {
return method(Method.PUT);
}
public Builder patch() {
return method(Method.PATCH);
}
public Builder setJsonBody(JsonObject jsonBody) {
mJsonBody = jsonBody;
return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON);
}
public Builder setTextBody(String textBody, String mediaType) {
mTextBody = textBody;
return method(Method.POST).contentType(mediaType);
}
public Builder allowErrorCode(int code) {
mAllowedErrorCodes.add(code);
return this;
}
/**
* Simple to add request parameter
*/
public Builder addParameter(String key, Object value){
mRequestParams.put(key, value);
return this;
}
/**
* Simple to add request parameter
*/
public Builder addParameter(String key, InputStream stream, String name){
mRequestParams.put(key, stream, name);
return this;
}
/**
* Simple to add request parameter
*/
public Builder addParameter(String key, InputStream stream, String name, String contentType){
mRequestParams.put(key, stream, name, contentType);
return this;
}
/**
* Simple to add request parameter
*/
public Builder addParameter(String key, File file, String contentType){
try {
mRequestParams.put(key, file, contentType);
} catch (FileNotFoundException e) {
Log.e(TAG, e.getMessage(), e);
}
return this;
}
public Builder requestParams(RequestParams params) {
if (params != null){
mRequestParams = params;
}
return this;
}
public Builder addParams(List<Pair<String, Object>> params) {
if (params != null){
mRequestParams.put(params);
}
return this;
}
public Builder method(@NonNull String method) {
this.mMethod = method;
return this;
}
public Builder tag(Object tag) {
mRawBuilder.tag(tag);
return this;
}
public Builder callback(@NonNull Callback callback){
mCallback = callback;
return this;
}
public Builder callbackExecutor(Executor executor){
mExecutor = executor;
return this;
}
public Builder callbackThreadMode(ThreadMode threadMode){
mThreadMode = threadMode;
return this;
}
public Builder userAgent(String ua){
header("User-Agent", ua);
return this;
}
public Builder contentType(@NonNull String contentType){
this.mMediaType = MediaType.parse(contentType);
header("Content-Type", contentType);
return this;
}
public Builder contentType(@NonNull MediaType mediaType){
this.mMediaType = mediaType;
header("Content-Type", this.mMediaType.toString());
return this;
}
public Request build() {
if (mMediaType == null){
// judgment request header
List<String> headers = mRawBuilder.build().headers("Content-Type");
final int len = headers.size();
if (len != 0){
StringBuilder mediaType = new StringBuilder();
for (int i = 0; i < len; i++){
mediaType.append(headers.get(i));
}
mMediaType = MediaType.parse(mediaType.toString());
if (mMediaType == null){
mMediaType = MediaTypeUtils.DEFAULT;
}
}
// default is application/x-www-form-urlencoded
else {
mMediaType = MediaTypeUtils.DEFAULT;
}
}
if (!Accept.EMPTY.equals(mCallback.accept())) {
addHeader("Accept", mCallback.accept());
}
switch (mMethod) {
case Method.GET:
mRawBuilder.method(mMethod, null);
mRawRequest = mRawBuilder.build();
mRawRequest = mRawBuilder.url(mRequestParams.formatURLParams(mRawRequest.url())).build();
break;
case Method.HEAD:
mRawBuilder.method(mMethod, null);
mRawRequest = mRawBuilder.build();
break;
default:
if (MediaTypeUtils.isJSON(mMediaType) && mJsonBody != null) {
mRawBuilder.method(mMethod, new JSONBody(mJsonBody.toString()));
}
else if (mTextBody != null) {
mRawBuilder.method(mMethod, new RequestBody() {
@Override
public MediaType contentType() {
return mMediaType;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.write(mTextBody.getBytes(), 0, mTextBody.getBytes().length);
}
@Override
public long contentLength() throws IOException {
return mTextBody.getBytes().length;
}
});
}
else {
// inject callback if exist.
mRawBuilder.method(mMethod, mRequestParams.requestBody(mMediaType,
(mCallback instanceof AbsCallbackHandler ? (AbsCallbackHandler) mCallback : null)));
}
mRawRequest = mRawBuilder.build();
break;
}
return new Request(this);
}
}
}

View File

@ -1,378 +0,0 @@
package im.wangchao.mhttp;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.util.Pair;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import im.wangchao.mhttp.body.FileBody;
import im.wangchao.mhttp.body.JSONBody;
import im.wangchao.mhttp.body.MediaTypeUtils;
import im.wangchao.mhttp.body.OctetStreamBody;
import im.wangchao.mhttp.body.ProgressRequestBody;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import static im.wangchao.mhttp.body.MediaTypeUtils.APPLICATION_OCTET_STREAM;
/**
* <p>Description : RequestParams.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/8/17.</p>
* <p>Time : 下午2:16.</p>
*/
public class RequestParams{
final private static String UTF_8_STR = "utf-8";
final private static Charset UTF_8 = Charset.forName(UTF_8_STR);
//params
final private List<Pair<String, Object>> urlParams = new ArrayList<>();
final private ConcurrentHashMap<String, StreamWrapper> streamParams = new ConcurrentHashMap<>();
final private ConcurrentHashMap<String, FileWrapper> fileParams = new ConcurrentHashMap<>();
//default
private String contentEncoding = UTF_8_STR;
public RequestParams(){
this((Map<String, Object>)null);
}
public RequestParams(Map<String, Object> params){
if (params != null){
for(Map.Entry<String, Object> entry : params.entrySet()){
put(entry.getKey(), entry.getValue());
}
}
}
public RequestParams(Object...keysAndValues){
int len = keysAndValues.length;
if (len % 2 != 0){
throw new IllegalArgumentException("Supplied arguments must be even.");
}
for (int i = 0; i < len; i += 2){
String key = String.valueOf(keysAndValues[i]);
String val = String.valueOf(keysAndValues[i + 1]);
put(key, val);
}
}
public RequestParams(RequestParams params){
if (params == null){
return;
}
this.urlParams.addAll(params.getUrlParams());
this.streamParams.putAll(params.getStreamParams());
this.fileParams.putAll(params.getFileParams());
this.contentEncoding = params.contentEncoding();
}
RequestBody requestBody(MediaType mediaType, AbsCallbackHandler callback){
if (isJSON(mediaType)){
Charset charset = mediaType.charset();
if (charset == null){
charset = UTF_8;
}
return new JSONBody(parseJSON(), charset.name());
}
if (isForm(mediaType)){
return formBody();
}
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
//form
for (Pair<String, Object> entry: urlParams){
builder.addFormDataPart(entry.first, String.valueOf(entry.second));
}
//stream
for (Map.Entry<String, RequestParams.StreamWrapper> streamEntry: streamParams.entrySet()){
builder.addPart(
okhttp3.Headers.of("Content-Disposition",
String.format("form-data;name=\"%s\";filename=\"%s\"", streamEntry.getKey(), streamEntry.getValue().name),
"Content-Transfer-Encoding", "binary"),
uploadProgressRequestBody(
new OctetStreamBody(streamEntry.getValue().inputStream, streamEntry.getValue().contentType),
callback));
}
//file
for (Map.Entry<String, RequestParams.FileWrapper> file: fileParams.entrySet()){
builder.addPart(uploadProgressRequestBody(
new FileBody(file.getValue().file, file.getValue().contentType),
callback
));
}
return builder.build();
}
private ProgressRequestBody uploadProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){
return new ProgressRequestBody(requestBody, callback);
}
private FormBody formBody(){
FormBody.Builder builder = new FormBody.Builder();
for (Pair<String, Object> entry: urlParams){
builder.add(entry.first, String.valueOf(entry.second));
}
return builder.build();
}
/**
* @return Request body media type is JSON.
*/
private boolean isJSON(MediaType mediaType){
return MediaTypeUtils.isJSON(mediaType) && streamParams.size() == 0
&& fileParams.size() == 0;
}
/**
* @return Request body media type is Form.
*/
private boolean isForm(MediaType mediaType){
return MediaTypeUtils.isFORM(mediaType) && streamParams.size() == 0
&& fileParams.size() == 0;
}
/**
* Request body encoding.
*/
public RequestParams contentEncoding(@NonNull String encoding) {
if (Charset.isSupported(encoding)){
this.contentEncoding = encoding;
}
return this;
}
public String contentEncoding(){
return contentEncoding;
}
public void put(Map<String, String> params){
if (params != null){
for(Map.Entry<String, String> entry : params.entrySet()){
put(entry.getKey(), entry.getValue());
}
}
}
public void put(List<Pair<String, Object>> params){
if (params != null){
urlParams.addAll(params);
}
}
public void put(String key, String value) {
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
urlParams.add(new Pair<>(key, value));
}
}
public void put(String key, Object value) {
if (!TextUtils.isEmpty(key) && (value != null)) {
if (value instanceof File){
try {
put(key, (File)value);
} catch (FileNotFoundException e) {
// Silent
}
} else {
urlParams.add(new Pair<>(key, value));
}
}
}
public void put(String key, InputStream stream){
put(key, stream, null);
}
public void put(String key, InputStream stream, String name){
put(key, stream, name, null);
}
public void put(String key, InputStream stream, String name, String contentType){
if (!TextUtils.isEmpty(key) && stream != null){
streamParams.put(key, StreamWrapper.newInstance(stream, name, contentType));
}
}
public void put(File file) throws FileNotFoundException {
put(file, null);
}
public void put(File file, String contentType) throws FileNotFoundException {
put(RequestParams.class.getSimpleName(), file, contentType);
}
public void put(String key, File file) throws FileNotFoundException {
put(key, file, null);
}
public void put(String key, File file, String contentType) throws FileNotFoundException {
if (file == null || !file.exists()){
throw new FileNotFoundException();
}
if (!TextUtils.isEmpty(key)){
fileParams.put(key, new FileWrapper(file, contentType));
}
}
public void remove(String key){
Pair<String, Object> removing = null;
for (Pair<String, Object> entry: urlParams) {
if (entry.first.equals(key)) {
removing = entry;
}
}
urlParams.remove(removing);
streamParams.remove(key);
fileParams.remove(key);
}
public boolean has(String key){
for (Pair<String, Object> entry: urlParams) {
if (entry.first.equals(key)) {
return true;
}
}
return (streamParams.containsKey(key) || fileParams.containsKey(key));
}
public boolean isEmpty(){
return urlParams.isEmpty() && streamParams.isEmpty() && fileParams.isEmpty();
}
private String parseJSON(){
JSONObject json = new JSONObject();
String key;
Object value;
for (Pair<String, Object> entry: urlParams){
key = entry.first;
value = entry.second;
if (key.isEmpty() || value == null){
continue;
}
try {
json.put(key, value);
} catch (JSONException e) {
// Silent
}
}
return json.toString();
}
public ConcurrentHashMap<String, StreamWrapper> getStreamParams() {
return streamParams;
}
public ConcurrentHashMap<String, FileWrapper> getFileParams() {
return fileParams;
}
public List<Pair<String, Object>> getUrlParams() {
return urlParams;
}
public HttpUrl formatURLParams(HttpUrl url) {
HttpUrl.Builder builder = url.newBuilder();
if (urlParams.size() != 0) {
for (Pair<String, Object> entry : urlParams) {
try {
builder.addEncodedQueryParameter(URLEncoder.encode(entry.first, contentEncoding),
URLEncoder.encode(String.valueOf(entry.second), contentEncoding));
} catch (UnsupportedEncodingException e) {
//Silent
}
}
}
return builder.build();
}
/**
* Format get params.
*/
public String formatURLParams() {
StringBuilder sb = new StringBuilder();
if (urlParams.size() != 0) {
for (Pair<String, Object> entry : urlParams) {
String encode = "";
try {
encode = URLEncoder.encode(String.valueOf(entry.second), contentEncoding);
} catch (UnsupportedEncodingException e) {
//Silent
}
sb.append(entry.first).append("=").append(encode);
sb.append("&");
}
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString().replace(" ", "%20");
}
/**
* Url params convert to {@link List}.
*/
public List<Pair<String, Object>> getParamsList(){
List<Pair<String, Object>> params = new LinkedList<>();
for (Pair<String, Object> entry : urlParams) {
params.add(new Pair<>(entry.first, entry.second));
}
return params;
}
public static class FileWrapper {
public final File file;
public final String contentType;
public FileWrapper(File file, String contentType) {
this.file = file;
this.contentType = contentType;
}
}
public static class StreamWrapper {
public final InputStream inputStream;
public final String name;
public final String contentType;
public StreamWrapper(InputStream inputStream, String name, String contentType) {
this.inputStream = inputStream;
this.name = name;
this.contentType = contentType;
}
static StreamWrapper newInstance(InputStream inputStream, String name, String contentType) {
return new StreamWrapper(
inputStream,
name,
TextUtils.isEmpty(contentType) ? APPLICATION_OCTET_STREAM : contentType);
}
}
}

View File

@ -1,63 +0,0 @@
package im.wangchao.mhttp;
import okhttp3.Headers;
import okhttp3.Protocol;
/**
* <p>Description : MResponse.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/6/3.</p>
* <p>Time : 下午3:03.</p>
*/
public final class Response {
public final static int IO_EXCEPTION_CODE = 1000;
public static Response error(Request request, int code, String message){
if (message == null){
message = "unknown exception.";
}
return new Response(request, new okhttp3.Response.Builder()
.request(request.raw())
.protocol(Protocol.HTTP_1_1)
.code(code)
.message(message)
.build());
}
public static Response newResponse(Request request, okhttp3.Response raw){
return new Response(request, raw);
}
private final Request request;
private final okhttp3.Response rawResponse;
public String parserErrorBody = null;
private Response(Request request, okhttp3.Response rawResponse){
this.request = request;
this.rawResponse = rawResponse;
}
public Request request() {
return request;
}
public okhttp3.Response raw() {
return rawResponse;
}
/** HTTP status code. */
public int code() {
return rawResponse.code();
}
/** HTTP status message or null if unknown. */
public String message() {
return rawResponse.message();
}
/** HTTP headers. */
public Headers headers() {
return rawResponse.headers();
}
}

View File

@ -1,43 +0,0 @@
package im.wangchao.mhttp;
import java.util.concurrent.Executor;
import im.wangchao.mhttp.executor.BACKGROUND;
import im.wangchao.mhttp.executor.MAIN;
import im.wangchao.mhttp.executor.SENDING;
/**
* <p>Description : ThreadMode.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/8/3.</p>
* <p>Time : 下午12:44.</p>
*/
public enum ThreadMode {
/**
* Callback will be called in the same thread, which is sending the request.
*/
SENDING{
@Override public Executor executor() {
return new SENDING();
}
},
/**
* Callback will be called in Android's main thread (UI thread).
*/
MAIN{
@Override public Executor executor() {
return new MAIN();
}
},
/**
* Callback will be called in a background thread. That is, work on the request thread(okhttp thread).
*/
BACKGROUND{
@Override public Executor executor() {
return new BACKGROUND();
}
};
public abstract Executor executor();
}

View File

@ -1,20 +0,0 @@
package im.wangchao.mhttp;
import java.net.URL;
import okhttp3.HttpUrl;
/**
* <p>Description : URLInterceptor.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/1/15.</p>
* <p>Time : 上午11:01.</p>
*/
public interface URLInterceptor {
String interceptor(String origin);
HttpUrl interceptor(HttpUrl origin);
URL interceptor(URL origin);
}

View File

@ -1,53 +0,0 @@
package im.wangchao.mhttp.body;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import java.io.File;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.internal.Util;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
/**
* <p>Description : FileBody.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/8.</p>
* <p>Time : 下午6:10.</p>
*/
public final class FileBody extends RequestBody{
private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET;
private final MediaType contentType;
private final File file;
public FileBody(File file){
this(file, null);
}
public FileBody(File file, String contentType){
this.file = file;
this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType);
}
@Override public MediaType contentType() {
return contentType;
}
@Override public long contentLength() throws IOException {
return file.length();
}
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file);
sink.writeAll(source);
} finally {
Util.closeQuietly(source);
}
}
}

View File

@ -1,50 +0,0 @@
package im.wangchao.mhttp.body;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
/**
* <p>Description : JSONBody.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/8.</p>
* <p>Time : 下午4:31.</p>
*/
public final class JSONBody extends RequestBody{
private final static MediaType CONTENT_TYPE = MediaTypeUtils.JSON;
private final MediaType contentType;
private final byte[] bytes;
public JSONBody(String content){
this(content, null);
}
public JSONBody(String content, String charset){
if (TextUtils.isEmpty(content)){
throw new NullPointerException("content == null");
}
if (TextUtils.isEmpty(charset)){
charset = "utf-8";
}
this.contentType = TextUtils.isEmpty(charset) ? CONTENT_TYPE : MediaType.parse("application/json; charset=" + charset);
bytes = content.getBytes(contentType.charset());
}
@Override public MediaType contentType() {
return contentType;
}
@Override public long contentLength() throws IOException {
return bytes.length;
}
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
sink.write(bytes, 0, bytes.length);
}
}

View File

@ -1,53 +0,0 @@
package im.wangchao.mhttp.body;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import okhttp3.MediaType;
/**
* <p>Description : MediaType.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2017/6/23.</p>
* <p>Time : 下午2:15.</p>
*/
public final class MediaTypeUtils {
/** MediaType String */
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
public static final String APPLICATION_JSON = "application/json; charset=utf-8";
public static final String APPLICATION_FORM = "application/x-www-form-urlencoded";
public static final String APPLICATION_XML = "application/xml";
/** MediaType */
public static final MediaType JSON = MediaType.parse(APPLICATION_JSON);
public static final MediaType OCTET = MediaType.parse(APPLICATION_OCTET_STREAM);
public static final MediaType FORM = MediaType.parse(APPLICATION_FORM);
public static final MediaType XML = MediaType.parse(APPLICATION_XML);
public static final MediaType DEFAULT = FORM;
/**
* 判断两个 MediaType 是否相等只判断 type subType
*/
public static boolean equals(@NonNull MediaType first, @NonNull MediaType second){
String first_type_subType = first.type().concat(first.subtype());
String second_type_subType = second.type().concat(second.subtype());
return TextUtils.equals(first_type_subType, second_type_subType);
}
public static boolean isJSON(@NonNull MediaType mediaType){
return equals(mediaType, JSON);
}
public static boolean isOCTET(@NonNull MediaType mediaType){
return equals(mediaType, OCTET);
}
public static boolean isFORM(@NonNull MediaType mediaType){
return equals(mediaType, FORM);
}
public static boolean isXML(@NonNull MediaType mediaType){
return equals(mediaType, XML);
}
}

View File

@ -1,88 +0,0 @@
package im.wangchao.mhttp.body;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.internal.Util;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
/**
* <p>Description : OctetStreamBody.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/8.</p>
* <p>Time : 下午4:31.</p>
*/
public final class OctetStreamBody extends RequestBody{
private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET;
private final MediaType contentType;
private final InputStream stream;
private long contentLength = -1L;
private Buffer buffer;
public OctetStreamBody(InputStream stream){
this(stream, null);
}
public OctetStreamBody(InputStream stream, String contentType){
this.stream = stream;
this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType);
}
@Override public MediaType contentType() {
return contentType;
}
@Override public long contentLength() throws IOException {
long result = contentLength;
if (result != -1L) return result;
return contentLength = writeOrCountBytes(null, true);
}
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
contentLength = writeOrCountBytes(sink, false);
}
private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) throws IOException{
long byteCount = 0L;
if (countBytes) {
buffer = new Buffer();
Source source = null;
try {
source = Okio.source(stream);
buffer.writeAll(source);
} finally {
Util.closeQuietly(source);
}
byteCount = buffer.size();
return byteCount;
} else {
if (sink == null){
return byteCount;
}
Source source = null;
try {
source = Okio.source(buffer == null ? stream : buffer.inputStream());
return sink.writeAll(source);
} finally {
if (buffer != null){
buffer.clear();
}
Util.closeQuietly(source);
}
}
}
}

View File

@ -1,70 +0,0 @@
package im.wangchao.mhttp.body;
import androidx.annotation.NonNull;
import java.io.IOException;
import im.wangchao.mhttp.AbsCallbackHandler;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
/**
* <p>Description : ProgressRequestBody.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/1/30.</p>
* <p>Time : 下午8:25.</p>
*/
public class ProgressRequestBody extends RequestBody {
private final RequestBody mRequestBody;
private final AbsCallbackHandler mCallback;
private BufferedSink mBufferedSink;
public ProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){
this.mRequestBody = requestBody;
this.mCallback = callback;
}
@Override public MediaType contentType() {
return mRequestBody.contentType();
}
@Override public long contentLength() throws IOException {
return mRequestBody.contentLength();
}
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
if (mCallback == null){
mRequestBody.writeTo(sink);
return;
}
if (mBufferedSink == null){
mBufferedSink = Okio.buffer(forward(sink));
}
mRequestBody.writeTo(mBufferedSink);
mBufferedSink.flush();
}
private Sink forward(Sink sink){
return new ForwardingSink(sink) {
private long bytesWritten = 0L;
private long contentLength = 0L;
@Override public void write(@NonNull Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
if (contentLength == 0) {
contentLength = contentLength();
}
bytesWritten += byteCount;
mCallback.sendUploadProgressEvent((int) bytesWritten, (int) contentLength);
}
};
}
}

View File

@ -1,30 +0,0 @@
package im.wangchao.mhttp.callback;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
/**
* <p>Description : BinaryResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/18.</p>
* <p>Time : 下午2:49.</p>
*/
public class BinaryCallbackHandler extends AbsCallbackHandler<byte[]> {
@Override public void onSuccess(byte[] data, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public byte[] backgroundParser(Response response) throws Exception {
return response.raw().body().bytes();
}
@Override public String accept() {
return Accept.ACCEPT_DATA;
}
}

View File

@ -1,27 +0,0 @@
package im.wangchao.mhttp.callback;
import android.graphics.Bitmap;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
/**
* <p>Description : ImageResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/18.</p>
* <p>Time : 下午2:49.</p>
*/
public abstract class BitmapCallbackHandler extends AbsCallbackHandler<Bitmap> {
@Override public void onSuccess(Bitmap bitmap, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public String accept() {
return Accept.ACCEPT_IMAGE;
}
}

View File

@ -1,34 +0,0 @@
package im.wangchao.mhttp.callback;
import im.wangchao.mhttp.Response;
import im.wangchao.mhttp.internal.exception.ParserException;
/**
* <p>Description : GSONResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/20.</p>
* <p>Time : 上午9:06.</p>
*/
public abstract class CustomCallbackHandler<T> extends TextCallbackHandler {
@Override final public void onSuccess(String data, Response response) {
if (data != null) {
onSuccess(parser(data));
}
else {
onFailure(response, new ParserException());
}
}
@Override public void onFailure(Response response, Throwable throwable) {
}
/** parser Json to T */
protected abstract T parser(String data);
public void onSuccess(T t){
}
}

View File

@ -1,103 +0,0 @@
package im.wangchao.mhttp.callback;
import android.content.Context;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
import okhttp3.internal.Util;
/**
* <p>Description : FileResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/18.</p>
* <p>Time : 下午2:39.</p>
*/
public class FileCallbackHandler extends AbsCallbackHandler<File> {
private File file;
final private static int BUFFER_SIZE = 4096;
public FileCallbackHandler(Context context){
this.file = getTempFile(context);
}
public FileCallbackHandler(File file){
this.file = file;
}
protected File getFile(){
return file;
}
@Override public void onSuccess(File file, Response response){
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public File backgroundParser(Response response) throws IOException{
writeFile(response.raw(), file);
return file;
}
@Override public String accept() {
return Accept.ACCEPT_FILE;
}
private File getTempFile(Context context){
try {
return File.createTempFile("temp", "_handled", context.getCacheDir());
} catch (IOException e) {
return null;
}
}
/**
* write file , send progress message
*/
protected void writeFile(okhttp3.Response response, File file) throws IOException {
if (file == null){
throw new IllegalArgumentException("File == null");
}
if (this.file.isDirectory()) {
String contentDisposition = response.header("content-disposition");
if (contentDisposition != null) {
if (contentDisposition.contains("*=UTF-8")) {
contentDisposition = contentDisposition.replace("*=UTF-8''", "\"") + "\"";
contentDisposition = URLDecoder.decode(contentDisposition, "UTF-8");
}
String filename = contentDisposition.substring(contentDisposition.indexOf("\"") + 1, contentDisposition.lastIndexOf("\""));
this.file = new File(file, filename);
file = this.file;
}
}
InputStream instream = response.body().byteStream();
long contentLength = response.body().contentLength();
FileOutputStream buffer = new FileOutputStream(file);
if (instream != null) {
try {
byte[] tmp = new byte[BUFFER_SIZE];
int l;
long count = 0;
while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) {
count += l;
buffer.write(tmp, 0, l);
sendProgressEvent(count, contentLength);
}
} finally {
Util.closeQuietly(instream);
buffer.flush();
Util.closeQuietly(buffer);
}
}
}
}

View File

@ -1,37 +0,0 @@
package im.wangchao.mhttp.callback;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
public class JsonArrayCallbackHandler extends AbsCallbackHandler<JsonArray> {
@Override public void onSuccess(JsonArray data, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public JsonArray backgroundParser(Response response) throws Exception {
try {
byte[] body = response.raw().body().bytes();
String bodyString = byteArrayToString(body);
JsonArray object = new JsonParser().parse(bodyString).getAsJsonArray();
return object;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override public String accept() {
return Accept.ACCEPT_JSON;
}
}

View File

@ -1,48 +0,0 @@
package im.wangchao.mhttp.callback;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
/**
* <p>Description : JSONResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/18.</p>
* <p>Time : 下午2:25.</p>
*/
public class JsonCallbackHandler extends AbsCallbackHandler<JsonObject> {
@Override public void onSuccess(JsonObject data, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public JsonObject backgroundParser(Response response) throws Exception {
try {
byte[] body = response.raw().body().bytes();
String bodyString = byteArrayToString(body);
try {
return new JsonParser().parse(bodyString).getAsJsonObject();
}
catch (Exception e) {
e.printStackTrace();
response.parserErrorBody = bodyString;
return null;
}
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override public String accept() {
return Accept.ACCEPT_JSON;
}
}

View File

@ -1,27 +0,0 @@
package im.wangchao.mhttp.callback;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Accept;
import im.wangchao.mhttp.Response;
/**
* <p>Description : TextResponseHandler.</p>
* <p>Author : wangchao.</p>
* <p>Date : 15/10/18.</p>
* <p>Time : 下午2:41.</p>
*/
public class TextCallbackHandler extends AbsCallbackHandler<String> {
@Override public void onSuccess(String data, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
@Override public String backgroundParser(Response response) throws Exception {
return byteArrayToString(response.raw().body().bytes());
}
@Override public String accept() {
return Accept.ACCEPT_TEXT;
}
}

View File

@ -1,17 +0,0 @@
package im.wangchao.mhttp.executor;
import androidx.annotation.NonNull;
import java.util.concurrent.Executor;
/**
* <p>Description : BACKGROUND.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/9/2.</p>
* <p>Time : 下午4:50.</p>
*/
public final class BACKGROUND implements Executor {
@Override public void execute(@NonNull Runnable command) {
command.run();
}
}

View File

@ -1,21 +0,0 @@
package im.wangchao.mhttp.executor;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import java.util.concurrent.Executor;
/**
* <p>Description : MainThread.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/9/2.</p>
* <p>Time : 下午4:45.</p>
*/
public final class MAIN implements Executor{
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(@NonNull Runnable command) {
handler.post(command);
}
}

View File

@ -1,27 +0,0 @@
package im.wangchao.mhttp.executor;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import java.util.concurrent.Executor;
/**
* <p>Description : SENDING.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/9/2.</p>
* <p>Time : 下午4:47.</p>
*/
public final class SENDING implements Executor {
private final Handler handler;
public SENDING(){
if (Looper.myLooper() == null){
throw new RuntimeException("The Looper of the current thread is null, please call Looper.prepare() on your thread.");
}
handler = new Handler(Looper.myLooper());
}
@Override public void execute(@NonNull Runnable command) {
handler.post(command);
}
}

View File

@ -1,25 +0,0 @@
package im.wangchao.mhttp.internal;
/**
* <p>Description : Singleton.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/8/25.</p>
* <p>Time : 上午10:37.</p>
*/
public abstract class Singleton<T> {
private T instance;
protected abstract T create();
public T get(){
if (instance == null){
synchronized (this){
if (instance == null){
instance = create();
}
}
}
return instance;
}
}

View File

@ -1,21 +0,0 @@
package im.wangchao.mhttp.internal;
/**
* <p>Description : Version.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/8/24.</p>
* <p>Time : 下午2:47.</p>
*/
public class Version {
private Version(){
throw new AssertionError();
}
public static String userAgent() {
return moduleName().concat("1.10.1");
}
public static String moduleName() {
return "mhttp";
}
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie;
import okhttp3.CookieJar;
public interface ClearableCookieJar extends CookieJar {
void clear();
void clearForDomain(String domain);
}

View File

@ -1,60 +0,0 @@
package im.wangchao.mhttp.internal.cookie;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import im.wangchao.mhttp.internal.cookie.cache.CookieCache;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
/**
* <p>Description : MemeryCookieJar.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/3/18.</p>
* <p>Time : 下午2:20.</p>
*/
public class MemoryCookieJar implements ClearableCookieJar {
private CookieCache cache;
public MemoryCookieJar(CookieCache cache) {
this.cache = cache;
}
@Override
synchronized public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cache.addAll(cookies);
}
@Override
synchronized public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> validCookies = new ArrayList<>();
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
Cookie currentCookie = it.next();
if (isCookieExpired(currentCookie)) {
it.remove();
} else if (currentCookie.matches(url)) {
validCookies.add(currentCookie);
}
}
return validCookies;
}
private static boolean isCookieExpired(Cookie cookie) {
return cookie.expiresAt() < System.currentTimeMillis();
}
synchronized public void clear() {
cache.clear();
}
synchronized public void clearForDomain(String domain) {
cache.clearForDomain(domain);
}
}

View File

@ -1,133 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import im.wangchao.mhttp.internal.cookie.cache.CookieCache;
import im.wangchao.mhttp.internal.cookie.persistence.CookiePersistor;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
public class PersistentCookieJar implements ClearableCookieJar {
private CookieCache cache;
private CookiePersistor persistor;
public PersistentCookieJar(CookieCache cache, CookiePersistor persistor) {
this.cache = cache;
this.persistor = persistor;
this.cache.addAll(persistor.loadAll());
}
@Override
synchronized public void saveFromResponse(@Nullable HttpUrl url, List<Cookie> cookies) {
// cookies need to be reversed, in order to replace old cookies with these coming later
// (if there are duplicate cookies in the same response)
List<Cookie> reverseCookies = new ArrayList<>(cookies);
Collections.reverse(reverseCookies);
cache.addAll(reverseCookies);
persistor.saveAll(reverseCookies);
}
@NonNull
@Override
synchronized public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> removedCookies = new ArrayList<>();
List<Cookie> validCookies = new ArrayList<>();
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
Cookie currentCookie = it.next();
if (isCookieExpired(currentCookie)) {
removedCookies.add(currentCookie);
it.remove();
} else if (currentCookie.matches(url)) {
validCookies.add(currentCookie);
}
}
persistor.removeAll(removedCookies);
return validCookies;
}
@NonNull
synchronized public List<Cookie> getForDomain(String domain) {
List<Cookie> removedCookies = new ArrayList<>();
List<Cookie> validCookies = new ArrayList<>();
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
Cookie currentCookie = it.next();
if (isCookieExpired(currentCookie)) {
removedCookies.add(currentCookie);
it.remove();
} else if (domain.equals(currentCookie.domain())) {
validCookies.add(currentCookie);
}
}
persistor.removeAll(removedCookies);
return validCookies;
}
@Nullable
synchronized public String getCookie(String domain, String name) {
String cookieValue = null;
List<Cookie> removedCookies = new ArrayList<>();
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
Cookie currentCookie = it.next();
if (isCookieExpired(currentCookie)) {
removedCookies.add(currentCookie);
it.remove();
} else if (domain.equals(currentCookie.domain()) && name.equals(currentCookie.name())) {
cookieValue = currentCookie.value();
break;
}
}
persistor.removeAll(removedCookies);
return cookieValue;
}
private static boolean isCookieExpired(Cookie cookie) {
return cookie.expiresAt() < System.currentTimeMillis();
}
synchronized public void clear() {
cache.clear();
persistor.clear();
}
synchronized public void clearForDomain(String domain) {
cache.clearForDomain(domain);
persistor.clearForDomain(domain);
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.cache;
import java.util.Collection;
import okhttp3.Cookie;
public interface CookieCache extends Iterable<Cookie> {
/**
* Add all the new cookies to the session, existing cookies will be overwritten.
*
* @param cookies
*/
void addAll(Collection<Cookie> cookies);
/**
* Clear all the cookies from the session.
*/
void clear();
void clearForDomain(String domain);
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import okhttp3.Cookie;
/**
* This class decorates a Cookie to re-implements equals() and hashcode() methods in order to identify
* the cookie by the following attributes: name, domain, path, secure & hostOnly.<p>
*
* This new behaviour will be useful in determining when an already existing cookie in session must be overwritten.
*/
class IdentifiableCookie {
private Cookie cookie;
static List<IdentifiableCookie> decorateAll(Collection<Cookie> cookies) {
List<IdentifiableCookie> identifiableCookies = new ArrayList<>(cookies.size());
for (Cookie cookie : cookies) {
identifiableCookies.add(new IdentifiableCookie(cookie));
}
return identifiableCookies;
}
IdentifiableCookie(Cookie cookie) {
this.cookie = cookie;
}
Cookie getCookie() {
return cookie;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof IdentifiableCookie)) return false;
IdentifiableCookie that = (IdentifiableCookie) other;
return that.cookie.name().equals(this.cookie.name())
&& that.cookie.domain().equals(this.cookie.domain())
&& that.cookie.path().equals(this.cookie.path())
&& that.cookie.secure() == this.cookie.secure()
&& that.cookie.hostOnly() == this.cookie.hostOnly();
}
@Override
public int hashCode() {
int hash = 17;
if (cookie == null)
return hash;
hash = 31 * hash + cookie.name().hashCode();
hash = 31 * hash + cookie.domain().hashCode();
hash = 31 * hash + cookie.path().hashCode();
hash = 31 * hash + (cookie.secure() ? 0 : 1);
hash = 31 * hash + (cookie.hostOnly() ? 0 : 1);
return hash;
}
}

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import okhttp3.Cookie;
public class SetCookieCache implements CookieCache {
private Set<IdentifiableCookie> cookies;
public SetCookieCache() {
cookies = new HashSet<>();
}
@Override
public void addAll(Collection<Cookie> newCookies) {
updateCookies(IdentifiableCookie.decorateAll(newCookies));
}
/**
* All cookies will be added to the collection, already existing cookies will be overwritten by the new ones.
*
* @param cookies
*/
private void updateCookies(Collection<IdentifiableCookie> cookies) {
this.cookies.removeAll(cookies);
this.cookies.addAll(cookies);
}
@Override
public void clear() {
cookies.clear();
}
@Override
public void clearForDomain(String domain) {
Collection<IdentifiableCookie> removeCookies = new ArrayList<>();
for (IdentifiableCookie cookie: cookies) {
if (cookie.getCookie().domain().equals(domain)) {
removeCookies.add(cookie);
}
}
cookies.removeAll(removeCookies);
}
@Override
public Iterator<Cookie> iterator() {
return new SetCookieCacheIterator();
}
private class SetCookieCacheIterator implements Iterator<Cookie> {
private Iterator<IdentifiableCookie> iterator;
public SetCookieCacheIterator() {
iterator = cookies.iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Cookie next() {
return iterator.next().getCookie();
}
@Override
public void remove() {
iterator.remove();
}
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.persistence;
import java.util.Collection;
import java.util.List;
import okhttp3.Cookie;
public interface CookiePersistor {
List<Cookie> loadAll();
/**
* Persist all cookies, existing cookies will be overwritten.
*
* @param cookies cookies persist
*/
void saveAll(Collection<Cookie> cookies);
/**
* Removes indicated cookies from persistence.
*
* @param cookies cookies to remove from persistence
*/
void removeAll(Collection<Cookie> cookies);
/**
* Clear all cookies from persistence.
*/
void clear();
/**
* Clear all cookies from persistence for specified url.
*
* @param domain domain name
*/
void clearForDomain(String domain);
}

View File

@ -1,146 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.persistence;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import okhttp3.Cookie;
public class SerializableCookie implements Serializable {
private static final String TAG = SerializableCookie.class
.getSimpleName();
private transient Cookie cookie;
public String encode(Cookie cookie) {
this.cookie = cookie;
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ObjectOutputStream outputStream = new ObjectOutputStream(os);
outputStream.writeObject(this);
} catch (IOException e) {
Log.d(TAG, "IOException in encodeCookie", e);
return null;
}
return byteArrayToHexString(os.toByteArray());
}
/**
* Using some super basic byte array &lt;-&gt; hex conversions so we don't
* have to rely on any large Base64 libraries. Can be overridden if you
* like!
*
* @param bytes byte array to be converted
* @return string containing hex values
*/
private static String byteArrayToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte element : bytes) {
int v = element & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
public Cookie decode(String encodedCookie) {
byte[] bytes = hexStringToByteArray(encodedCookie);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
bytes);
Cookie cookie = null;
try {
ObjectInputStream objectInputStream = new ObjectInputStream(
byteArrayInputStream);
cookie = ((SerializableCookie) objectInputStream.readObject()).cookie;
} catch (IOException e) {
Log.d(TAG, "IOException in decodeCookie", e);
} catch (ClassNotFoundException e) {
Log.d(TAG, "ClassNotFoundException in decodeCookie", e);
}
return cookie;
}
/**
* Converts hex values from strings to byte array
*
* @param hexString string of hex-encoded values
* @return decoded byte array
*/
private static byte[] hexStringToByteArray(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
.digit(hexString.charAt(i + 1), 16));
}
return data;
}
private static long NON_VALID_EXPIRES_AT = -1l;
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(cookie.name());
out.writeObject(cookie.value());
out.writeLong(cookie.persistent() ? cookie.expiresAt() : NON_VALID_EXPIRES_AT);
out.writeObject(cookie.domain());
out.writeObject(cookie.path());
out.writeBoolean(cookie.secure());
out.writeBoolean(cookie.httpOnly());
out.writeBoolean(cookie.hostOnly());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
Cookie.Builder builder = new Cookie.Builder();
builder.name((String) in.readObject());
builder.value((String) in.readObject());
long expiresAt = in.readLong();
if (expiresAt != NON_VALID_EXPIRES_AT) {
builder.expiresAt(expiresAt);
}
final String domain = (String) in.readObject();
builder.domain(domain);
builder.path((String) in.readObject());
if (in.readBoolean())
builder.secure();
if (in.readBoolean())
builder.httpOnly();
if (in.readBoolean())
builder.hostOnlyDomain(domain);
cookie = builder.build();
}
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (C) 2016 Francisco José Montiel Navarro.
*
* 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 im.wangchao.mhttp.internal.cookie.persistence;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import okhttp3.Cookie;
public class SharedPrefsCookiePersistor implements CookiePersistor {
private SharedPreferences sharedPreferences;
public SharedPrefsCookiePersistor(Context context) {
final String SHARED_PREFERENCES_NAME = "cookies";
sharedPreferences =
context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
}
@Override
public List<Cookie> loadAll() {
List<Cookie> cookies = new ArrayList<>();
for (Map.Entry<String, ?> entry : sharedPreferences.getAll().entrySet()) {
String serializedCookie = (String) entry.getValue();
Cookie cookie = new SerializableCookie().decode(serializedCookie);
cookies.add(cookie);
}
return cookies;
}
@Override
public void saveAll(Collection<Cookie> cookies) {
SharedPreferences.Editor editor = sharedPreferences.edit();
for (Cookie cookie : cookies) {
if (cookie.persistent()) {
editor.putString(createCookieKey(cookie), new SerializableCookie().encode(cookie));
}
}
editor.apply();
}
@Override
public void removeAll(Collection<Cookie> cookies) {
SharedPreferences.Editor editor = sharedPreferences.edit();
for (Cookie cookie : cookies) {
editor.remove(createCookieKey(cookie));
}
editor.apply();
}
private static String createCookieKey(Cookie cookie) {
return (cookie.secure() ? "https" : "http") + "://" + cookie.domain() + cookie.path() + "|" + cookie.name();
}
@Override
public void clear() {
sharedPreferences.edit().clear().apply();
}
@Override
public void clearForDomain(String domain) {
List<Cookie> cookies = loadAll();
SharedPreferences.Editor editor = sharedPreferences.edit();
for (Cookie cookie : cookies) {
if (cookie.domain().equals(domain))
editor.remove(createCookieKey(cookie));
}
editor.apply();
}
}

View File

@ -1,17 +0,0 @@
package im.wangchao.mhttp.internal.exception;
/**
* <p>Description : ParserException.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/4/26.</p>
* <p>Time : 下午8:38.</p>
*/
public class ParserException extends Exception{
public ParserException(){
super("Response parse exception.");
}
public ParserException(Throwable cause) {
super("Response parse exception.", cause);
}
}

View File

@ -1,14 +0,0 @@
package im.wangchao.mhttp.internal.exception;
/**
* <p>Description : ResponseFailException.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/4/25.</p>
* <p>Time : 下午4:06.</p>
*/
public class ResponseFailException extends Exception{
//Response Non Successful
public ResponseFailException(){
super("Response failure exception.");
}
}

View File

@ -1,320 +0,0 @@
package im.wangchao.mhttp.internal.interceptor;
/*
* Copyright (C) 2015 Square, Inc.
*
* 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.
*/
import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import okhttp3.Connection;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.platform.Platform;
import okio.Buffer;
import okio.BufferedSource;
import okio.GzipSource;
import static okhttp3.internal.platform.Platform.INFO;
/**
* An OkHttp interceptor which logs request and response information. Can be applied as an
* {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain
* OkHttpClient#networkInterceptors() network interceptor}. <p> The format of the logs created by
* this class should not be considered stable and may change slightly between releases. If you need
* a stable logging format, use your own interceptor.
*/
public final class HttpLoggingInterceptor implements Interceptor {
private static final Charset UTF8 = Charset.forName("UTF-8");
public enum Level {
/** No logs. */
NONE,
/**
* Logs request and response lines.
*
* <p>Example:
* <pre>{@code
* --> POST /greeting http/1.1 (3-byte body)
*
* <-- 200 OK (22ms, 6-byte body)
* }</pre>
*/
BASIC,
/**
* Logs request and response lines and their respective headers.
*
* <p>Example:
* <pre>{@code
* --> POST /greeting http/1.1
* Host: example.com
* Content-Type: plain/text
* Content-Length: 3
* --> END POST
*
* <-- 200 OK (22ms)
* Content-Type: plain/text
* Content-Length: 6
* <-- END HTTP
* }</pre>
*/
HEADERS,
/**
* Logs request and response lines and their respective headers and bodies (if present).
*
* <p>Example:
* <pre>{@code
* --> POST /greeting http/1.1
* Host: example.com
* Content-Type: plain/text
* Content-Length: 3
*
* Hi?
* --> END POST
*
* <-- 200 OK (22ms)
* Content-Type: plain/text
* Content-Length: 6
*
* Hello!
* <-- END HTTP
* }</pre>
*/
BODY
}
public interface Logger {
void log(String message);
/** A {@link Logger} defaults output appropriate for the current platform. */
Logger DEFAULT = new Logger() {
@Override public void log(String message) {
Platform.get().log(INFO, message, null);
}
};
}
public HttpLoggingInterceptor() {
this(Logger.DEFAULT);
}
public HttpLoggingInterceptor(Logger logger) {
this.logger = logger;
}
private final Logger logger;
private volatile Level level = Level.NONE;
/** Change the level at which this interceptor logs. */
public HttpLoggingInterceptor setLevel(Level level) {
if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead.");
this.level = level;
return this;
}
public Level getLevel() {
return level;
}
@Override public Response intercept(Chain chain) throws IOException {
Level level = this.level;
Request request = chain.request();
if (level == Level.NONE) {
return chain.proceed(request);
}
boolean logBody = level == Level.BODY;
boolean logHeaders = logBody || level == Level.HEADERS;
RequestBody requestBody = request.body();
boolean hasRequestBody = requestBody != null;
Connection connection = chain.connection();
String requestStartMessage = "--> "
+ request.method()
+ ' ' + request.url()
+ (connection != null ? " " + connection.protocol() : "");
if (!logHeaders && hasRequestBody) {
requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
}
logger.log(requestStartMessage);
if (logHeaders) {
if (hasRequestBody) {
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
if (requestBody.contentType() != null) {
logger.log("Content-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
logger.log("Content-Length: " + requestBody.contentLength());
}
}
Headers headers = request.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
String name = headers.name(i);
// Skip headers from the request body as they are explicitly logged above.
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
logger.log(name + ": " + headers.value(i));
}
}
if (!logBody || !hasRequestBody) {
logger.log("--> END " + request.method());
} else if (bodyHasUnknownEncoding(request.headers())) {
logger.log("--> END " + request.method() + " (encoded body omitted)");
} else {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = UTF8;
MediaType contentType = requestBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
logger.log("");
if (isPlaintext(buffer)) {
logger.log(buffer.readString(charset));
logger.log("--> END " + request.method()
+ " (" + requestBody.contentLength() + "-byte body)");
} else {
logger.log("--> END " + request.method() + " (binary "
+ requestBody.contentLength() + "-byte body omitted)");
}
}
}
long startNs = System.nanoTime();
Response response;
try {
response = chain.proceed(request);
} catch (Exception e) {
logger.log("<-- HTTP FAILED: " + e);
throw e;
}
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
ResponseBody responseBody = response.body();
long contentLength = responseBody.contentLength();
String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length";
logger.log("<-- "
+ response.code()
+ (response.message().isEmpty() ? "" : ' ' + response.message())
+ ' ' + response.request().url()
+ " (" + tookMs + "ms" + (!logHeaders ? ", " + bodySize + " body" : "") + ')');
if (logHeaders) {
Headers headers = response.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
logger.log(headers.name(i) + ": " + headers.value(i));
}
if (!logBody || !HttpHeaders.hasBody(response)) {
logger.log("<-- END HTTP");
} else if (bodyHasUnknownEncoding(response.headers())) {
logger.log("<-- END HTTP (encoded body omitted)");
} else {
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Long gzippedLength = null;
if ("gzip".equalsIgnoreCase(headers.get("Content-Encoding"))) {
gzippedLength = buffer.size();
GzipSource gzippedResponseBody = null;
try {
gzippedResponseBody = new GzipSource(buffer.clone());
buffer = new Buffer();
buffer.writeAll(gzippedResponseBody);
} finally {
if (gzippedResponseBody != null) {
gzippedResponseBody.close();
}
}
}
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
if (!isPlaintext(buffer)) {
logger.log("");
logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
return response;
}
if (contentLength != 0) {
logger.log("");
logger.log(buffer.clone().readString(charset));
}
if (gzippedLength != null) {
logger.log("<-- END HTTP (" + buffer.size() + "-byte, "
+ gzippedLength + "-gzipped-byte body)");
} else {
logger.log("<-- END HTTP (" + buffer.size() + "-byte body)");
}
}
}
return response;
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
static boolean isPlaintext(Buffer buffer) {
try {
Buffer prefix = new Buffer();
long byteCount = buffer.size() < 64 ? buffer.size() : 64;
buffer.copyTo(prefix, 0, byteCount);
for (int i = 0; i < 16; i++) {
if (prefix.exhausted()) {
break;
}
int codePoint = prefix.readUtf8CodePoint();
if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
return false;
}
}
return true;
} catch (EOFException e) {
return false; // Truncated UTF-8 sequence.
}
}
private boolean bodyHasUnknownEncoding(Headers headers) {
String contentEncoding = headers.get("Content-Encoding");
return contentEncoding != null
&& !contentEncoding.equalsIgnoreCase("identity")
&& !contentEncoding.equalsIgnoreCase("gzip");
}
}

View File

@ -1,36 +0,0 @@
package im.wangchao.mhttp.internal.interceptor;
import java.io.IOException;
import im.wangchao.mhttp.internal.Singleton;
import im.wangchao.mhttp.internal.Version;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
* <p>Description : MBridgeInterceptors.</p>
* <p>Author : wangchao.</p>
* <p>Date : 16/8/24.</p>
* <p>Time : 下午4:32.</p>
*/
public final class MBridgeInterceptor implements Interceptor {
private MBridgeInterceptor(){}
public static Singleton<MBridgeInterceptor> instance = new Singleton<MBridgeInterceptor>() {
@Override protected MBridgeInterceptor create() {
return new MBridgeInterceptor();
}
};
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
if (request.header("User-Agent") == null) {
builder.header("User-Agent", Version.userAgent());
}
return chain.proceed(builder.build());
}
}

View File

@ -1,35 +0,0 @@
package im.wangchao.mhttp.internal.log;
import android.util.Log;
import im.wangchao.mhttp.internal.Singleton;
import im.wangchao.mhttp.internal.Version;
import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor;
/**
* <p>Description : Logger.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/20.</p>
* <p>Time : 下午5:36.</p>
*/
public class LoggerImpl implements HttpLoggingInterceptor.Logger{
private static final String TAG = Version.moduleName();
private HttpLoggingInterceptor.Level mLevel;
public static Singleton<LoggerImpl> instance = new Singleton<LoggerImpl>() {
@Override protected LoggerImpl create() {
return new LoggerImpl();
}
};
public void setLevel(HttpLoggingInterceptor.Level level){
mLevel = level;
}
@Override public void log(String message) {
if (mLevel == HttpLoggingInterceptor.Level.NONE){
return;
}
Log.e(TAG, message);
}
}

View File

@ -1,133 +0,0 @@
package im.wangchao.mhttp.rxjava2;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Request;
import im.wangchao.mhttp.Response;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.CompositeException;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.plugins.RxJavaPlugins;
/**
* <p>Description : ResponseEnqueueObservable.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/19.</p>
* <p>Time : 下午4:45.</p>
*/
public class ResponseEnqueueObservable<T> extends Observable<T> {
private final RxRequest<T> request;
public ResponseEnqueueObservable(RxRequest<T> request){
this.request = request;
}
@Override protected void subscribeActual(Observer<? super T> observer) {
AbsCallbackHandler<T> callback = request.callback();
EnqueueDisposable<T> disposable = new EnqueueDisposable<>(observer, callback);
observer.onSubscribe(disposable);
request.request().newBuilder().callback(disposable).build().enqueue();
}
private static final class EnqueueDisposable<T> extends AbsCallbackHandler<T> implements Disposable{
private final AbsCallbackHandler<T> originCallback;
private final Observer<? super T> observer;
private volatile boolean disposed;
boolean terminated = false;
EnqueueDisposable(Observer<? super T> observer, AbsCallbackHandler<T> callbackHandler){
this.observer = observer;
this.originCallback = callbackHandler;
}
@Override public void dispose() {
disposed = true;
Request request = getRequest();
request.cancel();
}
@Override public boolean isDisposed() {
return disposed;
}
@Override public String charset() {
return originCallback.charset();
}
@Override public String accept() {
return originCallback.accept();
}
@Override public void onStart() {
originCallback.onStart();
}
@Override public void onUploadProgress(int bytesWritten, int bytesTotal) {
originCallback.onUploadProgress(bytesWritten, bytesTotal);
}
@Override public void onProgress(long bytesWritten, long bytesTotal) {
originCallback.onProgress(bytesWritten, bytesTotal);
}
@Override public void onFinish() {
originCallback.onFinish();
}
@Override public void onCancel() {
originCallback.onCancel();
if (!disposed){
dispose();
}
}
@Override public T apply(Response response) throws Exception {
return originCallback.apply(response);
}
@Override public void onSuccess(T data, Response response) {
if (disposed) return;
try {
originCallback.onSuccess(data, response);
observer.onNext(data);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposed) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
@Override public void onFailure(Response response, Throwable throwable) {
try {
originCallback.onFailure(response, throwable);
observer.onError(throwable);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(throwable, inner));
}
}
@Override public void onFinally(Response response) {
originCallback.onFinally(response);
}
}
}

View File

@ -1,76 +0,0 @@
package im.wangchao.mhttp.rxjava2;
import im.wangchao.mhttp.Converter;
import im.wangchao.mhttp.Request;
import im.wangchao.mhttp.Response;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.exceptions.CompositeException;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.plugins.RxJavaPlugins;
/**
* <p>Description : ResponseExecuteObservable.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/19.</p>
* <p>Time : 下午4:46.</p>
*/
public class ResponseExecuteObservable<T> extends Observable<T> {
private final RxRequest<T> request;
private final Converter<Response, T> converter;
public ResponseExecuteObservable(RxRequest<T> request, Converter<Response, T> converter){
this.request = request;
this.converter = converter;
}
@Override protected void subscribeActual(Observer<? super T> observer) {
ExecuteDisposable disposable = new ExecuteDisposable(request.request());
observer.onSubscribe(disposable);
boolean terminated = false;
try {
T response = converter.apply(request.request().execute());
if (!disposable.isDisposed()) {
observer.onNext(response);
}
if (!disposable.isDisposed()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposable.isDisposed()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
private static final class ExecuteDisposable implements Disposable {
private final Request request;
private volatile boolean disposed;
ExecuteDisposable(Request request) {
this.request = request;
}
@Override public void dispose() {
disposed = true;
request.cancel();
}
@Override public boolean isDisposed() {
return disposed;
}
}
}

View File

@ -1,233 +0,0 @@
package im.wangchao.mhttp.rxjava2;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.Executor;
import im.wangchao.mhttp.AbsCallbackHandler;
import im.wangchao.mhttp.Converter;
import im.wangchao.mhttp.Method;
import im.wangchao.mhttp.Request;
import im.wangchao.mhttp.RequestParams;
import im.wangchao.mhttp.Response;
import im.wangchao.mhttp.ThreadMode;
import io.reactivex.Observable;
import okhttp3.CacheControl;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
/**
* <p>Description : RxRequest.</p>
* <p>Author : wangchao.</p>
* <p>Date : 2018/3/26.</p>
* <p>Time : 下午5:40.</p>
*/
public class RxRequest<T> {
public static <T> RxRequest.Builder<T> builder(){
return new RxRequest.Builder<>();
}
private Request request;
private AbsCallbackHandler<T> callback;
private RxRequest(Builder<T> builder){
request = builder.request;
callback = builder.callback;
}
public Request request(){
return request;
}
public AbsCallbackHandler<T> callback(){
return callback;
}
public RxRequest.Builder<T> newBuilder() {
return new Builder<>(this);
}
public Observable<T> execute(Converter<Response, T> converter){
return new ResponseExecuteObservable<>(this, converter);
}
public Observable<T> enqueue(){
return new ResponseEnqueueObservable<>(this);
}
public static final class Builder<T> {
Request request;
Request.Builder requestBuilder;
AbsCallbackHandler<T> callback;
public Builder() {
requestBuilder = new Request.Builder();
callback = new AbsCallbackHandler<T>() {
@Override public void onSuccess(T data, Response response) {
}
@Override public void onFailure(Response response, Throwable throwable) {
}
};
}
private Builder(RxRequest<T> request) {
requestBuilder = request.request.newBuilder();
callback = request.callback;
}
public Builder<T> url(HttpUrl url) {
requestBuilder.url(url);
return this;
}
public Builder<T> url(String url) {
requestBuilder.url(url);
return this;
}
public Builder<T> url(URL url) {
requestBuilder.url(url);
return this;
}
public Builder<T> header(String name, String value) {
requestBuilder.header(name, value);
return this;
}
public Builder<T> addHeader(String name, String value) {
requestBuilder.header(name, value);
return this;
}
public Builder<T> removeHeader(String name) {
requestBuilder.removeHeader(name);
return this;
}
public Builder<T> headers(Headers headers) {
requestBuilder.headers(headers);
return this;
}
public Builder<T> cacheControl(CacheControl cacheControl) {
requestBuilder.cacheControl(cacheControl);
return this;
}
public Builder<T> get() {
return method(Method.GET);
}
public Builder<T> head() {
return method(Method.HEAD);
}
public Builder<T> post() {
return method(Method.POST);
}
public Builder<T> delete() {
return method(Method.DELETE);
}
public Builder<T> put() {
return method(Method.PUT);
}
public Builder<T> patch() {
return method(Method.PATCH);
}
/**
* Simple to add request parameter
*/
public Builder<T> addParameter(String key, Object value){
requestBuilder.addParameter(key, value);
return this;
}
/**
* Simple to add request parameter
*/
public Builder<T> addParameter(String key, InputStream stream, String name){
requestBuilder.addParameter(key, stream, name);
return this;
}
/**
* Simple to add request parameter
*/
public Builder<T> addParameter(String key, InputStream stream, String name, String contentType){
requestBuilder.addParameter(key, stream, name, contentType);
return this;
}
/**
* Simple to add request parameter
*/
public Builder<T> addParameter(String key, File file, String contentType) {
requestBuilder.addParameter(key, file, contentType);
return this;
}
public Builder<T> requestParams(RequestParams params) {
requestBuilder.requestParams(params);
return this;
}
public Builder<T> method(@NonNull String method) {
requestBuilder.method(method);
return this;
}
public Builder<T> tag(Object tag) {
requestBuilder.tag(tag);
return this;
}
public Builder<T> callback(@NonNull AbsCallbackHandler<T> callback){
this.callback = callback;
return this;
}
public Builder<T> callbackExecutor(Executor executor){
requestBuilder.callbackExecutor(executor);
return this;
}
public Builder<T> callbackThreadMode(ThreadMode threadMode){
requestBuilder.callbackThreadMode(threadMode);
return this;
}
public Builder<T> userAgent(String ua){
requestBuilder.userAgent(ua);
return this;
}
public Builder<T> contentType(@NonNull String contentType){
requestBuilder.contentType(contentType);
return this;
}
public Builder<T> contentType(@NonNull MediaType mediaType){
requestBuilder.contentType(mediaType);
return this;
}
public RxRequest<T> build() {
request = requestBuilder.build();
return new RxRequest<>(this);
}
}
}

View File

@ -3,7 +3,7 @@ include ':wear'
include ':codegen'
include ':annotation'
rootProject.name='Szkolny.eu'
include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font'
include ':app', ':agendacalendarview', ':szkolny-font'
/*
include ':Navigation'
project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/