1a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom/*
2a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Copyright (C) 2011 The Android Open Source Project
3a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
4a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * you may not use this file except in compliance with the License.
6a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * You may obtain a copy of the License at
7a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
8a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
10a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
11a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * See the License for the specific language governing permissions and
14a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * limitations under the License.
15a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom */
16a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
17a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrompackage android.net.http;
18a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
19a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport android.content.Context;
20a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.io.Closeable;
21a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.io.File;
22a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.io.IOException;
23a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.CacheRequest;
24a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.CacheResponse;
25a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.HttpURLConnection;
26a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.ResponseCache;
27a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.URI;
28a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.net.URLConnection;
29a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.util.List;
30a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport java.util.Map;
31a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport javax.net.ssl.HttpsURLConnection;
32a7284f0e72745d66155e1e282fc07113332790faBrian Carlstromimport org.apache.http.impl.client.DefaultHttpClient;
33a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
34a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom/**
35a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Caches HTTP and HTTPS responses to the filesystem so they may be reused,
36a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * saving time and bandwidth. This class supports {@link HttpURLConnection} and
37a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * {@link HttpsURLConnection}; there is no platform-provided cache for {@link
38a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * DefaultHttpClient} or {@link AndroidHttpClient}.
39a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
40a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <h3>Installing an HTTP response cache</h3>
41a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Enable caching of all of your application's HTTP requests by installing the
42a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * cache at application startup. For example, this code installs a 10 MiB cache
43a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * in the {@link Context#getCacheDir() application-specific cache directory} of
44a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * the filesystem}: <pre>   {@code
45a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *   protected void onCreate(Bundle savedInstanceState) {
46a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       ...
47a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
48a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       try {
49a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *           File httpCacheDir = new File(context.getCacheDir(), "http");
50a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *           long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
51a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *           HttpResponseCache.install(httpCacheDir, httpCacheSize);
52a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       } catch (IOException e) {
53a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *           Log.i(TAG, "HTTP response cache installation failed:" + e);
54a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       }
55a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *   }
56a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
57a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *   protected void onStop() {
58a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       ...
59a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
60a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       HttpResponseCache cache = HttpResponseCache.getInstalled();
61a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       if (cache != null) {
62a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *           cache.flush();
63a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *       }
64a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *   }}</pre>
65a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * This cache will evict entries as necessary to keep its size from exceeding
66a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * 10 MiB. The best cache size is application specific and depends on the size
67a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * and frequency of the files being downloaded. Increasing the limit may improve
68a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * the hit rate, but it may also just waste filesystem space!
69a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
70a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <p>For some applications it may be preferable to create the cache in the
7198e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * external storage directory. <strong>There are no access controls on the
7298e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * external storage directory so it should not be used for caches that could
7398e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * contain private data.</strong> Although it often has more free space,
7498e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * external storage is optional and&#8212;even if available&#8212;can disappear
7598e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * during use. Retrieve the external cache directory using {@link
7698e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * Context#getExternalCacheDir()}. If this method returns null, your application
7798e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * should fall back to either not caching or caching on non-external storage. If
7898e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * the external storage is removed during use, the cache hit rate will drop to
7998e8b19c7bc422600a7a27819311d0059b5af2daJesse Wilson * zero and ongoing cache reads will fail.
80a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
81a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <p>Flushing the cache forces its data to the filesystem. This ensures that
82a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * all responses written to the cache will be readable the next time the
83a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * activity starts.
84a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
85a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <h3>Cache Optimization</h3>
86a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * To measure cache effectiveness, this class tracks three statistics:
87a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <ul>
88a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     <li><strong>{@link #getRequestCount() Request Count:}</strong> the number
89a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         of HTTP requests issued since this cache was created.
90a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     <li><strong>{@link #getNetworkCount() Network Count:}</strong> the
91a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         number of those requests that required network use.
92a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     <li><strong>{@link #getHitCount() Hit Count:}</strong> the number of
93a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         those requests whose responses were served by the cache.
94a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * </ul>
95a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Sometimes a request will result in a conditional cache hit. If the cache
96a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * contains a stale copy of the response, the client will issue a conditional
97a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * {@code GET}. The server will then send either the updated response if it has
98a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * changed, or a short 'not modified' response if the client's copy is still
99a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * valid. Such responses increment both the network count and hit count.
100a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
101a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <p>The best way to improve the cache hit rate is by configuring the web
102a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * server to return cacheable responses. Although this client honors all <a
103a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * href="http://www.ietf.org/rfc/rfc2616.txt">HTTP/1.1 (RFC 2068)</a> cache
104a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * headers, it doesn't cache partial responses.
105a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
106a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <h3>Force a Network Response</h3>
107a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * In some situations, such as after a user clicks a 'refresh' button, it may be
108a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * necessary to skip the cache, and fetch data directly from the server. To force
109a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * a full refresh, add the {@code no-cache} directive: <pre>   {@code
110a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         connection.addRequestProperty("Cache-Control", "no-cache");
111a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * }</pre>
112a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * If it is only necessary to force a cached response to be validated by the
113a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * server, use the more efficient {@code max-age=0} instead: <pre>   {@code
114a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         connection.addRequestProperty("Cache-Control", "max-age=0");
115a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * }</pre>
116a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *
117a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <h3>Force a Cache Response</h3>
118a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * Sometimes you'll want to show resources if they are available immediately,
119a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * but not otherwise. This can be used so your application can show
120a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * <i>something</i> while waiting for the latest data to be downloaded. To
121a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * restrict a request to locally-cached resources, add the {@code
122a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * only-if-cached} directive: <pre>   {@code
123a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     try {
124a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         connection.addRequestProperty("Cache-Control", "only-if-cached");
125a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         InputStream cached = connection.getInputStream();
126a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         // the resource was cached! show it
127a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     } catch (FileNotFoundException e) {
128a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         // the resource was not cached
129a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *     }
130a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * }</pre>
131a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * This technique works even better in situations where a stale response is
132a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * better than no response. To permit stale cached responses, use the {@code
133a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * max-stale} directive with the maximum staleness in seconds: <pre>   {@code
134a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
135a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom *         connection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);
136a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom * }</pre>
1378543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *
1388543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson * <h3>Working With Earlier Releases</h3>
1398543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson * This class was added in Android 4.0 (Ice Cream Sandwich). Use reflection to
1408543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson * enable the response cache without impacting earlier releases: <pre>   {@code
1418543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *       try {
1428543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *           File httpCacheDir = new File(context.getCacheDir(), "http");
1438543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *           long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
1448543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *           Class.forName("android.net.http.HttpResponseCache")
1458543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *                   .getMethod("install", File.class, long.class)
1468543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *                   .invoke(null, httpCacheDir, httpCacheSize);
1478543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *       } catch (Exception httpResponseCacheNotAvailable) {
1488543b5480d9c261e72965f64a7bc918eb183ea25Jesse Wilson *       }}</pre>
149a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom */
15068a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamathpublic final class HttpResponseCache extends ResponseCache implements Closeable {
151a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
15268a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath    private final com.android.okhttp.HttpResponseCache delegate;
153a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
15468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath    private HttpResponseCache(com.android.okhttp.HttpResponseCache delegate) {
15568a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        this.delegate = delegate;
156a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
157a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
158a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
159a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the currently-installed {@code HttpResponseCache}, or null if
160a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * there is no cache installed or it is not a {@code HttpResponseCache}.
161a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
162a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public static HttpResponseCache getInstalled() {
163a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        ResponseCache installed = ResponseCache.getDefault();
16468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        if (installed instanceof com.android.okhttp.HttpResponseCache) {
16568a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath            return new HttpResponseCache(
16668a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                    (com.android.okhttp.HttpResponseCache) installed);
16768a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        }
16868a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath
16968a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        return null;
170a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
171a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
172a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
173a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Creates a new HTTP response cache and {@link ResponseCache#setDefault
174a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * sets it} as the system default cache.
175a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     *
176a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * @param directory the directory to hold cache data.
177a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * @param maxSize the maximum size of the cache in bytes.
178a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * @return the newly-installed cache
179a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * @throws IOException if {@code directory} cannot be used for this cache.
180a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     *     Most applications should respond to this exception by logging a
181a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     *     warning.
182a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
183a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public static HttpResponseCache install(File directory, long maxSize) throws IOException {
18468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        ResponseCache installed = ResponseCache.getDefault();
18568a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        if (installed instanceof com.android.okhttp.HttpResponseCache) {
18668a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath            com.android.okhttp.HttpResponseCache installedCache =
18768a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                    (com.android.okhttp.HttpResponseCache) installed;
188a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            // don't close and reopen if an equivalent cache is already installed
189a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            if (installedCache.getDirectory().equals(directory)
19068a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                    && installedCache.getMaxSize() == maxSize
191a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom                    && !installedCache.isClosed()) {
19268a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                return new HttpResponseCache(installedCache);
193a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            } else {
19468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                // The HttpResponseCache that owns this object is about to be replaced.
19568a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                installedCache.close();
196a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            }
197a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        }
198a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
19968a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        com.android.okhttp.HttpResponseCache responseCache =
20068a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath                new com.android.okhttp.HttpResponseCache(directory, maxSize);
20168a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        ResponseCache.setDefault(responseCache);
20268a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        return new HttpResponseCache(responseCache);
203a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
204a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
205a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    @Override public CacheResponse get(URI uri, String requestMethod,
206a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            Map<String, List<String>> requestHeaders) throws IOException {
207a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        return delegate.get(uri, requestMethod, requestHeaders);
208a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
209a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
210a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
211a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        return delegate.put(uri, urlConnection);
212a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
213a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
214a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
215a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the number of bytes currently being used to store the values in
216a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * this cache. This may be greater than the {@link #maxSize} if a background
217a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * deletion is pending.
218a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
219a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public long size() {
22068a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        return delegate.getSize();
221a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
222a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
223a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
224a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the maximum number of bytes that this cache should use to store
225a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * its data.
226a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
227a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public long maxSize() {
22868a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        return delegate.getMaxSize();
229a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
230a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
231a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
232a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Force buffered operations to the filesystem. This ensures that responses
233a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * written to the cache will be available the next time the cache is opened,
234a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * even if this process is killed.
235a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
236a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public void flush() {
237a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        try {
23868a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath            delegate.flush();
239a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        } catch (IOException ignored) {
240a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        }
241a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
242a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
243a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
244a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the number of HTTP requests that required the network to either
245a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * supply a response or validate a locally cached response.
246a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
247a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public int getNetworkCount() {
248a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        return delegate.getNetworkCount();
249a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
250a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
251a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
252a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the number of HTTP requests whose response was provided by the
253a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * cache. This may include conditional {@code GET} requests that were
254a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * validated over the network.
255a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
256a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public int getHitCount() {
257a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        return delegate.getHitCount();
258a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
259a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
260a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
261a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Returns the total number of HTTP requests that were made. This includes
262a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * both client requests and requests that were made on the client's behalf
263a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * to handle a redirects and retries.
264a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
265a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public int getRequestCount() {
266a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        return delegate.getRequestCount();
267a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
268a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
269a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
270a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Uninstalls the cache and releases any active resources. Stored contents
271a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * will remain on the filesystem.
272a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
273a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    @Override public void close() throws IOException {
27468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        if (ResponseCache.getDefault() == this.delegate) {
275a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            ResponseCache.setDefault(null);
276a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        }
27768a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        delegate.close();
278a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
279a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom
280a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    /**
281a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     * Uninstalls the cache and deletes all of its stored contents.
282a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom     */
283a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    public void delete() throws IOException {
28468a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        if (ResponseCache.getDefault() == this.delegate) {
285a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom            ResponseCache.setDefault(null);
286a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom        }
28768a3cd7955479d3f77fe3facd20c5ded7dafc68eNarayan Kamath        delegate.delete();
288a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom    }
289a7284f0e72745d66155e1e282fc07113332790faBrian Carlstrom}
290