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.hc.client5.http.impl.cache;
28
29 import java.io.File;
30 import java.util.concurrent.ScheduledExecutorService;
31 import java.util.concurrent.ScheduledThreadPoolExecutor;
32 import java.util.function.Function;
33
34 import org.apache.hc.client5.http.async.AsyncExecChainHandler;
35 import org.apache.hc.client5.http.cache.HttpAsyncCacheStorage;
36 import org.apache.hc.client5.http.cache.HttpAsyncCacheStorageAdaptor;
37 import org.apache.hc.client5.http.cache.HttpCacheContext;
38 import org.apache.hc.client5.http.cache.HttpCacheEntryFactory;
39 import org.apache.hc.client5.http.cache.HttpCacheStorage;
40 import org.apache.hc.client5.http.cache.ResourceFactory;
41 import org.apache.hc.client5.http.impl.ChainElement;
42 import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
43 import org.apache.hc.client5.http.impl.schedule.ImmediateSchedulingStrategy;
44 import org.apache.hc.client5.http.protocol.HttpClientContext;
45 import org.apache.hc.client5.http.schedule.SchedulingStrategy;
46 import org.apache.hc.core5.http.config.NamedElementChain;
47 import org.apache.hc.core5.http.protocol.HttpContext;
48
49
50
51
52
53
54
55 public class CachingHttpAsyncClientBuilder extends HttpAsyncClientBuilder {
56
57 private ResourceFactory resourceFactory;
58 private HttpAsyncCacheStorage storage;
59 private File cacheDir;
60 private SchedulingStrategy schedulingStrategy;
61 private CacheConfig cacheConfig;
62 private boolean deleteCache;
63
64 public static CachingHttpAsyncClientBuilder create() {
65 return new CachingHttpAsyncClientBuilder();
66 }
67
68 protected CachingHttpAsyncClientBuilder() {
69 super();
70 addResponseInterceptorFirst(ResponseCacheConformance.INSTANCE);
71 addResponseInterceptorLast(ResponseViaCache.INSTANCE);
72 addRequestInterceptorLast(RequestViaCache.INSTANCE);
73 this.deleteCache = true;
74 }
75
76 public final CachingHttpAsyncClientBuilder setResourceFactory(final ResourceFactory resourceFactory) {
77 this.resourceFactory = resourceFactory;
78 return this;
79 }
80
81 public final CachingHttpAsyncClientBuilder setHttpCacheStorage(final HttpCacheStorage storage) {
82 this.storage = storage != null ? new HttpAsyncCacheStorageAdaptor(storage) : null;
83 return this;
84 }
85
86 public final CachingHttpAsyncClientBuilder setHttpCacheStorage(final HttpAsyncCacheStorage storage) {
87 this.storage = storage;
88 return this;
89 }
90
91 public final CachingHttpAsyncClientBuilder setCacheDir(final File cacheDir) {
92 this.cacheDir = cacheDir;
93 return this;
94 }
95
96 public final CachingHttpAsyncClientBuilder setSchedulingStrategy(final SchedulingStrategy schedulingStrategy) {
97 this.schedulingStrategy = schedulingStrategy;
98 return this;
99 }
100
101 public final CachingHttpAsyncClientBuilder setCacheConfig(final CacheConfig cacheConfig) {
102 this.cacheConfig = cacheConfig;
103 return this;
104 }
105
106
107
108
109 @Deprecated
110 public final CachingHttpAsyncClientBuilder setHttpCacheInvalidator(final org.apache.hc.client5.http.cache.HttpAsyncCacheInvalidator cacheInvalidator) {
111 return this;
112 }
113
114 public CachingHttpAsyncClientBuilder setDeleteCache(final boolean deleteCache) {
115 this.deleteCache = deleteCache;
116 return this;
117 }
118
119 @Override
120 protected void customizeExecChain(final NamedElementChain<AsyncExecChainHandler> execChainDefinition) {
121 final CacheConfig config = this.cacheConfig != null ? this.cacheConfig : CacheConfig.DEFAULT;
122
123 ResourceFactory resourceFactoryCopy = this.resourceFactory;
124 if (resourceFactoryCopy == null) {
125 if (this.cacheDir == null) {
126 resourceFactoryCopy = new HeapResourceFactory();
127 } else {
128 resourceFactoryCopy = new FileResourceFactory(cacheDir);
129 }
130 }
131 HttpAsyncCacheStorage storageCopy = this.storage;
132 if (storageCopy == null) {
133 if (this.cacheDir == null) {
134 storageCopy = new HttpAsyncCacheStorageAdaptor(new BasicHttpCacheStorage(config));
135 } else {
136 final ManagedHttpCacheStorage managedStorage = new ManagedHttpCacheStorage(config);
137 if (this.deleteCache) {
138 addCloseable(managedStorage::shutdown);
139 } else {
140 addCloseable(managedStorage);
141 }
142 storageCopy = new HttpAsyncCacheStorageAdaptor(managedStorage);
143 }
144 }
145 final HttpAsyncCache httpCache = new BasicHttpAsyncCache(
146 resourceFactoryCopy,
147 HttpCacheEntryFactory.INSTANCE,
148 storageCopy,
149 CacheKeyGenerator.INSTANCE);
150
151 DefaultAsyncCacheRevalidator cacheRevalidator = null;
152 if (config.getAsynchronousWorkers() > 0) {
153 final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(config.getAsynchronousWorkers());
154 addCloseable(executorService::shutdownNow);
155 cacheRevalidator = new DefaultAsyncCacheRevalidator(
156 executorService,
157 this.schedulingStrategy != null ? this.schedulingStrategy : ImmediateSchedulingStrategy.INSTANCE);
158 }
159
160 final AsyncCachingExec cachingExec = new AsyncCachingExec(
161 httpCache,
162 cacheRevalidator,
163 config);
164 execChainDefinition.addBefore(ChainElement.PROTOCOL.name(), cachingExec, ChainElement.CACHING.name());
165 }
166
167 @Override
168 protected Function<HttpContext, HttpClientContext> contextAdaptor() {
169 return HttpCacheContext::castOrCreate;
170 }
171
172 }