View Javadoc

1   package com.atlassian.cache.ehcache;
2   
3   import java.util.Collection;
4   import java.util.SortedMap;
5   
6   import javax.annotation.Nonnull;
7   import javax.annotation.Nullable;
8   
9   import com.atlassian.cache.Cache;
10  import com.atlassian.cache.CacheEntryListener;
11  import com.atlassian.cache.CacheException;
12  import com.atlassian.cache.CacheSettings;
13  import com.atlassian.cache.CacheStatisticsKey;
14  import com.atlassian.util.concurrent.Supplier;
15  
16  import com.atlassian.cache.impl.CacheEntryListenerSupport;
17  import com.atlassian.cache.impl.LazyCacheEntryListenerSupport;
18  import net.sf.ehcache.Ehcache;
19  import net.sf.ehcache.Element;
20  import net.sf.ehcache.event.CacheEventListener;
21  
22  import static com.atlassian.cache.ehcache.DelegatingCacheStatistics.toStatistics;
23  
24  /**
25   * A Cache that delegates to EhCache.
26   *
27   * @since 2.0
28   */
29  class DelegatingCache<K, V> extends ManagedCacheSupport implements Cache<K, V>
30  {
31      private final Ehcache delegate;
32  
33      private final CacheEntryListenerSupport<K, V> listenerSupport = new LazyCacheEntryListenerSupport<K, V>()
34      {
35          @Override
36          protected void init()
37          {
38              delegate.getCacheEventNotificationService().registerListener(new DelegatingCacheEventListener());
39          }
40      };
41  
42      private DelegatingCache(final Ehcache delegate, CacheSettings settings)
43      {
44          super(delegate, settings);
45          this.delegate = delegate;
46      }
47  
48      static <K, V> DelegatingCache<K, V> create(final Ehcache delegate, CacheSettings settings)
49      {
50          return new DelegatingCache<K, V>(delegate, settings);
51      }
52  
53      @Override
54      public boolean containsKey(@Nonnull K key)
55      {
56          return delegate.isKeyInCache(key);
57      }
58  
59      @Nonnull
60      @SuppressWarnings("unchecked")
61      @Override
62      public Collection<K> getKeys()
63      {
64          try
65          {
66              return delegate.getKeys();
67          }
68          catch (Exception e)
69          {
70              throw new CacheException(e);
71          }
72      }
73  
74      @Override
75      public void put(@Nonnull final K key, @Nonnull final V value)
76      {
77          try
78          {
79              delegate.put(new Element(key, value));
80          }
81          catch (Exception e)
82          {
83              throw new CacheException(e);
84          }
85      }
86  
87      @SuppressWarnings("unchecked")
88      @Nullable
89      @Override
90      public V get(@Nonnull final K key)
91      {
92          try
93          {
94              Element element = delegate.get(key);
95              return element == null ? null : (V) element.getObjectValue();
96          }
97          catch (net.sf.ehcache.CacheException e)
98          {
99              throw new CacheException(e.getCause());
100         }
101         catch (Exception e)
102         {
103             throw new CacheException(e);
104         }
105     }
106 
107     @SuppressWarnings("unchecked")
108     @Nonnull
109     @Override
110     public V get(@Nonnull final K key, @Nonnull final com.atlassian.cache.Supplier<? extends V> valueSupplier)
111     {
112         try
113         {
114             Element element = delegate.getWithLoader(key, new ReferenceCacheLoader(valueSupplier), null);
115             return (V) element.getObjectValue();
116         }
117         catch (net.sf.ehcache.CacheException e)
118         {
119             throw new CacheException(e.getCause());
120         }
121         catch (Exception e)
122         {
123             throw new CacheException(e);
124         }
125     }
126 
127     @Override
128     public void remove(@Nonnull final K key)
129     {
130         try
131         {
132             try
133             {
134                 delegate.get(key);
135             }
136             finally
137             {
138                 delegate.remove(key);
139             }
140         }
141         catch (Exception e)
142         {
143             throw new CacheException(e);
144         }
145     }
146 
147     @Override
148     public void removeAll()
149     {
150         try
151         {
152             delegate.removeAll();
153         }
154         catch (Exception e)
155         {
156             throw new CacheException(e);
157         }
158     }
159 
160     @Override
161     public void clear()
162     {
163         removeAll();
164     }
165 
166     @Nullable
167     @Override
168     @SuppressWarnings("unchecked")
169     public V putIfAbsent(@Nonnull K key, @Nonnull V value)
170     {
171         try
172         {
173             Element previous = delegate.putIfAbsent(new Element(key, value));
174             if (previous != null)
175             {
176                 return (V) previous.getObjectValue();
177             }
178             else
179             {
180                 return null;
181             }
182         }
183         catch (Exception e)
184         {
185             throw new CacheException(e);
186         }
187     }
188 
189     @Override
190     public boolean remove(@Nonnull K key, @Nonnull V value)
191     {
192         try
193         {
194             boolean wasRemoved;
195             try
196             {
197                 delegate.get(key);
198             }
199             finally
200             {
201                 wasRemoved = delegate.removeElement(new Element(key, value));
202             }
203             return wasRemoved;
204         }
205         catch (Exception e)
206         {
207             throw new CacheException(e);
208         }
209     }
210 
211     @Override
212     public boolean replace(@Nonnull K key, @Nonnull V oldValue, @Nonnull V newValue)
213     {
214         try
215         {
216             return delegate.replace(new Element(key, oldValue), new Element(key, newValue));
217         }
218         catch (Exception e)
219         {
220             throw new CacheException(e);
221         }
222     }
223 
224     @Nonnull
225     @Override
226     public SortedMap<CacheStatisticsKey,Supplier<Long>> getStatistics()
227     {
228         return toStatistics(delegate.getStatistics());
229     }
230 
231     @Override
232     public boolean equals(@Nullable final Object other)
233     {
234         if (other instanceof DelegatingCache)
235         {
236             DelegatingCache<?,?> otherDelegatingCache = (DelegatingCache<?,?>)other;
237             if (delegate.equals(otherDelegatingCache.delegate))
238             {
239                 return true;
240             }
241         }
242         return false;
243     }
244 
245     @Override
246     public int hashCode()
247     {
248         return 3 + delegate.hashCode();
249     }
250 
251     @Override
252     public void addListener(@Nonnull CacheEntryListener<K, V> listener, boolean includeValues)
253     {
254         listenerSupport.add(listener, includeValues);
255     }
256 
257     @Override
258     public void removeListener(@Nonnull CacheEntryListener<K, V> listener)
259     {
260         listenerSupport.remove(listener);
261     }
262 
263     private class DelegatingCacheEventListener implements CacheEventListener
264     {
265         @Override
266         public void notifyElementRemoved(Ehcache ehcache, Element element) throws net.sf.ehcache.CacheException
267         {
268             listenerSupport.notifyRemove((K) element.getObjectKey(), (V) element.getObjectValue());
269         }
270 
271         @Override
272         public void notifyElementPut(Ehcache ehcache, Element element) throws net.sf.ehcache.CacheException
273         {
274             listenerSupport.notifyAdd((K) element.getObjectKey(), (V) element.getObjectValue());
275         }
276 
277         @Override
278         public void notifyElementUpdated(Ehcache ehcache, Element element) throws net.sf.ehcache.CacheException
279         {
280             listenerSupport.notifyUpdate((K) element.getObjectKey(), (V) element.getObjectValue(), null);
281         }
282 
283         @Override
284         public void notifyElementExpired(Ehcache ehcache, Element element)
285         {
286             listenerSupport.notifyEvict((K) element.getObjectKey(), (V) element.getObjectValue());
287         }
288 
289         @Override
290         public void notifyElementEvicted(Ehcache ehcache, Element element)
291         {
292             listenerSupport.notifyEvict((K) element.getObjectKey(), (V) element.getObjectValue());
293         }
294 
295         @Override
296         public void notifyRemoveAll(Ehcache ehcache)
297         {
298             // There is no way to enumerate the keys that were in the cache, therefore we cannot
299             // produce any meaningful event
300         }
301 
302         @Override
303         public void dispose()
304         {
305             // We don't hold onto any resources so there is nothing to be done.
306         }
307 
308         public Object clone() throws CloneNotSupportedException
309         {
310             throw new CloneNotSupportedException();
311         }
312     }
313 }