1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.client.cache;
28
29 import java.io.Closeable;
30 import java.io.IOException;
31 import java.lang.ref.ReferenceQueue;
32 import java.util.HashSet;
33 import java.util.Set;
34 import java.util.concurrent.atomic.AtomicBoolean;
35
36 import org.apache.http.annotation.Contract;
37 import org.apache.http.annotation.ThreadingBehavior;
38 import org.apache.http.client.cache.HttpCacheEntry;
39 import org.apache.http.client.cache.HttpCacheStorage;
40 import org.apache.http.client.cache.HttpCacheUpdateCallback;
41 import org.apache.http.client.cache.Resource;
42 import org.apache.http.util.Args;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 @Contract(threading = ThreadingBehavior.SAFE)
75 public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable {
76
77 private final CacheMap entries;
78 private final ReferenceQueue<HttpCacheEntry> morque;
79 private final Set<ResourceReference> resources;
80 private final AtomicBoolean active;
81
82 public ManagedHttpCacheStorage(final CacheConfig config) {
83 super();
84 this.entries = new CacheMap(config.getMaxCacheEntries());
85 this.morque = new ReferenceQueue<HttpCacheEntry>();
86 this.resources = new HashSet<ResourceReference>();
87 this.active = new AtomicBoolean(true);
88 }
89
90 private void ensureValidState() throws IllegalStateException {
91 if (!this.active.get()) {
92 throw new IllegalStateException("Cache has been shut down");
93 }
94 }
95
96 private void keepResourceReference(final HttpCacheEntry entry) {
97 final Resource resource = entry.getResource();
98 if (resource != null) {
99
100 final ResourceReferenceche/ResourceReference.html#ResourceReference">ResourceReference ref = new ResourceReference(entry, this.morque);
101 this.resources.add(ref);
102 }
103 }
104
105 @Override
106 public void putEntry(final String url, final HttpCacheEntry entry) throws IOException {
107 Args.notNull(url, "URL");
108 Args.notNull(entry, "Cache entry");
109 ensureValidState();
110 synchronized (this) {
111 this.entries.put(url, entry);
112 keepResourceReference(entry);
113 }
114 }
115
116 @Override
117 public HttpCacheEntry getEntry(final String url) throws IOException {
118 Args.notNull(url, "URL");
119 ensureValidState();
120 synchronized (this) {
121 return this.entries.get(url);
122 }
123 }
124
125 @Override
126 public void removeEntry(final String url) throws IOException {
127 Args.notNull(url, "URL");
128 ensureValidState();
129 synchronized (this) {
130
131
132 this.entries.remove(url);
133 }
134 }
135
136 @Override
137 public void updateEntry(
138 final String url,
139 final HttpCacheUpdateCallback callback) throws IOException {
140 Args.notNull(url, "URL");
141 Args.notNull(callback, "Callback");
142 ensureValidState();
143 synchronized (this) {
144 final HttpCacheEntry existing = this.entries.get(url);
145 final HttpCacheEntry updated = callback.update(existing);
146 this.entries.put(url, updated);
147 if (existing != updated) {
148 keepResourceReference(updated);
149 }
150 }
151 }
152
153 public void cleanResources() {
154 if (this.active.get()) {
155 ResourceReference ref;
156 while ((ref = (ResourceReference) this.morque.poll()) != null) {
157 synchronized (this) {
158 this.resources.remove(ref);
159 }
160 ref.getResource().dispose();
161 }
162 }
163 }
164
165 public void shutdown() {
166 if (this.active.compareAndSet(true, false)) {
167 synchronized (this) {
168 this.entries.clear();
169 for (final ResourceReference ref: this.resources) {
170 ref.getResource().dispose();
171 }
172 this.resources.clear();
173 while (this.morque.poll() != null) {
174 }
175 }
176 }
177 }
178
179 @Override
180 public void close() {
181 if (this.active.compareAndSet(true, false)) {
182 synchronized (this) {
183 ResourceReference ref;
184 while ((ref = (ResourceReference) this.morque.poll()) != null) {
185 this.resources.remove(ref);
186 ref.getResource().dispose();
187 }
188 }
189 }
190 }
191
192 }