1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/*
2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2011 The Android Open Source Project
3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License.
6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at
7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software
11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and
14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License.
15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage com.squareup.okhttp.android;
18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.Cache;
20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.AndroidShimResponseCache;
21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.OkCacheContainer;
22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.Closeable;
24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.File;
25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException;
26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.CacheRequest;
27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.CacheResponse;
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.ResponseCache;
29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.URI;
30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.URLConnection;
31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.List;
32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Map;
33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/**
35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * A copy of android.net.http.HttpResponseCache taken from AOSP. Android need to keep this code
36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * working somehow. Dependencies on com.squareup.okhttp are com.android.okhttp on Android.
37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/* <p>This class exists in okhttp-android-support to help keep the API as it always has been on
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Android. The public API cannot be changed. This class delegates to
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * {@link com.squareup.okhttp.AndroidShimResponseCache}, a class that exists in a package that
41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * enables it to interact with non-public OkHttp classes.
42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic final class HttpResponseCache extends ResponseCache implements Closeable, OkCacheContainer {
44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private AndroidShimResponseCache shimResponseCache;
46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private HttpResponseCache(AndroidShimResponseCache shimResponseCache) {
48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    this.shimResponseCache = shimResponseCache;
49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the currently-installed {@code HttpResponseCache}, or null if
53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * there is no cache installed or it is not a {@code HttpResponseCache}.
54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static HttpResponseCache getInstalled() {
56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    ResponseCache installed = ResponseCache.getDefault();
57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (installed instanceof HttpResponseCache) {
58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return (HttpResponseCache) installed;
59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return null;
61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Creates a new HTTP response cache and sets it as the system default cache.
65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *
66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * @param directory the directory to hold cache data.
67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * @param maxSize the maximum size of the cache in bytes.
68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * @return the newly-installed cache
69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * @throws java.io.IOException if {@code directory} cannot be used for this cache.
70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *     Most applications should respond to this exception by logging a
71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *     warning.
72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static synchronized HttpResponseCache install(File directory, long maxSize) throws
74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      IOException {
75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    ResponseCache installed = ResponseCache.getDefault();
76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (installed instanceof HttpResponseCache) {
78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      HttpResponseCache installedResponseCache = (HttpResponseCache) installed;
79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      // don't close and reopen if an equivalent cache is already installed
80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      AndroidShimResponseCache trueResponseCache = installedResponseCache.shimResponseCache;
81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (trueResponseCache.isEquivalent(directory, maxSize)) {
82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        return installedResponseCache;
83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      } else {
84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        // The HttpResponseCache that owns this object is about to be replaced.
85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        trueResponseCache.close();
86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AndroidShimResponseCache trueResponseCache =
90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        AndroidShimResponseCache.create(directory, maxSize);
91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    HttpResponseCache newResponseCache = new HttpResponseCache(trueResponseCache);
92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    ResponseCache.setDefault(newResponseCache);
93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return newResponseCache;
94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public CacheResponse get(URI uri, String requestMethod,
97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      Map<String, List<String>> requestHeaders) throws IOException {
98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.get(uri, requestMethod, requestHeaders);
99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.put(uri, urlConnection);
103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the number of bytes currently being used to store the values in
107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * this cache. This may be greater than the {@link #maxSize} if a background
108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * deletion is pending.
109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public long size() {
111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return shimResponseCache.size();
113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (IOException e) {
114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      // This can occur if the cache failed to lazily initialize. Return -1 to mean "unknown".
115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return -1;
116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the maximum number of bytes that this cache should use to store
121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * its data.
122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public long maxSize() {
124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.maxSize();
125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Force buffered operations to the filesystem. This ensures that responses
129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * written to the cache will be available the next time the cache is opened,
130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * even if this process is killed.
131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public void flush() {
133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      shimResponseCache.flush();
135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (IOException ignored) {
136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the number of HTTP requests that required the network to either
141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * supply a response or validate a locally cached response.
142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public int getNetworkCount() {
144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.getNetworkCount();
145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the number of HTTP requests whose response was provided by the
149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * cache. This may include conditional {@code GET} requests that were
150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * validated over the network.
151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public int getHitCount() {
153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.getHitCount();
154e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
155e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
156e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
157e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the total number of HTTP requests that were made. This includes
158e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * both client requests and requests that were made on the client's behalf
159e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * to handle a redirects and retries.
160e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
161e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public int getRequestCount() {
162e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.getRequestCount();
163e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
164e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
165e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
166e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Uninstalls the cache and releases any active resources. Stored contents
167e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * will remain on the filesystem.
168e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
169e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public void close() throws IOException {
170e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (ResponseCache.getDefault() == this) {
171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      ResponseCache.setDefault(null);
172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    shimResponseCache.close();
174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
176e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Uninstalls the cache and deletes all of its stored contents.
178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public void delete() throws IOException {
180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (ResponseCache.getDefault() == this) {
181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      ResponseCache.setDefault(null);
182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    shimResponseCache.delete();
184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override
187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public Cache getCache() {
188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return shimResponseCache.getCache();
189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller}
192