diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClientBuilder.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClientBuilder.java new file mode 100644 index 000000000..989126553 --- /dev/null +++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClientBuilder.java @@ -0,0 +1,144 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.http.impl.cache; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; + +import org.apache.hc.client5.http.async.AsyncExecChainHandler; +import org.apache.hc.client5.http.cache.HttpCacheInvalidator; +import org.apache.hc.client5.http.cache.HttpCacheStorage; +import org.apache.hc.client5.http.cache.ResourceFactory; +import org.apache.hc.client5.http.impl.ChainElements; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.core5.http.config.NamedElementChain; + +/** + * Builder for {@link org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient} + * instances capable of client-side caching. + * + * @since 5.0 + */ +public class CachingHttpAsyncClientBuilder extends HttpAsyncClientBuilder { + + private ResourceFactory resourceFactory; + private HttpCacheStorage storage; + private File cacheDir; + private CacheConfig cacheConfig; + private HttpCacheInvalidator httpCacheInvalidator; + private boolean deleteCache; + + public static CachingHttpAsyncClientBuilder create() { + return new CachingHttpAsyncClientBuilder(); + } + + protected CachingHttpAsyncClientBuilder() { + super(); + this.deleteCache = true; + } + + public final CachingHttpAsyncClientBuilder setResourceFactory( + final ResourceFactory resourceFactory) { + this.resourceFactory = resourceFactory; + return this; + } + + public final CachingHttpAsyncClientBuilder setHttpCacheStorage( + final HttpCacheStorage storage) { + this.storage = storage; + return this; + } + + public final CachingHttpAsyncClientBuilder setCacheDir( + final File cacheDir) { + this.cacheDir = cacheDir; + return this; + } + + public final CachingHttpAsyncClientBuilder setCacheConfig( + final CacheConfig cacheConfig) { + this.cacheConfig = cacheConfig; + return this; + } + + public final CachingHttpAsyncClientBuilder setHttpCacheInvalidator( + final HttpCacheInvalidator cacheInvalidator) { + this.httpCacheInvalidator = cacheInvalidator; + return this; + } + + public CachingHttpAsyncClientBuilder setDeleteCache(final boolean deleteCache) { + this.deleteCache = deleteCache; + return this; + } + + @Override + protected void customizeExecChain(final NamedElementChain execChainDefinition) { + final CacheConfig config = this.cacheConfig != null ? this.cacheConfig : CacheConfig.DEFAULT; + // We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong version + ResourceFactory resourceFactoryCopy = this.resourceFactory; + if (resourceFactoryCopy == null) { + if (this.cacheDir == null) { + resourceFactoryCopy = new HeapResourceFactory(); + } else { + resourceFactoryCopy = new FileResourceFactory(cacheDir); + } + } + HttpCacheStorage storageCopy = this.storage; + if (storageCopy == null) { + if (this.cacheDir == null) { + storageCopy = new BasicHttpCacheStorage(config); + } else { + final ManagedHttpCacheStorage managedStorage = new ManagedHttpCacheStorage(config); + if (this.deleteCache) { + addCloseable(new Closeable() { + + @Override + public void close() throws IOException { + managedStorage.shutdown(); + } + + }); + } else { + addCloseable(managedStorage); + } + storageCopy = managedStorage; + } + } + final CacheKeyGenerator uriExtractor = new CacheKeyGenerator(); + final HttpCache httpCache = new BasicHttpCache( + resourceFactoryCopy, + storageCopy, + uriExtractor, + this.httpCacheInvalidator != null ? this.httpCacheInvalidator : new CacheInvalidator(uriExtractor, storageCopy)); + + final AsyncCachingExec cachingExec = new AsyncCachingExec(httpCache, config); + execChainDefinition.addBefore(ChainElements.PROTOCOL.name(), cachingExec, ChainElements.CACHING.name()); + } + +} diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClients.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClients.java new file mode 100644 index 000000000..7356b8188 --- /dev/null +++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpAsyncClients.java @@ -0,0 +1,75 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.impl.cache; + +import java.io.File; + +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.core5.annotation.Contract; +import org.apache.hc.core5.annotation.ThreadingBehavior; + +/** + * Factory methods for {@link CloseableHttpAsyncClient} instances + * capable of client-side caching. + * + * @since 5.0 + */ +@Contract(threading = ThreadingBehavior.IMMUTABLE) +public class CachingHttpAsyncClients { + + private CachingHttpAsyncClients() { + super(); + } + + /** + * Creates builder object for construction of custom + * {@link CloseableHttpAsyncClient} instances. + */ + public static CachingHttpAsyncClientBuilder custom() { + return CachingHttpAsyncClientBuilder.create(); + } + + /** + * Creates {@link CloseableHttpAsyncClient} instance that uses a memory bound + * response cache. + */ + public static CloseableHttpAsyncClient createMemoryBound() { + return CachingHttpAsyncClientBuilder.create().build(); + } + + /** + * Creates {@link CloseableHttpAsyncClient} instance that uses a file system + * bound response cache. + * + * @param cacheDir location of response cache. + */ + public static CloseableHttpAsyncClient createFileBound(final File cacheDir) { + return CachingHttpAsyncClientBuilder.create().setCacheDir(cacheDir).build(); + } + +} diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java index 3a221e178..158361e55 100644 --- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java +++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/CachingHttpClientBuilder.java @@ -138,7 +138,7 @@ public void close() throws IOException { this.httpCacheInvalidator != null ? this.httpCacheInvalidator : new CacheInvalidator(uriExtractor, storageCopy)); final CachingExec cachingExec = new CachingExec(httpCache, config); - execChainDefinition.addAfter(ChainElements.PROTOCOL.name(), cachingExec, "CACHING"); + execChainDefinition.addBefore(ChainElements.PROTOCOL.name(), cachingExec, ChainElements.CACHING.name()); } } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElements.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElements.java index d570a4b9b..99d252378 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElements.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElements.java @@ -29,6 +29,6 @@ public enum ChainElements { - REDIRECT, BACK_OFF, RETRY_SERVICE_UNAVAILABLE, RETRY_IO_ERROR, PROTOCOL, CONNECT, MAIN_TRANSPORT + REDIRECT, BACK_OFF, RETRY_SERVICE_UNAVAILABLE, RETRY_IO_ERROR, CACHING, PROTOCOL, CONNECT, MAIN_TRANSPORT } \ No newline at end of file