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