View Javadoc

1   package com.atlassian.plugin.manager;
2   
3   import static com.atlassian.plugin.tracker.DefaultPluginModuleTracker.create;
4   import static com.google.common.base.Preconditions.checkNotNull;
5   import static com.google.common.collect.ImmutableList.copyOf;
6   
7   import com.atlassian.plugin.ModuleDescriptor;
8   import com.atlassian.plugin.PluginAccessor;
9   import com.atlassian.plugin.event.PluginEventListener;
10  import com.atlassian.plugin.event.PluginEventManager;
11  import com.atlassian.plugin.event.events.PluginDisabledEvent;
12  import com.atlassian.plugin.tracker.PluginModuleTracker;
13  
14  import com.google.common.base.Function;
15  import com.google.common.collect.MapMaker;
16  
17  import java.util.List;
18  import java.util.concurrent.ConcurrentMap;
19  
20  /**
21   * A caching decorator which caches {@link #getEnabledModuleDescriptorsByClass(Class)} on {@link com.atlassian.plugin.PluginAccessor} interface.
22   *
23   * @since 2.7.0
24   */
25  public final class EnabledModuleCachingPluginAccessor extends ForwardingPluginAccessor implements PluginAccessor
26  {
27      private final PluginEventManager pluginEventManager;
28      private final ConcurrentMap<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>> cache = new MapMaker()
29              .weakKeys().weakValues().makeComputingMap(new PluginModuleTrackerFactory());
30  
31      public EnabledModuleCachingPluginAccessor(final PluginAccessor delegate, final PluginEventManager pluginEventManager)
32      {
33          super(delegate);
34          this.pluginEventManager = checkNotNull(pluginEventManager);
35          this.pluginEventManager.register(this);
36      }
37  
38      @Override
39      public <D extends ModuleDescriptor<?>> List<D> getEnabledModuleDescriptorsByClass(final Class<D> descriptorClazz)
40      {
41          return copyOf(descriptors(descriptorClazz));
42      }
43  
44      /**
45       * Clears the enabled module cache when any plugin is disabled.  The cache already has weak keys and values, but this
46       * ensures old modules are never returned from disabled plugins.
47       *
48       * @param event The plugin disabled event
49       */
50      @PluginEventListener
51      public void onPluginDisable(PluginDisabledEvent event)
52      {
53          cache.clear();
54      }
55  
56      /**
57       * Cache implementation.
58       */
59      <D> Iterable<D> descriptors(final Class<D> moduleDescriptorClass)
60      {
61          @SuppressWarnings("unchecked")
62          final Iterable<D> descriptors = (Iterable<D>) cache.get(moduleDescriptorClass).getModuleDescriptors();
63          return descriptors;
64      }
65  
66      final class PluginModuleTrackerFactory implements Function<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>>
67      {
68          public PluginModuleTracker<Object, ModuleDescriptor<Object>> apply(final Class<ModuleDescriptor<Object>> moduleDescriptorClass)
69          {
70              return create(delegate, pluginEventManager, moduleDescriptorClass);
71          }
72      }
73  }