1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.caches.ehcache;
17
18 import java.io.Serializable;
19 import java.nio.file.Path;
20 import java.time.Duration;
21 import java.util.concurrent.locks.ReadWriteLock;
22
23 import org.apache.ibatis.cache.Cache;
24 import org.ehcache.Cache.Entry;
25 import org.ehcache.PersistentCacheManager;
26 import org.ehcache.config.builders.CacheConfigurationBuilder;
27 import org.ehcache.config.builders.CacheManagerBuilder;
28 import org.ehcache.config.builders.ExpiryPolicyBuilder;
29 import org.ehcache.config.builders.ResourcePoolsBuilder;
30 import org.ehcache.config.units.EntryUnit;
31 import org.ehcache.config.units.MemoryUnit;
32
33
34
35
36
37
38 public abstract class AbstractEhcacheCache implements Cache {
39
40
41 private static final Object NULL_VALUE = new NullValue();
42
43
44
45
46
47 protected static PersistentCacheManager CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder()
48 .with(
49 CacheManagerBuilder.persistence(Path.of(System.getProperty("java.io.tmpdir"), "ehcache-mybatis").toString()))
50 .build(true);
51
52
53
54
55 protected final String id;
56
57
58
59
60 protected org.ehcache.Cache<Object, Object> cache;
61
62 protected long timeToIdleSeconds;
63 protected long timeToLiveSeconds;
64 protected long maxEntriesLocalHeap;
65 protected long maxEntriesLocalDisk;
66 protected long maxBytesLocalDisk;
67 protected String memoryStoreEvictionPolicy;
68
69
70
71
72
73
74
75 public AbstractEhcacheCache(final String id) {
76 if (id == null) {
77 throw new IllegalArgumentException("Cache instances require an ID");
78 }
79 this.id = id;
80
81 if (CACHE_MANAGER.getCache(id, Object.class, Object.class) != null) {
82 CACHE_MANAGER.removeCache(id);
83 }
84 }
85
86
87
88
89 protected synchronized org.ehcache.Cache<Object, Object> getOrCreateCache() {
90 if (cache == null) {
91 cache = buildAndRegisterCache();
92 }
93 return cache;
94 }
95
96
97
98
99 protected org.ehcache.Cache<Object, Object> buildAndRegisterCache() {
100 if (CACHE_MANAGER.getCache(id, Object.class, Object.class) != null) {
101 CACHE_MANAGER.removeCache(id);
102 }
103 long heapEntries = maxEntriesLocalHeap > 0 ? maxEntriesLocalHeap : Long.MAX_VALUE / 2;
104 ResourcePoolsBuilder poolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(heapEntries,
105 EntryUnit.ENTRIES);
106 if (maxBytesLocalDisk > 0) {
107 poolsBuilder = poolsBuilder.disk(maxBytesLocalDisk, MemoryUnit.B);
108 }
109 CacheConfigurationBuilder<Object, Object> builder = CacheConfigurationBuilder
110 .newCacheConfigurationBuilder(Object.class, Object.class, poolsBuilder).withExpiry(buildExpiryPolicy());
111 if (maxBytesLocalDisk > 0) {
112
113
114 builder = builder.withKeySerializer(ObjectSerializer.class).withValueSerializer(ObjectSerializer.class);
115 }
116 CACHE_MANAGER.createCache(id, builder.build());
117 return CACHE_MANAGER.getCache(id, Object.class, Object.class);
118 }
119
120 private org.ehcache.expiry.ExpiryPolicy<Object, Object> buildExpiryPolicy() {
121 if (timeToLiveSeconds > 0) {
122 return ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(timeToLiveSeconds));
123 }
124 if (timeToIdleSeconds > 0) {
125 return ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(timeToIdleSeconds));
126 }
127 return ExpiryPolicyBuilder.noExpiration();
128 }
129
130
131
132
133 @Override
134 public void clear() {
135 getOrCreateCache().clear();
136 }
137
138
139
140
141 @Override
142 public String getId() {
143 return id;
144 }
145
146
147
148
149 @Override
150 public Object getObject(Object key) {
151 Object value = getOrCreateCache().get(new HashKeyWrapper(key));
152 return value instanceof NullValue ? null : value;
153 }
154
155
156
157
158 @Override
159 public int getSize() {
160 int count = 0;
161 for (Entry<Object, Object> ignored : getOrCreateCache()) {
162 count++;
163 }
164 return count;
165 }
166
167
168
169
170 @Override
171 public void putObject(Object key, Object value) {
172 getOrCreateCache().put(new HashKeyWrapper(key), value == null ? NULL_VALUE : value);
173 }
174
175
176
177
178 @Override
179 public Object removeObject(Object key) {
180 Object obj = getObject(key);
181 getOrCreateCache().remove(new HashKeyWrapper(key));
182 return obj;
183 }
184
185
186
187
188 public void unlock(Object key) {
189 }
190
191
192
193
194 @Override
195 public boolean equals(Object obj) {
196 if (this == obj) {
197 return true;
198 }
199 if (obj == null) {
200 return false;
201 }
202 if (!(obj instanceof Cache)) {
203 return false;
204 }
205
206 Cache otherCache = (Cache) obj;
207 return id.equals(otherCache.getId());
208 }
209
210
211
212
213 @Override
214 public int hashCode() {
215 return id.hashCode();
216 }
217
218 @Override
219 public ReadWriteLock getReadWriteLock() {
220 return null;
221 }
222
223
224
225
226 @Override
227 public String toString() {
228 return "EHCache {" + id + "}";
229 }
230
231
232
233
234
235
236
237
238
239
240 public void setTimeToIdleSeconds(long timeToIdleSeconds) {
241 this.timeToIdleSeconds = timeToIdleSeconds;
242 recreateCacheIfInitialized();
243 }
244
245
246
247
248
249
250
251
252 public void setTimeToLiveSeconds(long timeToLiveSeconds) {
253 this.timeToLiveSeconds = timeToLiveSeconds;
254 recreateCacheIfInitialized();
255 }
256
257
258
259
260
261
262
263
264 public void setMaxEntriesLocalHeap(long maxEntriesLocalHeap) {
265 this.maxEntriesLocalHeap = maxEntriesLocalHeap;
266 recreateCacheIfInitialized();
267 }
268
269
270
271
272
273
274
275
276
277
278
279 public void setMaxEntriesLocalDisk(long maxEntriesLocalDisk) {
280 this.maxEntriesLocalDisk = maxEntriesLocalDisk;
281 recreateCacheIfInitialized();
282 }
283
284
285
286
287
288
289
290
291
292 public void setMaxBytesLocalDisk(long maxBytesLocalDisk) {
293 this.maxBytesLocalDisk = maxBytesLocalDisk;
294 recreateCacheIfInitialized();
295 }
296
297
298
299
300
301
302
303 public void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
304 this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
305 recreateCacheIfInitialized();
306 }
307
308
309
310
311
312 protected synchronized void recreateCacheIfInitialized() {
313 if (cache != null) {
314 cache = buildAndRegisterCache();
315 }
316 }
317
318
319
320
321
322 private static final class NullValue implements Serializable {
323 private static final long serialVersionUID = 1L;
324 }
325
326 }