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