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