Android Open Source - android Job

From Project

Back to project page android.


The source code is released under:

GNU General Public License

If you think the Android project android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

 * Copyright (C) 2013 Square, Inc.//  w w w  .  ja v  a2 s .c  o m
 * 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
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.
package com.squareup.okhttp;

import com.squareup.okhttp.internal.http.HttpAuthenticator;
import com.squareup.okhttp.internal.http.HttpEngine;
import com.squareup.okhttp.internal.http.HttpTransport;
import com.squareup.okhttp.internal.http.HttpsEngine;
import com.squareup.okhttp.internal.http.Policy;
import com.squareup.okhttp.internal.http.RawHeaders;

import static com.squareup.okhttp.internal.Util.getEffectivePort;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_MOVED_PERM;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_MOVED_TEMP;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_MULT_CHOICE;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_PROXY_AUTH;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_SEE_OTHER;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_TEMP_REDIRECT;
import static com.squareup.okhttp.internal.http.HttpURLConnectionImpl.HTTP_UNAUTHORIZED;

final class Job implements Runnable, Policy {
  private final Dispatcher dispatcher;
  private final OkHttpClient client;
  private final Response.Receiver responseReceiver;

  /** The request; possibly a consequence of redirects or auth headers. */
  private Request request;

  public Job(Dispatcher dispatcher, OkHttpClient client, Request request,
      Response.Receiver responseReceiver) {
    this.dispatcher = dispatcher;
    this.client = client;
    this.request = request;
    this.responseReceiver = responseReceiver;

  @Override public int getChunkLength() {
    return request.body().contentLength() == -1 ? HttpTransport.DEFAULT_CHUNK_LENGTH : -1;

  @Override public long getFixedContentLength() {
    return request.body().contentLength();

  @Override public boolean getUseCaches() {
    return false; // TODO.

  @Override public HttpURLConnection getHttpConnectionToCache() {
    return null;

  @Override public URL getURL() {
    return request.url();

  @Override public long getIfModifiedSince() {
    return 0; // For HttpURLConnection only. We let the cache drive this.

  @Override public boolean usingProxy() {
    return false; // We let the connection decide this.

  @Override public void setSelectedProxy(Proxy proxy) {
    // Do nothing.

  Object tag() {
    return request.tag();

  @Override public void run() {
    try {
      Response response = execute();
    } catch (IOException e) {
      responseReceiver.onFailure(new Failure.Builder()
    } finally {
      // TODO: close the response body
      // TODO: release the HTTP engine (potentially multiple!)

  private Response execute() throws IOException {
    Connection connection = null;
    Response redirectedBy = null;

    while (true) {
      HttpEngine engine = newEngine(connection);

      Request.Body body = request.body();
      if (body != null) {
        MediaType contentType = body.contentType();
        if (contentType == null) throw new IllegalStateException("contentType == null");
        if (engine.getRequestHeaders().getContentType() == null) {


      if (body != null) {


      int responseCode = engine.getResponseCode();
      Dispatcher.RealResponseBody responseBody = new Dispatcher.RealResponseBody(
          engine.getResponseHeaders(), engine.getResponseBody());

      Response response = new Response.Builder(request, responseCode)

      Request redirect = processResponse(engine, response);

      if (redirect == null) {
        return response;

      // TODO: fail if too many redirects
      // TODO: fail if not following redirects
      // TODO: release engine

      connection = sameConnection(request, redirect) ? engine.getConnection() : null;
      redirectedBy = response;
      request = redirect;

  HttpEngine newEngine(Connection connection) throws IOException {
    String protocol = request.url().getProtocol();
    RawHeaders requestHeaders = request.rawHeaders();
    if (protocol.equals("http")) {
      return new HttpEngine(client, this, request.method(), requestHeaders, connection, null);
    } else if (protocol.equals("https")) {
      return new HttpsEngine(client, this, request.method(), requestHeaders, connection, null);
    } else {
      throw new AssertionError();

   * Figures out the HTTP request to make in response to receiving {@code
   * response}. This will either add authentication headers or follow
   * redirects. If a follow-up is either unnecessary or not applicable, this
   * returns null.
  private Request processResponse(HttpEngine engine, Response response) throws IOException {
    Request request = response.request();
    Proxy selectedProxy = engine.getConnection() != null
        ? engine.getConnection().getRoute().getProxy()
        : client.getProxy();
    int responseCode = response.code();

    switch (responseCode) {
      case HTTP_PROXY_AUTH:
        if (selectedProxy.type() != Proxy.Type.HTTP) {
          throw new ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy");
        // fall-through
        RawHeaders successorRequestHeaders = request.rawHeaders();
        boolean credentialsFound = HttpAuthenticator.processAuthHeader(client.getAuthenticator(),
            response.code(), response.rawHeaders(), successorRequestHeaders, selectedProxy,
        return credentialsFound
            ? request.newBuilder().rawHeaders(successorRequestHeaders).build()
            : null;

      case HTTP_MULT_CHOICE:
      case HTTP_MOVED_PERM:
      case HTTP_MOVED_TEMP:
      case HTTP_SEE_OTHER:
        String method = request.method();
        if (responseCode == HTTP_TEMP_REDIRECT && !method.equals("GET") && !method.equals("HEAD")) {
          // "If the 307 status code is received in response to a request other than GET or HEAD,
          // the user agent MUST NOT automatically redirect the request"
          return null;

        String location = response.header("Location");
        if (location == null) {
          return null;

        URL url = new URL(request.url(), location);
        if (!url.getProtocol().equals("https") && !url.getProtocol().equals("http")) {
          return null; // Don't follow redirects to unsupported protocols.

        return this.request.newBuilder().url(url).build();

        return null;

  private boolean sameConnection(Request a, Request b) {
    return a.url().getHost().equals(b.url().getHost())
        && getEffectivePort(a.url()) == getEffectivePort(b.url())
        && a.url().getProtocol().equals(b.url().getProtocol());

Java Source Code List