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