1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27 package org.apache.hc.client5.http.impl.cache.ehcache;
28
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import org.apache.hc.client5.http.cache.HttpCacheEntrySerializer;
34 import org.apache.hc.client5.http.cache.HttpCacheStorageEntry;
35 import org.apache.hc.client5.http.cache.ResourceIOException;
36 import org.apache.hc.client5.http.impl.cache.AbstractSerializingCacheStorage;
37 import org.apache.hc.client5.http.impl.cache.ByteArrayCacheEntrySerializer;
38 import org.apache.hc.client5.http.impl.cache.CacheConfig;
39 import org.apache.hc.client5.http.impl.cache.NoopCacheEntrySerializer;
40 import org.apache.hc.core5.util.Args;
41 import org.ehcache.Cache;
42
43 /**
44 * <p>This class is a storage backend for cache entries that uses the
45 * popular <a href="http://ehcache.org">Ehcache</a> cache implementation.
46 * In particular, this backend allows for spillover to disk, where the
47 * cache can be effectively larger than memory, and cached responses are
48 * paged into and out of memory from disk as needed.</p>
49 *
50 * <p><b>N.B.</b> Since the Ehcache is configured ahead of time with a
51 * maximum number of cache entries, this effectively ignores the
52 * {@link CacheConfig#getMaxCacheEntries()} maximum cache entries}
53 * specified by a provided {@link CacheConfig}.</p>
54 *
55 * <p>Please refer to the <a href="http://ehcache.org/documentation/index.html">
56 * Ehcache documentation</a> for details on how to configure the Ehcache
57 * itself.</p>
58 * @since 4.1
59 */
60 public class EhcacheHttpCacheStorage<T> extends AbstractSerializingCacheStorage<T, T> {
61
62 /**
63 * Creates cache that stores {@link HttpCacheStorageEntry}s without direct serialization.
64 *
65 * @since 5.0
66 */
67 public static EhcacheHttpCacheStorage<HttpCacheStorageEntry> createObjectCache(
68 final Cache<String, HttpCacheStorageEntry> cache, final CacheConfig config) {
69 return new EhcacheHttpCacheStorage<>(cache, config, NoopCacheEntrySerializer.INSTANCE);
70 }
71
72 /**
73 * Creates cache that stores serialized {@link HttpCacheStorageEntry}s.
74 *
75 * @since 5.0
76 */
77 public static EhcacheHttpCacheStorage<byte[]> createSerializedCache(
78 final Cache<String, byte[]> cache, final CacheConfig config) {
79 return new EhcacheHttpCacheStorage<>(cache, config, ByteArrayCacheEntrySerializer.INSTANCE);
80 }
81
82 private final Cache<String, T> cache;
83
84 /**
85 * Constructs a storage backend using the provided Ehcache
86 * with the given configuration options, but using an alternative
87 * cache entry serialization strategy.
88 * @param cache where to store cached origin responses
89 * @param config cache storage configuration options - note that
90 * the setting for max object size <b>will be ignored</b> and
91 * should be configured in the Ehcache instead.
92 * @param serializer alternative serialization mechanism
93 */
94 public EhcacheHttpCacheStorage(
95 final Cache<String, T> cache,
96 final CacheConfig config,
97 final HttpCacheEntrySerializer<T> serializer) {
98 super((config != null ? config : CacheConfig.DEFAULT).getMaxUpdateRetries(), serializer);
99 this.cache = Args.notNull(cache, "Ehcache");
100 }
101
102 @Override
103 protected String digestToStorageKey(final String key) {
104 return key;
105 }
106
107 @Override
108 protected void store(final String storageKey, final T storageObject) throws ResourceIOException {
109 cache.put(storageKey, storageObject);
110 }
111
112 @Override
113 protected T restore(final String storageKey) throws ResourceIOException {
114 return cache.get(storageKey);
115 }
116
117 @Override
118 protected T getForUpdateCAS(final String storageKey) throws ResourceIOException {
119 return cache.get(storageKey);
120 }
121
122 @Override
123 protected T getStorageObject(final T element) throws ResourceIOException {
124 return element;
125 }
126
127 @Override
128 protected boolean updateCAS(
129 final String storageKey, final T oldStorageObject, final T storageObject) throws ResourceIOException {
130 return cache.replace(storageKey, oldStorageObject, storageObject);
131 }
132
133 @Override
134 protected void delete(final String storageKey) throws ResourceIOException {
135 cache.remove(storageKey);
136 }
137
138 @Override
139 protected Map<String, T> bulkRestore(final Collection<String> storageKeys) throws ResourceIOException {
140 final Map<String, T> resultMap = new HashMap<>();
141 for (final String storageKey: storageKeys) {
142 final T storageObject = cache.get(storageKey);
143 if (storageObject != null) {
144 resultMap.put(storageKey, storageObject);
145 }
146 }
147 return resultMap;
148 }
149
150 }