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