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