package com.virjar.dungproxy.client.ningclient.conn;
import java.lang.reflect.InvocationTargetException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ning.http.client.*;
import com.ning.http.client.providers.jdk.JDKAsyncHttpProvider;
import com.ning.http.client.uri.Uri;
import com.virjar.dungproxy.client.ippool.IpPool;
import com.virjar.dungproxy.client.ippool.IpPoolHolder;
import com.virjar.dungproxy.client.model.AvProxy;
/**
* Created by virjar on 17/1/31. <br/>
* 注入本类即可实现IP绑定和IP上下线
*/
public class DungProxyAsyncHttpProvider implements AsyncHttpProvider {
private static final Logger logger = LoggerFactory.getLogger(DungProxyAsyncHttpProvider.class);
private final static String DEFAULT_PROVIDER = "com.ning.http.client.providers.netty.NettyAsyncHttpProvider";
private AsyncHttpProvider delegate;
private IpPool ipPool;
/**
* 这种情况必须引入netty
*/
public DungProxyAsyncHttpProvider() {
this(null, null);
}
public DungProxyAsyncHttpProvider(AsyncHttpProvider asyncHttpProvider, AsyncHttpClientConfig config) {
if (asyncHttpProvider == null) {
asyncHttpProvider = loadDefaultProvider(DEFAULT_PROVIDER, config);
}
this.delegate = asyncHttpProvider;
ipPool = IpPoolHolder.getIpPool();// TODO 这里是否需要扩展
}
public DungProxyAsyncHttpProvider(AsyncHttpProvider asyncHttpProvider) {
this(asyncHttpProvider, null);
}
@Override
public <T> ListenableFuture<T> execute(Request request, AsyncHandler<T> handler) {
Uri uri = request.getUri();
if (request.getProxyServer() == null) {// 在这里绑定IP池
AvProxy proxy = ipPool.bind(uri.getHost(), uri.toUrl());
if (proxy != null) {
return delegate.execute(new DungProxyRequest(request, proxy),
new DungProxyHandler<>(proxy, handler));
}
}
return delegate.execute(request, handler);
}
@Override
public void close() {
delegate.close();
}
@SuppressWarnings("unchecked")
private final static AsyncHttpProvider loadDefaultProvider(String className, AsyncHttpClientConfig config) {
try {
Class<AsyncHttpProvider> providerClass = (Class<AsyncHttpProvider>) Thread.currentThread()
.getContextClassLoader().loadClass(className);
return providerClass.getDeclaredConstructor(new Class[] { AsyncHttpClientConfig.class })
.newInstance(new Object[] { config });
} catch (Throwable t) {
if (t instanceof InvocationTargetException) {
final InvocationTargetException ite = (InvocationTargetException) t;
if (logger.isErrorEnabled()) {
logger.error("Unable to instantiate provider {}. Trying other providers.", className);
logger.error(ite.getCause().toString(), ite.getCause());
}
}
// Let's try with another classloader
try {
Class<AsyncHttpProvider> providerClass = (Class<AsyncHttpProvider>) AsyncHttpClient.class
.getClassLoader().loadClass(className);
return providerClass.getDeclaredConstructor(new Class[] { AsyncHttpClientConfig.class })
.newInstance(new Object[] { config });
} catch (Throwable t2) {
}
if (logger.isDebugEnabled()) {
logger.debug("Default provider not found {}. Using the {}", DEFAULT_PROVIDER,
JDKAsyncHttpProvider.class.getName());
}
if (config != null) {
return new JDKAsyncHttpProvider(config);
}
throw new IllegalStateException("不支持自动产生JDKAsyncHttpProvider 请手动注入");// 应该不会发生
// return new JDKAsyncHttpProvider(config);
}
}
}