View Javadoc
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 }