public Builder ( ) {
dispatcher = new Dispatcher ( ) ;
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener . factory ( EventListener . NONE) ;
proxySelector = ProxySelector . getDefault ( ) ;
cookieJar = CookieJar . NO_COOKIES;
socketFactory = SocketFactory . getDefault ( ) ;
hostnameVerifier = OkHostnameVerifier . INSTANCE;
certificatePinner = CertificatePinner . DEFAULT;
proxyAuthenticator = Authenticator . NONE;
authenticator = Authenticator . NONE;
connectionPool = new ConnectionPool ( ) ;
dns = Dns . SYSTEM;
followSslRedirects = true ;
followRedirects = true ;
retryOnConnectionFailure = true ;
connectTimeout = 10_000 ;
readTimeout = 10_000 ;
writeTimeout = 10_000 ;
pingInterval = 0 ;
}
public final class Dispatcher {
private int maxRequests = 64 ;
private int maxRequestsPerHost = 5 ;
private @Nullable Runnable idleCallback;
private @Nullable ExecutorService executorService;
private final Deque < AsyncCall > readyAsyncCalls = new ArrayDeque < > ( ) ;
private final Deque < AsyncCall > runningAsyncCalls = new ArrayDeque < > ( ) ;
private final Deque < RealCall > runningSyncCalls = new ArrayDeque < > ( ) ;
public synchronized ExecutorService executorService ( ) {
if ( executorService == null ) {
executorService = new ThreadPoolExecutor ( 0 , Integer . MAX_VALUE, 60 , TimeUnit . SECONDS,
new SynchronousQueue < Runnable > ( ) , Util . threadFactory ( "OkHttp Dispatcher" , false ) ) ;
}
return executorService;
}
}
public static class Builder {
HttpUrl url;
String method;
Headers. Builder headers;
RequestBody body;
Object tag;
public Builder ( ) {
this . method = "GET" ;
this . headers = new Headers. Builder ( ) ;
}
public Builder url ( HttpUrl url) {
if ( url == null ) throw new NullPointerException ( "url == null" ) ;
this . url = url;
return this ;
}
public Request build ( ) {
if ( url == null ) throw new IllegalStateException ( "url == null" ) ;
return new Request ( this ) ;
}
. . .
}
public Call newCall ( Request request) {
return RealCall . newRealCall ( this , request, false ) ;
}
static RealCall newRealCall ( OkHttpClient client, Request originalRequest, boolean forWebSocket) {
RealCall call = new RealCall ( client, originalRequest, forWebSocket) ;
call. eventListener = client. eventListenerFactory ( ) . create ( call) ;
return call;
}
private RealCall ( OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this . client = client;
this . originalRequest = originalRequest;
this . forWebSocket = forWebSocket;
this . retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor ( client, forWebSocket) ;
}
public void enqueue ( Callback responseCallback) {
synchronized ( this ) {
if ( executed) throw new IllegalStateException ( "Already Executed" ) ;
executed = true ;
}
captureCallStackTrace ( ) ;
eventListener. callStart ( this ) ;
client. dispatcher ( ) . enqueue ( new AsyncCall ( responseCallback) ) ;
}
synchronized void enqueue ( AsyncCall call) {
if ( runningAsyncCalls. size ( ) < maxRequests && runningCallsForHost ( call) < maxRequestsPerHost) {
runningAsyncCalls. add ( call) ;
executorService ( ) . execute ( call) ;
} else {
readyAsyncCalls. add ( call) ;
}
}
public Response proceed ( Request request) throws IOException {
return proceed ( request, streamAllocation, httpCodec, connection) ;
}
public Response proceed ( Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
RealInterceptorChain next = new RealInterceptorChain ( interceptors, streamAllocation, httpCodec,
connection, index + 1 , request, call, eventListener, connectTimeout, readTimeout,
writeTimeout) ;
Interceptor interceptor = interceptors. get ( index) ;
Response response = interceptor. intercept ( next) ;
return response;
}
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable ( String format, Object . . . args) {
this . name = Util . format ( format, args) ;
}
@Override public final void run ( ) {
String oldName = Thread . currentThread ( ) . getName ( ) ;
Thread . currentThread ( ) . setName ( name) ;
try {
execute ( ) ;
} finally {
Thread . currentThread ( ) . setName ( oldName) ;
}
}
protected abstract void execute ( ) ;
}
final class AsyncCall extends NamedRunnable {
@Override protected void execute ( ) {
boolean signalledCallback = false ;
try {
Response response = getResponseWithInterceptorChain ( ) ;
if ( retryAndFollowUpInterceptor. isCanceled ( ) ) {
signalledCallback = true ;
responseCallback. onFailure ( RealCall . this , new IOException ( "Canceled" ) ) ;
} else {
signalledCallback = true ;
responseCallback. onResponse ( RealCall . this , response) ;
}
} catch ( IOException e) {
if ( signalledCallback) {
Platform . get ( ) . log ( INFO, "Callback failure for " + toLoggableString ( ) , e) ;
} else {
eventListener. callFailed ( RealCall . this , e) ;
responseCallback. onFailure ( RealCall . this , e) ;
}
} finally {
client. dispatcher ( ) . finished ( this ) ;
}
}
}
void finished ( AsyncCall call) {
finished ( runningAsyncCalls, call, true ) ;
}
private < T > void finished ( Deque < T > calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized ( this ) {
if ( ! calls. remove ( call) ) throw new AssertionError ( "Call wasn't in-flight!" ) ;
if ( promoteCalls) promoteCalls ( ) ;
runningCallsCount = runningCallsCount ( ) ;
idleCallback = this . idleCallback;
}
if ( runningCallsCount == 0 && idleCallback != null ) {
idleCallback. run ( ) ;
}
}
private void promoteCalls ( ) {
if ( runningAsyncCalls. size ( ) >= maxRequests) return ;
if ( readyAsyncCalls. isEmpty ( ) ) return ;
for ( Iterator < AsyncCall > i = readyAsyncCalls. iterator ( ) ; i. hasNext ( ) ; ) {
AsyncCall call = i. next ( ) ;
if ( runningCallsForHost ( call) < maxRequestsPerHost) {
i. remove ( ) ;
runningAsyncCalls. add ( call) ;
executorService ( ) . execute ( call) ;
}
if ( runningAsyncCalls. size ( ) >= maxRequests) return ;
}
}