View Javadoc

1   package com.atlassian.cache.impl;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.List;
6   import java.util.concurrent.ConcurrentHashMap;
7   import java.util.concurrent.ConcurrentMap;
8   
9   import javax.annotation.Nonnull;
10  import javax.annotation.Nullable;
11  
12  import com.atlassian.cache.Cache;
13  import com.atlassian.cache.CacheLoader;
14  import com.atlassian.cache.CacheManager;
15  import com.atlassian.cache.CacheSettings;
16  import com.atlassian.cache.CacheSettingsBuilder;
17  import com.atlassian.cache.CacheSettingsDefaultsProvider;
18  import com.atlassian.cache.CachedReference;
19  import com.atlassian.cache.ManagedCache;
20  import com.atlassian.util.concurrent.Function;
21  import com.atlassian.util.concurrent.ManagedLock;
22  import com.atlassian.util.concurrent.ManagedLocks;
23  import com.atlassian.util.concurrent.Supplier;
24  
25  import static com.google.common.base.Preconditions.checkNotNull;
26  
27  /**
28   * A partial implementation of {@link CacheManager}.
29   *
30   * @since 2.0.6
31   */
32  public abstract class AbstractCacheManager implements CacheManager
33  {
34  
35      /**
36       * Map of all the caches.
37       * Before creating a cache to put into the map, acquire a lock using {@link #cacheCreationLocks}
38       * to ensure that a cache is created only once.
39       */
40      protected final ConcurrentMap<String, Supplier<ManagedCache>> caches = new ConcurrentHashMap<String, Supplier<ManagedCache>>();
41  
42      /** Used to synchronize the creation of caches. */
43      protected final Function<String, ManagedLock> cacheCreationLocks = ManagedLocks.weakManagedLockFactory();
44  
45      protected final CacheSettingsDefaultsProvider cacheSettingsDefaultsProvider;
46  
47      protected AbstractCacheManager(CacheSettingsDefaultsProvider cacheSettingsDefaultsProvider)
48      {
49          this.cacheSettingsDefaultsProvider = cacheSettingsDefaultsProvider;
50      }
51  
52      @Nonnull
53      @SuppressWarnings("unchecked")
54      @Override
55      public Collection<Cache<?, ?>> getCaches()
56      {
57          List<Cache<?, ?>> managedCaches = new ArrayList<Cache<?, ?>>(64);
58  
59          for (final com.atlassian.util.concurrent.Supplier<ManagedCache> cacheRef : caches.values())
60          {
61              final ManagedCache managedCache = cacheRef.get();
62              // Only return instances of Cache. Do not return CachedReference instances
63              if (managedCache instanceof Cache)
64              {
65                  managedCaches.add((Cache<?,?>)managedCache);
66              }
67          }
68          return managedCaches;
69      }
70  
71      @Nonnull
72      @Override
73      public Collection<ManagedCache> getManagedCaches()
74      {
75          List<ManagedCache> managedCaches = new ArrayList<ManagedCache>(64);
76          for (final com.atlassian.util.concurrent.Supplier<ManagedCache> cacheRef : caches.values())
77          {
78              final ManagedCache managedCache = cacheRef.get();
79              if (managedCache != null)
80              {
81                  managedCaches.add(managedCache);
82              }
83          }
84          return managedCaches;
85      }
86  
87      @Nullable
88      @Override
89      public ManagedCache getManagedCache(@Nonnull String name)
90      {
91          final Supplier<ManagedCache> cacheRef = caches.get(name);
92          return (null == cacheRef) ? null : cacheRef.get();
93      }
94  
95      @Override
96      public void flushCaches()
97      {
98          for (final com.atlassian.util.concurrent.Supplier<ManagedCache> cacheRef : caches.values())
99          {
100             final ManagedCache managedCache = cacheRef.get();
101             if (managedCache != null && managedCache.isFlushable())
102             {
103                 managedCache.clear();
104             }
105         }
106     }
107 
108     @Nonnull
109     @Override
110     public <K, V> Cache<K, V> getCache(@Nonnull final String name)
111     {
112         return getCache(name, null);
113     }
114 
115     @Nonnull
116     @Override
117     public <K, V> Cache<K, V> getCache(@Nonnull Class<?> owningClass, @Nonnull String name)
118     {
119         return getCache(cacheName(owningClass, name));
120     }
121 
122     @Nonnull
123     @Override
124     public <K, V> Cache<K, V> getCache(@Nonnull final String name, @Nonnull final Class<K> keyType, @Nonnull final Class<V> valueType)
125     {
126         return getCache(name);
127     }
128 
129     @Nonnull
130     @Override
131     public <K, V> Cache<K, V> getCache(@Nonnull String name, CacheLoader<K, V> loader)
132     {
133         return getCache(name, loader, new CacheSettingsBuilder().build());
134     }
135 
136     @Nonnull
137     @Override
138     public <V> CachedReference<V> getCachedReference(@Nonnull String name, @Nonnull com.atlassian.cache.Supplier<V> supplier)
139     {
140         return getCachedReference(name, supplier, new CacheSettingsBuilder().build());
141     }
142 
143     @Nonnull
144     @Override
145     public <V> CachedReference<V> getCachedReference(@Nonnull Class<?> owningClass,
146                                                      @Nonnull String name,
147                                                      @Nonnull com.atlassian.cache.Supplier<V> supplier)
148     {
149         return getCachedReference(owningClass, name, supplier, new CacheSettingsBuilder().build());
150     }
151 
152     @Nonnull
153     @Override
154     public <V> CachedReference<V> getCachedReference(@Nonnull Class<?> owningClass,
155                                                      @Nonnull String name,
156                                                      @Nonnull com.atlassian.cache.Supplier<V> supplier,
157                                                      @Nonnull CacheSettings settings)
158     {
159         return getCachedReference(cacheName(owningClass, name), supplier, settings);
160     }
161 
162     private static String cacheName(Class<?> owningClass, String name)
163     {
164         checkNotNull(name, "name cannot be null");
165         return owningClass.getName() + '.' + name;
166     }
167 
168     @Nonnull
169     @SuppressWarnings("unchecked")
170     @Override
171     public <K, V> Cache<K, V> getCache(@Nonnull String name, CacheLoader<K, V> loader, @Nonnull CacheSettings settings)
172     {
173         if (null == loader)
174         {
175             return (Cache<K, V>) createSimpleCache(name, mergeSettings(name, settings));
176         }
177         else
178         {
179             return (Cache<K, V>) createComputingCache(name, mergeSettings(name, settings), loader);
180         }
181     }
182 
183     /**
184      * Creates a cache that upon a miss is able to populate itself using the loader.
185      *
186      * @return a non-null cache
187      */
188     protected abstract <K, V> ManagedCache createComputingCache(@Nonnull String name, @Nonnull CacheSettings settings, CacheLoader<K, V> loader);
189 
190     /**
191      * Creates a cache with no loader, i.e. one populated via explicit puts.
192      *
193      * @param name the name to give the cache (required)
194      * @return a non-null cache
195      */
196     protected abstract ManagedCache createSimpleCache(@Nonnull String name, @Nonnull CacheSettings settings);
197 
198     protected CacheSettings mergeSettings(String name, CacheSettings settings)
199     {
200         if (cacheSettingsDefaultsProvider == null)
201         {
202             return settings;
203         }
204 
205         return cacheSettingsDefaultsProvider.getDefaults(name).override(settings);
206     }
207 
208     @Override
209     public void shutdown()
210     {
211         //By default cacheManages does not have to implements the shutdown method.
212     }
213 }