OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / support / src / test / java / tests / http / DefaultResponseCache.java
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package tests.http;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.net.CacheRequest;
25 import java.net.CacheResponse;
26 import java.net.ResponseCache;
27 import java.net.URI;
28 import java.net.URLConnection;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34
35 /**
36  * Cache all responses in memory by URI.
37  */
38 public final class DefaultResponseCache extends ResponseCache {
39     private final Map<URI, Entry> entries = new HashMap<URI, Entry>();
40     private int abortCount;
41     private int successCount;
42     private int hitCount;
43     private int missCount;
44
45     @Override public synchronized CacheResponse get(URI uri, String requestMethod,
46             Map<String, List<String>> requestHeaders) throws IOException {
47         // TODO: honor the request headers in the cache key
48         Entry entry = entries.get(uri);
49         if (entry != null) {
50             hitCount++;
51             return entry.asResponse();
52         } else {
53             missCount++;
54             return null;
55         }
56     }
57
58     @Override public CacheRequest put(URI uri, URLConnection urlConnection)
59             throws IOException {
60         // TODO: honor the response headers for cache invalidation
61         return new Entry(uri, urlConnection).asRequest();
62     }
63
64     public synchronized Map<URI, Entry> getContents() {
65         return new HashMap<URI, Entry>(entries);
66     }
67
68     /**
69      * Returns the number of requests that were aborted before they were closed.
70      */
71     public synchronized int getAbortCount() {
72         return abortCount;
73     }
74
75     /**
76      * Returns the number of requests that were closed successfully.
77      */
78     public synchronized int getSuccessCount() {
79         return successCount;
80     }
81
82     /**
83      * Returns the number of responses served by the cache.
84      */
85     public synchronized int getHitCount() {
86         return hitCount;
87     }
88
89     /**
90      * Returns the number of responses that couldn't be served by the cache.
91      */
92     public synchronized int getMissCount() {
93         return missCount;
94     }
95
96     public final class Entry {
97         private final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream() {
98             private boolean closed;
99             @Override public void close() throws IOException {
100                 synchronized (DefaultResponseCache.this) {
101                     if (closed) {
102                         return;
103                     }
104
105                     super.close();
106                     entries.put(uri, Entry.this);
107                     successCount++;
108                     closed = true;
109                 }
110             }
111         };
112         private final Map<String, List<String>> headers;
113         private final URI uri;
114
115         private Entry(URI uri, URLConnection conn) {
116             this.uri = uri;
117             this.headers = deepCopy(conn.getHeaderFields());
118         }
119
120         public CacheRequest asRequest() {
121             return new CacheRequest() {
122                 private boolean aborted;
123                 @Override public void abort() {
124                     synchronized (DefaultResponseCache.this) {
125                         if (aborted) {
126                             return;
127                         }
128
129                         abortCount++;
130                         aborted = true;
131                     }
132                 }
133                 @Override public OutputStream getBody() throws IOException {
134                     return bytesOut;
135                 }
136             };
137         }
138
139         public CacheResponse asResponse() {
140             return new CacheResponse() {
141                 @Override public InputStream getBody() throws IOException {
142                     return new ByteArrayInputStream(getBytes());
143                 }
144                 @Override public Map<String, List<String>> getHeaders() throws IOException {
145                     return deepCopy(headers);
146                 }
147             };
148         }
149
150         public byte[] getBytes() {
151             return bytesOut.toByteArray();
152         }
153     }
154
155     private static Map<String, List<String>> deepCopy(Map<String, List<String>> input) {
156         Map<String, List<String>> result = new LinkedHashMap<String, List<String>>(input);
157         for (Map.Entry<String, List<String>> entry : result.entrySet()) {
158             entry.setValue(new ArrayList<String>(entry.getValue()));
159         }
160         return result;
161     }
162 }