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