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;
28
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.LinkedHashMap;
32 import java.util.Map;
33 import java.util.concurrent.locks.ReentrantLock;
34
35 import org.apache.hc.client5.http.cache.HttpCacheCASOperation;
36 import org.apache.hc.client5.http.cache.HttpCacheEntry;
37 import org.apache.hc.client5.http.cache.HttpCacheStorage;
38 import org.apache.hc.client5.http.cache.ResourceIOException;
39 import org.apache.hc.core5.annotation.Contract;
40 import org.apache.hc.core5.annotation.ThreadingBehavior;
41 import org.apache.hc.core5.util.Args;
42
43 /**
44 * Basic {@link HttpCacheStorage} implementation backed by an instance of
45 * {@link LinkedHashMap}. In other words, cache entries and
46 * the cached response bodies are held in-memory. This cache does NOT
47 * deallocate resources associated with the cache entries; it is intended
48 * for use with {@link HeapResource} and similar. This is the default cache
49 * storage backend used by {@link CachingHttpClients}.
50 *
51 * @since 4.1
52 */
53 @Contract(threading = ThreadingBehavior.SAFE)
54 public class BasicHttpCacheStorage implements HttpCacheStorage {
55
56 private final InternalCacheStorage entries;
57
58 private final ReentrantLock lock;
59
60 public BasicHttpCacheStorage(final CacheConfig config) {
61 super();
62 this.entries = new InternalCacheStorage(config.getMaxCacheEntries(), null);
63 this.lock = new ReentrantLock();
64 }
65
66 /**
67 * Places a HttpCacheEntry in the cache
68 *
69 * @param url
70 * Url to use as the cache key
71 * @param entry
72 * HttpCacheEntry to place in the cache
73 */
74 @Override
75 public void putEntry(
76 final String url, final HttpCacheEntry entry) throws ResourceIOException {
77 lock.lock();
78 try {
79 entries.put(url, entry);
80 } finally {
81 lock.unlock();
82 }
83 }
84
85 /**
86 * Gets an entry from the cache, if it exists
87 *
88 * @param url
89 * Url that is the cache key
90 * @return HttpCacheEntry if one exists, or null for cache miss
91 */
92 @Override
93 public HttpCacheEntry getEntry(final String url) throws ResourceIOException {
94 lock.lock();
95 try {
96 return entries.get(url);
97 } finally {
98 lock.unlock();
99 }
100 }
101
102 /**
103 * Removes a HttpCacheEntry from the cache
104 *
105 * @param url
106 * Url that is the cache key
107 */
108 @Override
109 public void removeEntry(final String url) throws ResourceIOException {
110 lock.lock();
111 try {
112 entries.remove(url);
113 } finally {
114 lock.unlock();
115 }
116
117 }
118
119 @Override
120 public void updateEntry(
121 final String url, final HttpCacheCASOperation casOperation) throws ResourceIOException {
122 lock.lock();
123 try {
124 final HttpCacheEntry existingEntry = entries.get(url);
125 entries.put(url, casOperation.execute(existingEntry));
126 } finally {
127 lock.unlock();
128 }
129 }
130
131 @Override
132 public Map<String, HttpCacheEntry> getEntries(final Collection<String> keys) throws ResourceIOException {
133 Args.notNull(keys, "Key");
134 final Map<String, HttpCacheEntry> resultMap = new HashMap<>(keys.size());
135 for (final String key: keys) {
136 final HttpCacheEntry entry = getEntry(key);
137 if (entry != null) {
138 resultMap.put(key, entry);
139 }
140 }
141 return resultMap;
142 }
143
144 }