1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.jcs3.jcache.proxy;
20
21 import javax.cache.Cache;
22 import javax.cache.CacheManager;
23 import javax.cache.configuration.CacheEntryListenerConfiguration;
24 import javax.cache.configuration.Configuration;
25 import javax.cache.integration.CompletionListener;
26 import javax.cache.processor.EntryProcessor;
27 import javax.cache.processor.EntryProcessorException;
28 import javax.cache.processor.EntryProcessorResult;
29
30 import org.apache.commons.jcs3.jcache.JCSCache;
31
32 import java.io.Serializable;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Set;
36
37
38 public class ClassLoaderAwareCache<K, V> implements Cache<K, V>
39 {
40 private final ClassLoader loader;
41 private final JCSCache<K, V> delegate;
42
43 public ClassLoaderAwareCache(final ClassLoader loader, final JCSCache<K, V> delegate)
44 {
45 this.loader = loader;
46 this.delegate = delegate;
47 }
48
49 private ClassLoader before(final Thread thread)
50 {
51 final ClassLoader tccl = thread.getContextClassLoader();
52 thread.setContextClassLoader(loader);
53 return tccl;
54 }
55
56 @Override
57 public V get(final K key)
58 {
59 final Thread thread = Thread.currentThread();
60 final ClassLoader loader = before(thread);
61 try
62 {
63 return delegate.get(key);
64 }
65 finally
66 {
67 thread.setContextClassLoader(loader);
68 }
69 }
70
71 @Override
72 public Map<K, V> getAll(final Set<? extends K> keys)
73 {
74 final Thread thread = Thread.currentThread();
75 final ClassLoader loader = before(thread);
76 try
77 {
78 return delegate.getAll(keys);
79 }
80 finally
81 {
82 thread.setContextClassLoader(loader);
83 }
84 }
85
86 @Override
87 public boolean containsKey(final K key)
88 {
89 final Thread thread = Thread.currentThread();
90 final ClassLoader loader = before(thread);
91 try
92 {
93 return delegate.containsKey(key);
94 }
95 finally
96 {
97 thread.setContextClassLoader(loader);
98 }
99 }
100
101 @Override
102 public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
103 {
104 final Thread thread = Thread.currentThread();
105 final ClassLoader loader = before(thread);
106 try
107 {
108 delegate.loadAll(keys, replaceExistingValues, completionListener);
109 }
110 finally
111 {
112 thread.setContextClassLoader(loader);
113 }
114 }
115
116 @Override
117 public void put(final K key, final V value)
118 {
119 final Thread thread = Thread.currentThread();
120 final ClassLoader loader = before(thread);
121 try
122 {
123 delegate.put(key, value);
124 }
125 finally
126 {
127 thread.setContextClassLoader(loader);
128 }
129 }
130
131 @Override
132 public V getAndPut(final K key, final V value)
133 {
134 final Thread thread = Thread.currentThread();
135 final ClassLoader loader = before(thread);
136 try
137 {
138 return delegate.getAndPut(key, value);
139 }
140 finally
141 {
142 thread.setContextClassLoader(loader);
143 }
144 }
145
146 @Override
147 public void putAll(final Map<? extends K, ? extends V> map)
148 {
149 final Thread thread = Thread.currentThread();
150 final ClassLoader loader = before(thread);
151 try
152 {
153 delegate.putAll(map);
154 }
155 finally
156 {
157 thread.setContextClassLoader(loader);
158 }
159 }
160
161 @Override
162 public boolean putIfAbsent(final K key, final V value)
163 {
164 final Thread thread = Thread.currentThread();
165 final ClassLoader loader = before(thread);
166 try
167 {
168 return delegate.putIfAbsent(key, value);
169 }
170 finally
171 {
172 thread.setContextClassLoader(loader);
173 }
174 }
175
176 @Override
177 public boolean remove(final K key)
178 {
179 final Thread thread = Thread.currentThread();
180 final ClassLoader loader = before(thread);
181 try
182 {
183 return delegate.remove(key);
184 }
185 finally
186 {
187 thread.setContextClassLoader(loader);
188 }
189 }
190
191 @Override
192 public boolean remove(final K key, final V oldValue)
193 {
194 final Thread thread = Thread.currentThread();
195 final ClassLoader loader = before(thread);
196 try
197 {
198 return delegate.remove(key, oldValue);
199 }
200 finally
201 {
202 thread.setContextClassLoader(loader);
203 }
204 }
205
206 @Override
207 public V getAndRemove(final K key)
208 {
209 final Thread thread = Thread.currentThread();
210 final ClassLoader loader = before(thread);
211 try
212 {
213 return delegate.getAndRemove(key);
214 }
215 finally
216 {
217 thread.setContextClassLoader(loader);
218 }
219 }
220
221 @Override
222 public boolean replace(final K key, final V oldValue, final V newValue)
223 {
224 final Thread thread = Thread.currentThread();
225 final ClassLoader loader = before(thread);
226 try
227 {
228 return delegate.replace(key, oldValue, newValue);
229 }
230 finally
231 {
232 thread.setContextClassLoader(loader);
233 }
234 }
235
236 @Override
237 public boolean replace(final K key, final V value)
238 {
239 final Thread thread = Thread.currentThread();
240 final ClassLoader loader = before(thread);
241 try
242 {
243 return delegate.replace(key, value);
244 }
245 finally
246 {
247 thread.setContextClassLoader(loader);
248 }
249 }
250
251 @Override
252 public V getAndReplace(final K key, final V value)
253 {
254 final Thread thread = Thread.currentThread();
255 final ClassLoader loader = before(thread);
256 try
257 {
258 return delegate.getAndReplace(key, value);
259 }
260 finally
261 {
262 thread.setContextClassLoader(loader);
263 }
264 }
265
266 @Override
267 public void removeAll(final Set<? extends K> keys)
268 {
269 final Thread thread = Thread.currentThread();
270 final ClassLoader loader = before(thread);
271 try
272 {
273 delegate.removeAll(keys);
274 }
275 finally
276 {
277 thread.setContextClassLoader(loader);
278 }
279 }
280
281 @Override
282 public void removeAll()
283 {
284 final Thread thread = Thread.currentThread();
285 final ClassLoader loader = before(thread);
286 try
287 {
288 delegate.removeAll();
289 }
290 finally
291 {
292 thread.setContextClassLoader(loader);
293 }
294 }
295
296 @Override
297 public void clear()
298 {
299 final Thread thread = Thread.currentThread();
300 final ClassLoader loader = before(thread);
301 try
302 {
303 delegate.clear();
304 }
305 finally
306 {
307 thread.setContextClassLoader(loader);
308 }
309 }
310
311 @Override
312 public <C extends Configuration<K, V>> C getConfiguration(final Class<C> clazz)
313 {
314 final Thread thread = Thread.currentThread();
315 final ClassLoader loader = before(thread);
316 try
317 {
318 return delegate.getConfiguration(clazz);
319 }
320 finally
321 {
322 thread.setContextClassLoader(loader);
323 }
324 }
325
326 @Override
327 public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException
328 {
329 final Thread thread = Thread.currentThread();
330 final ClassLoader loader = before(thread);
331 try
332 {
333 return delegate.invoke(key, entryProcessor, arguments);
334 }
335 finally
336 {
337 thread.setContextClassLoader(loader);
338 }
339 }
340
341 @Override
342 public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments)
343 {
344 final Thread thread = Thread.currentThread();
345 final ClassLoader loader = before(thread);
346 try
347 {
348 return delegate.invokeAll(keys, entryProcessor, arguments);
349 }
350 finally
351 {
352 thread.setContextClassLoader(loader);
353 }
354 }
355
356 @Override
357 public String getName()
358 {
359 final Thread thread = Thread.currentThread();
360 final ClassLoader loader = before(thread);
361 try
362 {
363 return delegate.getName();
364 }
365 finally
366 {
367 thread.setContextClassLoader(loader);
368 }
369 }
370
371 @Override
372 public CacheManager getCacheManager()
373 {
374 final Thread thread = Thread.currentThread();
375 final ClassLoader loader = before(thread);
376 try
377 {
378 return delegate.getCacheManager();
379 }
380 finally
381 {
382 thread.setContextClassLoader(loader);
383 }
384 }
385
386 @Override
387 public void close()
388 {
389 final Thread thread = Thread.currentThread();
390 final ClassLoader loader = before(thread);
391 try
392 {
393 delegate.close();
394 }
395 finally
396 {
397 thread.setContextClassLoader(loader);
398 }
399 }
400
401 @Override
402 public boolean isClosed()
403 {
404 final Thread thread = Thread.currentThread();
405 final ClassLoader loader = before(thread);
406 try
407 {
408 return delegate.isClosed();
409 }
410 finally
411 {
412 thread.setContextClassLoader(loader);
413 }
414 }
415
416 @Override
417 public <T> T unwrap(final Class<T> clazz)
418 {
419 final Thread thread = Thread.currentThread();
420 final ClassLoader loader = before(thread);
421 try
422 {
423 return delegate.unwrap(clazz);
424 }
425 finally
426 {
427 thread.setContextClassLoader(loader);
428 }
429 }
430
431 @Override
432 public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
433 {
434 final Thread thread = Thread.currentThread();
435 final ClassLoader loader = before(thread);
436 try
437 {
438 delegate.registerCacheEntryListener(cacheEntryListenerConfiguration);
439 }
440 finally
441 {
442 thread.setContextClassLoader(loader);
443 }
444 }
445
446 @Override
447 public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
448 {
449 final Thread thread = Thread.currentThread();
450 final ClassLoader loader = before(thread);
451 try
452 {
453 delegate.deregisterCacheEntryListener(cacheEntryListenerConfiguration);
454 }
455 finally
456 {
457 thread.setContextClassLoader(loader);
458 }
459 }
460
461 @Override
462 public Iterator<Entry<K, V>> iterator()
463 {
464 final Thread thread = Thread.currentThread();
465 final ClassLoader loader = before(thread);
466 try
467 {
468 return delegate.iterator();
469 }
470 finally
471 {
472 thread.setContextClassLoader(loader);
473 }
474 }
475
476 @Override
477 public boolean equals(final Object obj)
478 {
479 if (ClassLoaderAwareCache.class.isInstance(obj))
480 {
481 return delegate.equals(ClassLoaderAwareCache.class.cast(obj).delegate);
482 }
483 return super.equals(obj);
484 }
485
486 @Override
487 public int hashCode()
488 {
489 return delegate.hashCode();
490 }
491
492 public static <K extends Serializable, V extends Serializable> Cache<K, V> wrap(final ClassLoader loader, final JCSCache<K, V> delegate)
493 {
494 ClassLoader dontWrapLoader = ClassLoaderAwareCache.class.getClassLoader();
495 while (dontWrapLoader != null)
496 {
497 if (loader == dontWrapLoader)
498 {
499 return delegate;
500 }
501 dontWrapLoader = dontWrapLoader.getParent();
502 }
503 return new ClassLoaderAwareCache<>(loader, delegate);
504 }
505
506 public static <K extends Serializable, V extends Serializable> JCSCache<K, V> getDelegate(final Cache<?, ?> cache)
507 {
508 if (JCSCache.class.isInstance(cache))
509 {
510 return (JCSCache<K, V>) cache;
511 }
512 return ((ClassLoaderAwareCache<K, V>) cache).delegate;
513 }
514 }