ClassLoaderAwareCache.java

  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.jcs3.jcache.proxy;

  20. import javax.cache.Cache;
  21. import javax.cache.CacheManager;
  22. import javax.cache.configuration.CacheEntryListenerConfiguration;
  23. import javax.cache.configuration.Configuration;
  24. import javax.cache.integration.CompletionListener;
  25. import javax.cache.processor.EntryProcessor;
  26. import javax.cache.processor.EntryProcessorException;
  27. import javax.cache.processor.EntryProcessorResult;

  28. import org.apache.commons.jcs3.jcache.JCSCache;

  29. import java.io.Serializable;
  30. import java.util.Iterator;
  31. import java.util.Map;
  32. import java.util.Set;

  33. // don't use a proxy, reflection is too slow here :(
  34. public class ClassLoaderAwareCache<K, V> implements Cache<K, V>
  35. {
  36.     private final ClassLoader loader;
  37.     private final JCSCache<K, V> delegate;

  38.     public ClassLoaderAwareCache(final ClassLoader loader, final JCSCache<K, V> delegate)
  39.     {
  40.         this.loader = loader;
  41.         this.delegate = delegate;
  42.     }

  43.     private ClassLoader before(final Thread thread)
  44.     {
  45.         final ClassLoader tccl = thread.getContextClassLoader();
  46.         thread.setContextClassLoader(loader);
  47.         return tccl;
  48.     }

  49.     @Override
  50.     public V get(final K key)
  51.     {
  52.         final Thread thread = Thread.currentThread();
  53.         final ClassLoader loader = before(thread);
  54.         try
  55.         {
  56.             return delegate.get(key);
  57.         }
  58.         finally
  59.         {
  60.             thread.setContextClassLoader(loader);
  61.         }
  62.     }

  63.     @Override
  64.     public Map<K, V> getAll(final Set<? extends K> keys)
  65.     {
  66.         final Thread thread = Thread.currentThread();
  67.         final ClassLoader loader = before(thread);
  68.         try
  69.         {
  70.             return delegate.getAll(keys);
  71.         }
  72.         finally
  73.         {
  74.             thread.setContextClassLoader(loader);
  75.         }
  76.     }

  77.     @Override
  78.     public boolean containsKey(final K key)
  79.     {
  80.         final Thread thread = Thread.currentThread();
  81.         final ClassLoader loader = before(thread);
  82.         try
  83.         {
  84.             return delegate.containsKey(key);
  85.         }
  86.         finally
  87.         {
  88.             thread.setContextClassLoader(loader);
  89.         }
  90.     }

  91.     @Override
  92.     public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues, final CompletionListener completionListener)
  93.     {
  94.         final Thread thread = Thread.currentThread();
  95.         final ClassLoader loader = before(thread);
  96.         try
  97.         {
  98.             delegate.loadAll(keys, replaceExistingValues, completionListener);
  99.         }
  100.         finally
  101.         {
  102.             thread.setContextClassLoader(loader);
  103.         }
  104.     }

  105.     @Override
  106.     public void put(final K key, final V value)
  107.     {
  108.         final Thread thread = Thread.currentThread();
  109.         final ClassLoader loader = before(thread);
  110.         try
  111.         {
  112.             delegate.put(key, value);
  113.         }
  114.         finally
  115.         {
  116.             thread.setContextClassLoader(loader);
  117.         }
  118.     }

  119.     @Override
  120.     public V getAndPut(final K key, final V value)
  121.     {
  122.         final Thread thread = Thread.currentThread();
  123.         final ClassLoader loader = before(thread);
  124.         try
  125.         {
  126.             return delegate.getAndPut(key, value);
  127.         }
  128.         finally
  129.         {
  130.             thread.setContextClassLoader(loader);
  131.         }
  132.     }

  133.     @Override
  134.     public void putAll(final Map<? extends K, ? extends V> map)
  135.     {
  136.         final Thread thread = Thread.currentThread();
  137.         final ClassLoader loader = before(thread);
  138.         try
  139.         {
  140.             delegate.putAll(map);
  141.         }
  142.         finally
  143.         {
  144.             thread.setContextClassLoader(loader);
  145.         }
  146.     }

  147.     @Override
  148.     public boolean putIfAbsent(final K key, final V value)
  149.     {
  150.         final Thread thread = Thread.currentThread();
  151.         final ClassLoader loader = before(thread);
  152.         try
  153.         {
  154.             return delegate.putIfAbsent(key, value);
  155.         }
  156.         finally
  157.         {
  158.             thread.setContextClassLoader(loader);
  159.         }
  160.     }

  161.     @Override
  162.     public boolean remove(final K key)
  163.     {
  164.         final Thread thread = Thread.currentThread();
  165.         final ClassLoader loader = before(thread);
  166.         try
  167.         {
  168.             return delegate.remove(key);
  169.         }
  170.         finally
  171.         {
  172.             thread.setContextClassLoader(loader);
  173.         }
  174.     }

  175.     @Override
  176.     public boolean remove(final K key, final V oldValue)
  177.     {
  178.         final Thread thread = Thread.currentThread();
  179.         final ClassLoader loader = before(thread);
  180.         try
  181.         {
  182.             return delegate.remove(key, oldValue);
  183.         }
  184.         finally
  185.         {
  186.             thread.setContextClassLoader(loader);
  187.         }
  188.     }

  189.     @Override
  190.     public V getAndRemove(final K key)
  191.     {
  192.         final Thread thread = Thread.currentThread();
  193.         final ClassLoader loader = before(thread);
  194.         try
  195.         {
  196.             return delegate.getAndRemove(key);
  197.         }
  198.         finally
  199.         {
  200.             thread.setContextClassLoader(loader);
  201.         }
  202.     }

  203.     @Override
  204.     public boolean replace(final K key, final V oldValue, final V newValue)
  205.     {
  206.         final Thread thread = Thread.currentThread();
  207.         final ClassLoader loader = before(thread);
  208.         try
  209.         {
  210.             return delegate.replace(key, oldValue, newValue);
  211.         }
  212.         finally
  213.         {
  214.             thread.setContextClassLoader(loader);
  215.         }
  216.     }

  217.     @Override
  218.     public boolean replace(final K key, final V value)
  219.     {
  220.         final Thread thread = Thread.currentThread();
  221.         final ClassLoader loader = before(thread);
  222.         try
  223.         {
  224.             return delegate.replace(key, value);
  225.         }
  226.         finally
  227.         {
  228.             thread.setContextClassLoader(loader);
  229.         }
  230.     }

  231.     @Override
  232.     public V getAndReplace(final K key, final V value)
  233.     {
  234.         final Thread thread = Thread.currentThread();
  235.         final ClassLoader loader = before(thread);
  236.         try
  237.         {
  238.             return delegate.getAndReplace(key, value);
  239.         }
  240.         finally
  241.         {
  242.             thread.setContextClassLoader(loader);
  243.         }
  244.     }

  245.     @Override
  246.     public void removeAll(final Set<? extends K> keys)
  247.     {
  248.         final Thread thread = Thread.currentThread();
  249.         final ClassLoader loader = before(thread);
  250.         try
  251.         {
  252.             delegate.removeAll(keys);
  253.         }
  254.         finally
  255.         {
  256.             thread.setContextClassLoader(loader);
  257.         }
  258.     }

  259.     @Override
  260.     public void removeAll()
  261.     {
  262.         final Thread thread = Thread.currentThread();
  263.         final ClassLoader loader = before(thread);
  264.         try
  265.         {
  266.             delegate.removeAll();
  267.         }
  268.         finally
  269.         {
  270.             thread.setContextClassLoader(loader);
  271.         }
  272.     }

  273.     @Override
  274.     public void clear()
  275.     {
  276.         final Thread thread = Thread.currentThread();
  277.         final ClassLoader loader = before(thread);
  278.         try
  279.         {
  280.             delegate.clear();
  281.         }
  282.         finally
  283.         {
  284.             thread.setContextClassLoader(loader);
  285.         }
  286.     }

  287.     @Override
  288.     public <C extends Configuration<K, V>> C getConfiguration(final Class<C> clazz)
  289.     {
  290.         final Thread thread = Thread.currentThread();
  291.         final ClassLoader loader = before(thread);
  292.         try
  293.         {
  294.             return delegate.getConfiguration(clazz);
  295.         }
  296.         finally
  297.         {
  298.             thread.setContextClassLoader(loader);
  299.         }
  300.     }

  301.     @Override
  302.     public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException
  303.     {
  304.         final Thread thread = Thread.currentThread();
  305.         final ClassLoader loader = before(thread);
  306.         try
  307.         {
  308.             return delegate.invoke(key, entryProcessor, arguments);
  309.         }
  310.         finally
  311.         {
  312.             thread.setContextClassLoader(loader);
  313.         }
  314.     }

  315.     @Override
  316.     public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments)
  317.     {
  318.         final Thread thread = Thread.currentThread();
  319.         final ClassLoader loader = before(thread);
  320.         try
  321.         {
  322.             return delegate.invokeAll(keys, entryProcessor, arguments);
  323.         }
  324.         finally
  325.         {
  326.             thread.setContextClassLoader(loader);
  327.         }
  328.     }

  329.     @Override
  330.     public String getName()
  331.     {
  332.         final Thread thread = Thread.currentThread();
  333.         final ClassLoader loader = before(thread);
  334.         try
  335.         {
  336.             return delegate.getName();
  337.         }
  338.         finally
  339.         {
  340.             thread.setContextClassLoader(loader);
  341.         }
  342.     }

  343.     @Override
  344.     public CacheManager getCacheManager()
  345.     {
  346.         final Thread thread = Thread.currentThread();
  347.         final ClassLoader loader = before(thread);
  348.         try
  349.         {
  350.             return delegate.getCacheManager();
  351.         }
  352.         finally
  353.         {
  354.             thread.setContextClassLoader(loader);
  355.         }
  356.     }

  357.     @Override
  358.     public void close()
  359.     {
  360.         final Thread thread = Thread.currentThread();
  361.         final ClassLoader loader = before(thread);
  362.         try
  363.         {
  364.             delegate.close();
  365.         }
  366.         finally
  367.         {
  368.             thread.setContextClassLoader(loader);
  369.         }
  370.     }

  371.     @Override
  372.     public boolean isClosed()
  373.     {
  374.         final Thread thread = Thread.currentThread();
  375.         final ClassLoader loader = before(thread);
  376.         try
  377.         {
  378.             return delegate.isClosed();
  379.         }
  380.         finally
  381.         {
  382.             thread.setContextClassLoader(loader);
  383.         }
  384.     }

  385.     @Override
  386.     public <T> T unwrap(final Class<T> clazz)
  387.     {
  388.         final Thread thread = Thread.currentThread();
  389.         final ClassLoader loader = before(thread);
  390.         try
  391.         {
  392.             return delegate.unwrap(clazz);
  393.         }
  394.         finally
  395.         {
  396.             thread.setContextClassLoader(loader);
  397.         }
  398.     }

  399.     @Override
  400.     public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
  401.     {
  402.         final Thread thread = Thread.currentThread();
  403.         final ClassLoader loader = before(thread);
  404.         try
  405.         {
  406.             delegate.registerCacheEntryListener(cacheEntryListenerConfiguration);
  407.         }
  408.         finally
  409.         {
  410.             thread.setContextClassLoader(loader);
  411.         }
  412.     }

  413.     @Override
  414.     public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration)
  415.     {
  416.         final Thread thread = Thread.currentThread();
  417.         final ClassLoader loader = before(thread);
  418.         try
  419.         {
  420.             delegate.deregisterCacheEntryListener(cacheEntryListenerConfiguration);
  421.         }
  422.         finally
  423.         {
  424.             thread.setContextClassLoader(loader);
  425.         }
  426.     }

  427.     @Override
  428.     public Iterator<Entry<K, V>> iterator()
  429.     {
  430.         final Thread thread = Thread.currentThread();
  431.         final ClassLoader loader = before(thread);
  432.         try
  433.         {
  434.             return delegate.iterator();
  435.         }
  436.         finally
  437.         {
  438.             thread.setContextClassLoader(loader);
  439.         }
  440.     }

  441.     @Override
  442.     public boolean equals(final Object obj)
  443.     {
  444.         if (ClassLoaderAwareCache.class.isInstance(obj))
  445.         {
  446.             return delegate.equals(ClassLoaderAwareCache.class.cast(obj).delegate);
  447.         }
  448.         return super.equals(obj);
  449.     }

  450.     @Override
  451.     public int hashCode()
  452.     {
  453.         return delegate.hashCode();
  454.     }

  455.     public static <K extends Serializable, V extends Serializable> Cache<K, V> wrap(final ClassLoader loader, final JCSCache<K, V> delegate)
  456.     {
  457.         ClassLoader dontWrapLoader = ClassLoaderAwareCache.class.getClassLoader();
  458.         while (dontWrapLoader != null)
  459.         {
  460.             if (loader == dontWrapLoader)
  461.             {
  462.                 return delegate;
  463.             }
  464.             dontWrapLoader = dontWrapLoader.getParent();
  465.         }
  466.         return new ClassLoaderAwareCache<>(loader, delegate);
  467.     }

  468.     public static <K extends Serializable, V extends Serializable> JCSCache<K, V> getDelegate(final Cache<?, ?> cache)
  469.     {
  470.         if (JCSCache.class.isInstance(cache))
  471.         {
  472.             return (JCSCache<K, V>) cache;
  473.         }
  474.         return ((ClassLoaderAwareCache<K, V>) cache).delegate;
  475.     }
  476. }