1 package com.atlassian.cache.ehcache;
2
3 import javax.annotation.Nonnull;
4 import javax.annotation.Nullable;
5 import javax.management.MBeanServer;
6
7 import com.atlassian.cache.CacheLoader;
8 import com.atlassian.cache.CacheSettings;
9 import com.atlassian.cache.CacheSettingsBuilder;
10 import com.atlassian.cache.CacheSettingsDefaultsProvider;
11 import com.atlassian.cache.CachedReference;
12 import com.atlassian.cache.ManagedCache;
13 import com.atlassian.cache.impl.AbstractCacheManager;
14 import com.atlassian.cache.impl.ReferenceKey;
15 import com.atlassian.cache.impl.StrongSupplier;
16 import com.atlassian.cache.impl.WeakSupplier;
17 import com.atlassian.cache.impl.jmx.MBeanRegistrar;
18 import com.atlassian.util.concurrent.Supplier;
19
20 import net.sf.ehcache.Ehcache;
21 import net.sf.ehcache.management.ManagementService;
22
23
24
25
26
27
28 public class EhCacheManager extends AbstractCacheManager implements MBeanRegistrar
29 {
30 private final net.sf.ehcache.CacheManager delegate;
31
32 private boolean statisticsEnabled = true;
33
34
35
36
37 public EhCacheManager()
38 {
39 this(net.sf.ehcache.CacheManager.create(), null);
40 }
41
42
43
44
45
46
47 public EhCacheManager(net.sf.ehcache.CacheManager delegate, CacheSettingsDefaultsProvider cacheSettingsDefaultsProvider)
48 {
49 super(cacheSettingsDefaultsProvider);
50
51 this.delegate = delegate;
52 }
53
54 net.sf.ehcache.CacheManager getEh()
55 {
56 return delegate;
57 }
58
59 public boolean isStatisticsEnabled()
60 {
61 return statisticsEnabled;
62 }
63
64 public void setStatisticsEnabled(final boolean statisticsEnabled)
65 {
66 this.statisticsEnabled = statisticsEnabled;
67 }
68
69 @Nonnull
70 @SuppressWarnings("unchecked")
71 @Override
72 public <V> CachedReference<V> getCachedReference(@Nonnull final String name,
73 @Nonnull final com.atlassian.cache.Supplier<V> supplier,
74 @Nonnull final CacheSettings settings)
75 {
76
77 final CacheSettings overridenSettings = settings.override(
78 new CacheSettingsBuilder().flushable().maxEntries(1).build());
79
80 return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<DelegatingCachedReference<V>>()
81 {
82 @Override
83 public DelegatingCachedReference<V> get()
84 {
85 Ehcache ehCache = getCleanCache(name, overridenSettings);
86 final Ehcache spCache = new LoadingCache<ReferenceKey,V>(ehCache, new SupplierAdapter<V>(supplier));
87 final DelegatingCachedReference<V> cache = DelegatingCachedReference.create(spCache, overridenSettings);
88 caches.put(name, new WeakSupplier<ManagedCache>(cache));
89 return cache;
90 }
91 });
92 }
93
94 @Override
95 protected ManagedCache createSimpleCache(@Nonnull final String name, @Nonnull final CacheSettings settings)
96 {
97 final Supplier<ManagedCache> cacheSupplier = caches.get(name);
98 if (cacheSupplier != null)
99 {
100 ManagedCache cache = cacheSupplier.get();
101 if (cache != null)
102 {
103 return cache;
104 }
105 }
106 return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<ManagedCache>()
107 {
108 @Override
109 public ManagedCache get()
110 {
111 if (!caches.containsKey(name))
112 {
113 final Ehcache simpleCache = createCache(name, settings, false);
114 DelegatingCache<?,?> cache = DelegatingCache.create(simpleCache, settings);
115 caches.put(name, new StrongSupplier<ManagedCache>(cache));
116 }
117 return caches.get(name).get();
118 }
119 });
120
121 }
122
123 @SuppressWarnings("unchecked")
124 protected <K, V> ManagedCache createComputingCache(@Nonnull final String name, @Nonnull final CacheSettings settings, final CacheLoader<K, V> loader)
125 {
126 return cacheCreationLocks.get(name).withLock(new com.atlassian.util.concurrent.Supplier<ManagedCache>()
127 {
128 @Override
129 public ManagedCache get()
130 {
131 Ehcache ehCache = getCleanCache(name, settings);
132
133 Ehcache spCache = new LoadingCache(ehCache, loader);
134 DelegatingCache<K,V> cache = DelegatingCache.create(spCache, settings);
135 caches.put(name, new WeakSupplier<ManagedCache>(cache));
136 return cache;
137 }
138 });
139 }
140
141 private Ehcache getCleanCache(final String name, final CacheSettings settings)
142 {
143
144
145
146
147
148 Ehcache ehCache = delegate.getCache(name);
149 if (ehCache != null)
150 {
151
152 ehCache.removeAll(true);
153 }
154 else
155 {
156 ehCache = createCache(name, settings, true);
157 }
158 return ehCache;
159 }
160
161 private Ehcache createCache(String name, CacheSettings settings, boolean selfLoading)
162 {
163 return new EhCacheHelper().getEhcache(name, delegate, settings, selfLoading, statisticsEnabled);
164 }
165
166 @Override
167 public void shutdown()
168 {
169
170 delegate.shutdown();
171 }
172
173 @Override
174 public void registerMBeans(@Nullable final MBeanServer mBeanServer)
175 {
176 if (mBeanServer != null)
177 {
178 ManagementService.registerMBeans(delegate, mBeanServer, true, true, true, true);
179 }
180 }
181
182 @Override
183 public void unregisterMBeans(@Nullable final MBeanServer mBeanServer)
184 {
185 if (mBeanServer != null)
186 {
187 final ManagementService managementService = new ManagementService(delegate, mBeanServer, true, true, true, true);
188 managementService.dispose();
189 }
190 }
191
192 static class SupplierAdapter<V> implements CacheLoader<ReferenceKey, V>
193 {
194 private final com.atlassian.cache.Supplier<V> supplier;
195
196 SupplierAdapter(com.atlassian.cache.Supplier<V> supplier)
197 {
198 this.supplier = supplier;
199 }
200
201 @Nonnull
202 @Override
203 public V load(@Nonnull ReferenceKey key)
204 {
205 return supplier.get();
206 }
207 }
208 }