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