View Javadoc

1   package com.atlassian.plugin.manager;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   import com.atlassian.plugin.PluginAccessor;
5   import com.atlassian.plugin.event.PluginEventListener;
6   import com.atlassian.plugin.event.PluginEventManager;
7   import com.atlassian.plugin.event.events.PluginDisabledEvent;
8   import com.atlassian.plugin.tracker.PluginModuleTracker;
9   import com.atlassian.plugin.cache.ConcurrentCacheFactory;
10  import com.google.common.base.Function;
11  import com.google.common.cache.Cache;
12  import com.google.common.cache.CacheBuilder;
13  import com.google.common.cache.CacheLoader;
14  
15  import java.util.List;
16  
17  import static com.atlassian.plugin.tracker.DefaultPluginModuleTracker.create;
18  import static com.google.common.base.Preconditions.checkNotNull;
19  import static com.google.common.collect.ImmutableList.copyOf;
20  
21  /**
22   * A caching decorator which caches {@link #getEnabledModuleDescriptorsByClass(Class)} on {@link com.atlassian.plugin.PluginAccessor} interface.
23   *
24   * @since 2.7.0
25   */
26  public final class EnabledModuleCachingPluginAccessor extends ForwardingPluginAccessor implements PluginAccessor
27  {
28      private final PluginEventManager pluginEventManager;
29      private final Cache<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>> cache;
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          this.cache = new DefaultPluginModuleTrackerCacheFactory().createCache();
37      }
38  
39      public EnabledModuleCachingPluginAccessor(final PluginAccessor delegate, final PluginEventManager pluginEventManager, final ConcurrentCacheFactory<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>> pluginModuleTrackerCacheFactory)
40      {
41          super(delegate);
42          this.pluginEventManager = checkNotNull(pluginEventManager);
43          this.pluginEventManager.register(this);
44          this.cache = pluginModuleTrackerCacheFactory.createCache();
45      }
46  
47  
48      @Override
49      public <D extends ModuleDescriptor<?>> List<D> getEnabledModuleDescriptorsByClass(final Class<D> descriptorClazz)
50      {
51          return copyOf(descriptors(descriptorClazz));
52      }
53  
54      /**
55       * Clears the enabled module cache when any plugin is disabled.  The cache already has weak keys and values, but this
56       * ensures old modules are never returned from disabled plugins.
57       *
58       * @param event The plugin disabled event
59       */
60      @PluginEventListener
61      public void onPluginDisable(PluginDisabledEvent event)
62      {
63          cache.invalidateAll();
64      }
65  
66      /**
67       * Cache implementation.
68       */
69      @SuppressWarnings("unchecked")
70      <D> Iterable<D> descriptors(final Class<D> moduleDescriptorClass)
71      {
72          PluginModuleTracker<Object, ModuleDescriptor<Object>> tracker = cache.getUnchecked((Class<ModuleDescriptor<Object>>) moduleDescriptorClass);
73          return (Iterable<D>) tracker.getModuleDescriptors();
74      }
75  
76      private class DefaultPluginModuleTrackerCacheFactory implements ConcurrentCacheFactory<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>>
77      {
78          @Override
79          public Cache<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>> createCache()
80          {
81              return CacheBuilder.newBuilder().weakKeys().weakValues().build(CacheLoader.from(new PluginModuleTrackerFactory()));
82          }
83      }
84  
85      private class PluginModuleTrackerFactory implements Function<Class<ModuleDescriptor<Object>>, PluginModuleTracker<Object, ModuleDescriptor<Object>>>
86      {
87          public PluginModuleTracker<Object, ModuleDescriptor<Object>> apply(final Class<ModuleDescriptor<Object>> moduleDescriptorClass)
88          {
89              return create(delegate, pluginEventManager, moduleDescriptorClass);
90          }
91      }
92  }