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