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
26
27
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
299
300 }
301
302 @Override
303 public void dispose()
304 {
305
306 }
307
308 public Object clone() throws CloneNotSupportedException
309 {
310 throw new CloneNotSupportedException();
311 }
312 }
313 }