Android Open Source - wototoplayer Http Response Cache






From Project

Back to project page wototoplayer.

License

The source code is released under:

Copyright (c) 2015, Chris Greenhalgh All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met...

If you think the Android project wototoplayer 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) 2010 The Android Open Source Project
 *//from  w  ww.jav a 2  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
 *
 *      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 com.squareup.okhttp;

import com.squareup.okhttp.internal.Base64;
import com.squareup.okhttp.internal.DiskLruCache;
import com.squareup.okhttp.internal.StrictLineReader;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.http.HttpEngine;
import com.squareup.okhttp.internal.http.HttpURLConnectionImpl;
import com.squareup.okhttp.internal.http.HttpsEngine;
import com.squareup.okhttp.internal.http.HttpsURLConnectionImpl;
import com.squareup.okhttp.internal.http.RawHeaders;
import com.squareup.okhttp.internal.http.ResponseHeaders;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.CacheRequest;
import java.net.CacheResponse;
import java.net.HttpURLConnection;
import java.net.ResponseCache;
import java.net.SecureCacheResponse;
import java.net.URI;
import java.net.URLConnection;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;

import static com.squareup.okhttp.internal.Util.US_ASCII;
import static com.squareup.okhttp.internal.Util.UTF_8;

/**
 * Caches HTTP and HTTPS responses to the filesystem so they may be reused,
 * saving time and bandwidth.
 *
 * <h3>Cache Optimization</h3>
 * To measure cache effectiveness, this class tracks three statistics:
 * <ul>
 *     <li><strong>{@link #getRequestCount() Request Count:}</strong> the number
 *         of HTTP requests issued since this cache was created.
 *     <li><strong>{@link #getNetworkCount() Network Count:}</strong> the
 *         number of those requests that required network use.
 *     <li><strong>{@link #getHitCount() Hit Count:}</strong> the number of
 *         those requests whose responses were served by the cache.
 * </ul>
 * Sometimes a request will result in a conditional cache hit. If the cache
 * contains a stale copy of the response, the client will issue a conditional
 * {@code GET}. The server will then send either the updated response if it has
 * changed, or a short 'not modified' response if the client's copy is still
 * valid. Such responses increment both the network count and hit count.
 *
 * <p>The best way to improve the cache hit rate is by configuring the web
 * server to return cacheable responses. Although this client honors all <a
 * href="http://www.ietf.org/rfc/rfc2616.txt">HTTP/1.1 (RFC 2068)</a> cache
 * headers, it doesn't cache partial responses.
 *
 * <h3>Force a Network Response</h3>
 * In some situations, such as after a user clicks a 'refresh' button, it may be
 * necessary to skip the cache, and fetch data directly from the server. To force
 * a full refresh, add the {@code no-cache} directive: <pre>   {@code
 *         connection.addRequestProperty("Cache-Control", "no-cache");
 * }</pre>
 * If it is only necessary to force a cached response to be validated by the
 * server, use the more efficient {@code max-age=0} instead: <pre>   {@code
 *         connection.addRequestProperty("Cache-Control", "max-age=0");
 * }</pre>
 *
 * <h3>Force a Cache Response</h3>
 * Sometimes you'll want to show resources if they are available immediately,
 * but not otherwise. This can be used so your application can show
 * <i>something</i> while waiting for the latest data to be downloaded. To
 * restrict a request to locally-cached resources, add the {@code
 * only-if-cached} directive: <pre>   {@code
 *     try {
 *         connection.addRequestProperty("Cache-Control", "only-if-cached");
 *         InputStream cached = connection.getInputStream();
 *         // the resource was cached! show it
 *     } catch (FileNotFoundException e) {
 *         // the resource was not cached
 *     }
 * }</pre>
 * This technique works even better in situations where a stale response is
 * better than no response. To permit stale cached responses, use the {@code
 * max-stale} directive with the maximum staleness in seconds: <pre>   {@code
 *         int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
 *         connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
 * }</pre>
 */
public final class HttpResponseCache extends ResponseCache {
  // TODO: add APIs to iterate the cache?
  private static final int VERSION = 201105;
  private static final int ENTRY_METADATA = 0;
  private static final int ENTRY_BODY = 1;
  private static final int ENTRY_COUNT = 2;

  private final DiskLruCache cache;

  /* read and write statistics, all guarded by 'this' */
  private int writeSuccessCount;
  private int writeAbortCount;
  private int networkCount;
  private int hitCount;
  private int requestCount;

  /**
   * Although this class only exposes the limited ResponseCache API, it
   * implements the full OkResponseCache interface. This field is used as a
   * package private handle to the complete implementation. It delegates to
   * public and private members of this type.
   */
  final OkResponseCache okResponseCache = new OkResponseCache() {
    @Override public CacheResponse get(URI uri, String requestMethod,
        Map<String, List<String>> requestHeaders) throws IOException {
      return HttpResponseCache.this.get(uri, requestMethod, requestHeaders);
    }

    @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
      return HttpResponseCache.this.put(uri, connection);
    }

    @Override public void maybeRemove(String requestMethod, URI uri) throws IOException {
      HttpResponseCache.this.maybeRemove(requestMethod, uri);
    }

    @Override public void update(
        CacheResponse conditionalCacheHit, HttpURLConnection connection) throws IOException {
      HttpResponseCache.this.update(conditionalCacheHit, connection);
    }

    @Override public void trackConditionalCacheHit() {
      HttpResponseCache.this.trackConditionalCacheHit();
    }

    @Override public void trackResponse(ResponseSource source) {
      HttpResponseCache.this.trackResponse(source);
    }
  };

  public HttpResponseCache(File directory, long maxSize) throws IOException {
    cache = DiskLruCache.open(directory, VERSION, ENTRY_COUNT, maxSize);
  }

  private String uriToKey(URI uri) {
    return Util.hash(uri.toString());
  }

  @Override public CacheResponse get(URI uri, String requestMethod,
      Map<String, List<String>> requestHeaders) {
    String key = uriToKey(uri);
    DiskLruCache.Snapshot snapshot;
    Entry entry;
    try {
      snapshot = cache.get(key);
      if (snapshot == null) {
        return null;
      }
      entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
    } catch (IOException e) {
      // Give up because the cache cannot be read.
      return null;
    }

    if (!entry.matches(uri, requestMethod, requestHeaders)) {
      snapshot.close();
      return null;
    }

    return entry.isHttps() ? new EntrySecureCacheResponse(entry, snapshot)
        : new EntryCacheResponse(entry, snapshot);
  }

  @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
    if (!(urlConnection instanceof HttpURLConnection)) {
      return null;
    }

    HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
    String requestMethod = httpConnection.getRequestMethod();

    if (maybeRemove(requestMethod, uri)) {
      return null;
    }
    if (!requestMethod.equals("GET")) {
      // Don't cache non-GET responses. We're technically allowed to cache
      // HEAD requests and some POST requests, but the complexity of doing
      // so is high and the benefit is low.
      return null;
    }

    HttpEngine httpEngine = getHttpEngine(httpConnection);
    if (httpEngine == null) {
      // Don't cache unless the HTTP implementation is ours.
      return null;
    }

    ResponseHeaders response = httpEngine.getResponseHeaders();
    if (response.hasVaryAll()) {
      return null;
    }

    RawHeaders varyHeaders =
        httpEngine.getRequestHeaders().getHeaders().getAll(response.getVaryFields());
    Entry entry = new Entry(uri, varyHeaders, httpConnection);
    DiskLruCache.Editor editor = null;
    try {
      editor = cache.edit(uriToKey(uri));
      if (editor == null) {
        return null;
      }
      entry.writeTo(editor);
      return new CacheRequestImpl(editor);
    } catch (IOException e) {
      abortQuietly(editor);
      return null;
    }
  }

  /**
   * Returns true if the supplied {@code requestMethod} potentially invalidates an entry in the
   * cache.
   */
  private boolean maybeRemove(String requestMethod, URI uri) {
    if (requestMethod.equals("POST") || requestMethod.equals("PUT") || requestMethod.equals(
        "DELETE")) {
      try {
        cache.remove(uriToKey(uri));
      } catch (IOException ignored) {
        // The cache cannot be written.
      }
      return true;
    }
    return false;
  }

  private void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection)
      throws IOException {
    HttpEngine httpEngine = getHttpEngine(httpConnection);
    URI uri = httpEngine.getUri();
    ResponseHeaders response = httpEngine.getResponseHeaders();
    RawHeaders varyHeaders =
        httpEngine.getRequestHeaders().getHeaders().getAll(response.getVaryFields());
    Entry entry = new Entry(uri, varyHeaders, httpConnection);
    DiskLruCache.Snapshot snapshot = (conditionalCacheHit instanceof EntryCacheResponse)
        ? ((EntryCacheResponse) conditionalCacheHit).snapshot
        : ((EntrySecureCacheResponse) conditionalCacheHit).snapshot;
    DiskLruCache.Editor editor = null;
    try {
      editor = snapshot.edit(); // returns null if snapshot is not current
      if (editor != null) {
        entry.writeTo(editor);
        editor.commit();
      }
    } catch (IOException e) {
      abortQuietly(editor);
    }
  }

  private void abortQuietly(DiskLruCache.Editor editor) {
    // Give up because the cache cannot be written.
    try {
      if (editor != null) {
        editor.abort();
      }
    } catch (IOException ignored) {
    }
  }

  private HttpEngine getHttpEngine(URLConnection httpConnection) {
    if (httpConnection instanceof HttpURLConnectionImpl) {
      return ((HttpURLConnectionImpl) httpConnection).getHttpEngine();
    } else if (httpConnection instanceof HttpsURLConnectionImpl) {
      return ((HttpsURLConnectionImpl) httpConnection).getHttpEngine();
    } else {
      return null;
    }
  }

  /**
   * Closes the cache and deletes all of its stored values. This will delete
   * all files in the cache directory including files that weren't created by
   * the cache.
   */
  public void delete() throws IOException {
    cache.delete();
  }

  public synchronized int getWriteAbortCount() {
    return writeAbortCount;
  }

  public synchronized int getWriteSuccessCount() {
    return writeSuccessCount;
  }

  public long getSize() {
    return cache.size();
  }

  public long getMaxSize() {
    return cache.getMaxSize();
  }

  public void flush() throws IOException {
    cache.flush();
  }

  public void close() throws IOException {
    cache.close();
  }

  public File getDirectory() {
    return cache.getDirectory();
  }

  public boolean isClosed() {
    return cache.isClosed();
  }

  private synchronized void trackResponse(ResponseSource source) {
    requestCount++;

    switch (source) {
      case CACHE:
        hitCount++;
        break;
      case CONDITIONAL_CACHE:
      case NETWORK:
        networkCount++;
        break;
    }
  }

  private synchronized void trackConditionalCacheHit() {
    hitCount++;
  }

  public synchronized int getNetworkCount() {
    return networkCount;
  }

  public synchronized int getHitCount() {
    return hitCount;
  }

  public synchronized int getRequestCount() {
    return requestCount;
  }

  private final class CacheRequestImpl extends CacheRequest {
    private final DiskLruCache.Editor editor;
    private OutputStream cacheOut;
    private boolean done;
    private OutputStream body;

    public CacheRequestImpl(final DiskLruCache.Editor editor) throws IOException {
      this.editor = editor;
      this.cacheOut = editor.newOutputStream(ENTRY_BODY);
      this.body = new FilterOutputStream(cacheOut) {
        @Override public void close() throws IOException {
          synchronized (HttpResponseCache.this) {
            if (done) {
              return;
            }
            done = true;
            writeSuccessCount++;
          }
          super.close();
          editor.commit();
        }

        @Override public void write(byte[] buffer, int offset, int length) throws IOException {
          // Since we don't override "write(int oneByte)", we can write directly to "out"
          // and avoid the inefficient implementation from the FilterOutputStream.
          out.write(buffer, offset, length);
        }
      };
    }

    @Override public void abort() {
      synchronized (HttpResponseCache.this) {
        if (done) {
          return;
        }
        done = true;
        writeAbortCount++;
      }
      Util.closeQuietly(cacheOut);
      try {
        editor.abort();
      } catch (IOException ignored) {
      }
    }

    @Override public OutputStream getBody() throws IOException {
      return body;
    }
  }

  private static final class Entry {
    private final String uri;
    private final RawHeaders varyHeaders;
    private final String requestMethod;
    private final RawHeaders responseHeaders;
    private final String cipherSuite;
    private final Certificate[] peerCertificates;
    private final Certificate[] localCertificates;

    /**
     * Reads an entry from an input stream. A typical entry looks like this:
     * <pre>{@code
     *   http://google.com/foo
     *   GET
     *   2
     *   Accept-Language: fr-CA
     *   Accept-Charset: UTF-8
     *   HTTP/1.1 200 OK
     *   3
     *   Content-Type: image/png
     *   Content-Length: 100
     *   Cache-Control: max-age=600
     * }</pre>
     *
     * <p>A typical HTTPS file looks like this:
     * <pre>{@code
     *   https://google.com/foo
     *   GET
     *   2
     *   Accept-Language: fr-CA
     *   Accept-Charset: UTF-8
     *   HTTP/1.1 200 OK
     *   3
     *   Content-Type: image/png
     *   Content-Length: 100
     *   Cache-Control: max-age=600
     *
     *   AES_256_WITH_MD5
     *   2
     *   base64-encoded peerCertificate[0]
     *   base64-encoded peerCertificate[1]
     *   -1
     * }</pre>
     * The file is newline separated. The first two lines are the URL and
     * the request method. Next is the number of HTTP Vary request header
     * lines, followed by those lines.
     *
     * <p>Next is the response status line, followed by the number of HTTP
     * response header lines, followed by those lines.
     *
     * <p>HTTPS responses also contain SSL session information. This begins
     * with a blank line, and then a line containing the cipher suite. Next
     * is the length of the peer certificate chain. These certificates are
     * base64-encoded and appear each on their own line. The next line
     * contains the length of the local certificate chain. These
     * certificates are also base64-encoded and appear each on their own
     * line. A length of -1 is used to encode a null array.
     */
    public Entry(InputStream in) throws IOException {
      try {
        StrictLineReader reader = new StrictLineReader(in, US_ASCII);
        uri = reader.readLine();
        requestMethod = reader.readLine();
        varyHeaders = new RawHeaders();
        int varyRequestHeaderLineCount = reader.readInt();
        for (int i = 0; i < varyRequestHeaderLineCount; i++) {
          varyHeaders.addLine(reader.readLine());
        }

        responseHeaders = new RawHeaders();
        responseHeaders.setStatusLine(reader.readLine());
        int responseHeaderLineCount = reader.readInt();
        for (int i = 0; i < responseHeaderLineCount; i++) {
          responseHeaders.addLine(reader.readLine());
        }

        if (isHttps()) {
          String blank = reader.readLine();
          if (blank.length() > 0) {
            throw new IOException("expected \"\" but was \"" + blank + "\"");
          }
          cipherSuite = reader.readLine();
          peerCertificates = readCertArray(reader);
          localCertificates = readCertArray(reader);
        } else {
          cipherSuite = null;
          peerCertificates = null;
          localCertificates = null;
        }
      } finally {
        in.close();
      }
    }

    public Entry(URI uri, RawHeaders varyHeaders, HttpURLConnection httpConnection)
        throws IOException {
      this.uri = uri.toString();
      this.varyHeaders = varyHeaders;
      this.requestMethod = httpConnection.getRequestMethod();
      this.responseHeaders = RawHeaders.fromMultimap(httpConnection.getHeaderFields(), true);

      SSLSocket sslSocket = getSslSocket(httpConnection);
      if (sslSocket != null) {
        cipherSuite = sslSocket.getSession().getCipherSuite();
        Certificate[] peerCertificatesNonFinal = null;
        try {
          peerCertificatesNonFinal = sslSocket.getSession().getPeerCertificates();
        } catch (SSLPeerUnverifiedException ignored) {
        }
        peerCertificates = peerCertificatesNonFinal;
        localCertificates = sslSocket.getSession().getLocalCertificates();
      } else {
        cipherSuite = null;
        peerCertificates = null;
        localCertificates = null;
      }
    }

    /**
     * Returns the SSL socket used by {@code httpConnection} for HTTPS, nor null
     * if the connection isn't using HTTPS. Since we permit redirects across
     * protocols (HTTP to HTTPS or vice versa), the implementation type of the
     * connection doesn't necessarily match the implementation type of its HTTP
     * engine.
     */
    private SSLSocket getSslSocket(HttpURLConnection httpConnection) {
      HttpEngine engine = httpConnection instanceof HttpsURLConnectionImpl
          ? ((HttpsURLConnectionImpl) httpConnection).getHttpEngine()
          : ((HttpURLConnectionImpl) httpConnection).getHttpEngine();
      return engine instanceof HttpsEngine
          ? ((HttpsEngine) engine).getSslSocket()
          : null;
    }

    public void writeTo(DiskLruCache.Editor editor) throws IOException {
      OutputStream out = editor.newOutputStream(ENTRY_METADATA);
      Writer writer = new BufferedWriter(new OutputStreamWriter(out, UTF_8));

      writer.write(uri + '\n');
      writer.write(requestMethod + '\n');
      writer.write(Integer.toString(varyHeaders.length()) + '\n');
      for (int i = 0; i < varyHeaders.length(); i++) {
        writer.write(varyHeaders.getFieldName(i) + ": " + varyHeaders.getValue(i) + '\n');
      }

      writer.write(responseHeaders.getStatusLine() + '\n');
      writer.write(Integer.toString(responseHeaders.length()) + '\n');
      for (int i = 0; i < responseHeaders.length(); i++) {
        writer.write(responseHeaders.getFieldName(i) + ": " + responseHeaders.getValue(i) + '\n');
      }

      if (isHttps()) {
        writer.write('\n');
        writer.write(cipherSuite + '\n');
        writeCertArray(writer, peerCertificates);
        writeCertArray(writer, localCertificates);
      }
      writer.close();
    }

    private boolean isHttps() {
      return uri.startsWith("https://");
    }

    private Certificate[] readCertArray(StrictLineReader reader) throws IOException {
      int length = reader.readInt();
      if (length == -1) {
        return null;
      }
      try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate[] result = new Certificate[length];
        for (int i = 0; i < result.length; i++) {
          String line = reader.readLine();
          byte[] bytes = Base64.decode(line.getBytes("US-ASCII"));
          result[i] = certificateFactory.generateCertificate(new ByteArrayInputStream(bytes));
        }
        return result;
      } catch (CertificateException e) {
        throw new IOException(e.getMessage());
      }
    }

    private void writeCertArray(Writer writer, Certificate[] certificates) throws IOException {
      if (certificates == null) {
        writer.write("-1\n");
        return;
      }
      try {
        writer.write(Integer.toString(certificates.length) + '\n');
        for (Certificate certificate : certificates) {
          byte[] bytes = certificate.getEncoded();
          String line = Base64.encode(bytes);
          writer.write(line + '\n');
        }
      } catch (CertificateEncodingException e) {
        throw new IOException(e.getMessage());
      }
    }

    public boolean matches(URI uri, String requestMethod,
        Map<String, List<String>> requestHeaders) {
      return this.uri.equals(uri.toString())
          && this.requestMethod.equals(requestMethod)
          && new ResponseHeaders(uri, responseHeaders).varyMatches(varyHeaders.toMultimap(false),
          requestHeaders);
    }
  }

  /**
   * Returns an input stream that reads the body of a snapshot, closing the
   * snapshot when the stream is closed.
   */
  private static InputStream newBodyInputStream(final DiskLruCache.Snapshot snapshot) {
    return new FilterInputStream(snapshot.getInputStream(ENTRY_BODY)) {
      @Override public void close() throws IOException {
        snapshot.close();
        super.close();
      }
    };
  }

  static class EntryCacheResponse extends CacheResponse {
    private final Entry entry;
    private final DiskLruCache.Snapshot snapshot;
    private final InputStream in;

    public EntryCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
      this.entry = entry;
      this.snapshot = snapshot;
      this.in = newBodyInputStream(snapshot);
    }

    @Override public Map<String, List<String>> getHeaders() {
      return entry.responseHeaders.toMultimap(true);
    }

    @Override public InputStream getBody() {
      return in;
    }
  }

  static class EntrySecureCacheResponse extends SecureCacheResponse {
    private final Entry entry;
    private final DiskLruCache.Snapshot snapshot;
    private final InputStream in;

    public EntrySecureCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
      this.entry = entry;
      this.snapshot = snapshot;
      this.in = newBodyInputStream(snapshot);
    }

    @Override public Map<String, List<String>> getHeaders() {
      return entry.responseHeaders.toMultimap(true);
    }

    @Override public InputStream getBody() {
      return in;
    }

    @Override public String getCipherSuite() {
      return entry.cipherSuite;
    }

    @Override public List<Certificate> getServerCertificateChain()
        throws SSLPeerUnverifiedException {
      if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
        throw new SSLPeerUnverifiedException(null);
      }
      return Arrays.asList(entry.peerCertificates.clone());
    }

    @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
      if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
        throw new SSLPeerUnverifiedException(null);
      }
      return ((X509Certificate) entry.peerCertificates[0]).getSubjectX500Principal();
    }

    @Override public List<Certificate> getLocalCertificateChain() {
      if (entry.localCertificates == null || entry.localCertificates.length == 0) {
        return null;
      }
      return Arrays.asList(entry.localCertificates.clone());
    }

    @Override public Principal getLocalPrincipal() {
      if (entry.localCertificates == null || entry.localCertificates.length == 0) {
        return null;
      }
      return ((X509Certificate) entry.localCertificates[0]).getSubjectX500Principal();
    }
  }
}




Java Source Code List

com.phonegap.plugins.barcodescanner.BarcodeScanner.java
com.squareup.okhttp.Address.java
com.squareup.okhttp.ConnectionPool.java
com.squareup.okhttp.Connection.java
com.squareup.okhttp.Dispatcher.java
com.squareup.okhttp.Failure.java
com.squareup.okhttp.HttpResponseCache.java
com.squareup.okhttp.Job.java
com.squareup.okhttp.MediaType.java
com.squareup.okhttp.OkAuthenticator.java
com.squareup.okhttp.OkHttpClient.java
com.squareup.okhttp.OkResponseCache.java
com.squareup.okhttp.Request.java
com.squareup.okhttp.ResponseSource.java
com.squareup.okhttp.Response.java
com.squareup.okhttp.RouteDatabase.java
com.squareup.okhttp.Route.java
com.squareup.okhttp.TunnelRequest.java
com.squareup.okhttp.internal.AbstractOutputStream.java
com.squareup.okhttp.internal.Base64.java
com.squareup.okhttp.internal.DiskLruCache.java
com.squareup.okhttp.internal.Dns.java
com.squareup.okhttp.internal.FaultRecoveringOutputStream.java
com.squareup.okhttp.internal.NamedRunnable.java
com.squareup.okhttp.internal.Platform.java
com.squareup.okhttp.internal.StrictLineReader.java
com.squareup.okhttp.internal.Util.java
com.squareup.okhttp.internal.http.AbstractHttpInputStream.java
com.squareup.okhttp.internal.http.HeaderParser.java
com.squareup.okhttp.internal.http.HttpAuthenticator.java
com.squareup.okhttp.internal.http.HttpDate.java
com.squareup.okhttp.internal.http.HttpEngine.java
com.squareup.okhttp.internal.http.HttpTransport.java
com.squareup.okhttp.internal.http.HttpURLConnectionImpl.java
com.squareup.okhttp.internal.http.HttpsEngine.java
com.squareup.okhttp.internal.http.HttpsURLConnectionImpl.java
com.squareup.okhttp.internal.http.OkResponseCacheAdapter.java
com.squareup.okhttp.internal.http.Policy.java
com.squareup.okhttp.internal.http.RawHeaders.java
com.squareup.okhttp.internal.http.RequestHeaders.java
com.squareup.okhttp.internal.http.ResponseHeaders.java
com.squareup.okhttp.internal.http.RetryableOutputStream.java
com.squareup.okhttp.internal.http.RouteSelector.java
com.squareup.okhttp.internal.http.SpdyTransport.java
com.squareup.okhttp.internal.http.Transport.java
com.squareup.okhttp.internal.http.UnknownLengthHttpInputStream.java
com.squareup.okhttp.internal.spdy.ErrorCode.java
com.squareup.okhttp.internal.spdy.FrameReader.java
com.squareup.okhttp.internal.spdy.FrameWriter.java
com.squareup.okhttp.internal.spdy.HeadersMode.java
com.squareup.okhttp.internal.spdy.Hpack.java
com.squareup.okhttp.internal.spdy.Http20Draft06.java
com.squareup.okhttp.internal.spdy.IncomingStreamHandler.java
com.squareup.okhttp.internal.spdy.NameValueBlockReader.java
com.squareup.okhttp.internal.spdy.Ping.java
com.squareup.okhttp.internal.spdy.Settings.java
com.squareup.okhttp.internal.spdy.Spdy3.java
com.squareup.okhttp.internal.spdy.SpdyConnection.java
com.squareup.okhttp.internal.spdy.SpdyStream.java
com.squareup.okhttp.internal.spdy.Variant.java
com.squareup.okhttp.internal.tls.DistinguishedNameParser.java
com.squareup.okhttp.internal.tls.OkHostnameVerifier.java
org.apache.cordova.App.java
org.apache.cordova.AuthenticationToken.java
org.apache.cordova.CallbackContext.java
org.apache.cordova.ConfigXmlParser.java
org.apache.cordova.Config.java
org.apache.cordova.CordovaActivity.java
org.apache.cordova.CordovaArgs.java
org.apache.cordova.CordovaBridge.java
org.apache.cordova.CordovaChromeClient.java
org.apache.cordova.CordovaInterface.java
org.apache.cordova.CordovaPlugin.java
org.apache.cordova.CordovaPreferences.java
org.apache.cordova.CordovaResourceApi.java
org.apache.cordova.CordovaUriHelper.java
org.apache.cordova.CordovaWebViewClient.java
org.apache.cordova.CordovaWebView.java
org.apache.cordova.DirectoryManager.java
org.apache.cordova.DroidGap.java
org.apache.cordova.ExifHelper.java
org.apache.cordova.ExposedJsApi.java
org.apache.cordova.FileHelper.java
org.apache.cordova.IceCreamCordovaWebViewClient.java
org.apache.cordova.JSONUtils.java
org.apache.cordova.LOG.java
org.apache.cordova.LinearLayoutSoftKeyboardDetect.java
org.apache.cordova.NativeToJsMessageQueue.java
org.apache.cordova.PluginEntry.java
org.apache.cordova.PluginManager.java
org.apache.cordova.PluginResult.java
org.apache.cordova.ScrollEvent.java
org.apache.cordova.Whitelist.java
org.opensharingtoolkit.cordova.aestheticodes.Scan.java
org.opensharingtoolkit.cordova.aestheticodes.Scan.java
org.opensharingtoolkit.player.CordovaApp.java