View Javadoc

1   package com.atlassian.plugin.manager;
2   
3   import java.util.Collection;
4   import java.util.Date;
5   import java.util.concurrent.atomic.AtomicInteger;
6   
7   import com.atlassian.plugin.Plugin;
8   import com.atlassian.plugin.PluginArtifact;
9   import com.atlassian.plugin.PluginArtifactBackedPlugin;
10  import com.atlassian.plugin.PluginInformation;
11  import com.atlassian.plugin.jmx.AbstractJmxBridge;
12  import com.atlassian.plugin.jmx.JmxUtil;
13  import com.atlassian.plugin.jmx.PluginManagerMXBean;
14  
15  import com.google.common.base.Function;
16  
17  import static com.google.common.collect.Iterables.toArray;
18  import static com.google.common.collect.Iterables.transform;
19  
20  /**
21   * Expose a {@link DefaultPluginManager} as a JMX {@link PluginManagerMXBean}.
22   * <p/>
23   * This implementation has concurrency issues, because it traverses unprotected data structures. It does not update them (except
24   * where such problems already exist, such as in {@link DefaultPluginManager#scanForNewPlugins()}, so the likely fall out here is
25   * simply a failed request. We should address this when we have a firm plan to managing asynchrony in the plugin system generally.
26   * Replacing the collections here with snapshots is really just going to shrink the race window a little and not close it, and
27   * doesn't feel worth the effort unless it causes problems in expected usage.
28   *
29   * @since v3.0.24
30   */
31  class DefaultPluginManagerJmxBridge extends AbstractJmxBridge<PluginManagerMXBean> implements PluginManagerMXBean
32  {
33      /**
34       * Counter for uniqueifying jmx object names, since we have no uniqueness in our scope to fall back on.
35       */
36      private static final AtomicInteger nextJmxInstance = new AtomicInteger();
37  
38      private final DefaultPluginManager defaultPluginManager;
39  
40      DefaultPluginManagerJmxBridge(final DefaultPluginManager defaultPluginManager)
41      {
42          super(JmxUtil.objectName(nextJmxInstance, "PluginManager"), PluginManagerMXBean.class);
43          this.defaultPluginManager = defaultPluginManager;
44      }
45  
46      @Override
47      protected PluginManagerMXBean getMXBean()
48      {
49          return this;
50      }
51  
52      @Override
53      public PluginData[] getPlugins()
54      {
55          final Collection<Plugin> plugins = defaultPluginManager.getPlugins();
56          final Iterable<PluginData> pluginDatas = transform(plugins, new Function<Plugin, PluginData>()
57          {
58              @Override
59              public PluginData apply(final Plugin plugin)
60              {
61                  return new PluginData()
62                  {
63                      @Override
64                      public String getKey()
65                      {
66                          return plugin.getKey();
67                      }
68  
69                      @Override
70                      public String getVersion()
71                      {
72                          final PluginInformation pluginInformation = plugin.getPluginInformation();
73                          // It's unclear whether getPluginInformation can return null, but it is handled in a few places (such as
74                          // version comparison code), so i'm being defensive about it here.
75                          return (null == pluginInformation) ? null : pluginInformation.getVersion();
76                      }
77  
78                      @Override
79                      public String getLocation()
80                      {
81                          if (!(plugin instanceof PluginArtifactBackedPlugin))
82                          {
83                              return null;
84                          }
85  
86                          final PluginArtifact pluginArtifact = ((PluginArtifactBackedPlugin) plugin).getPluginArtifact();
87  
88                          return (null == pluginArtifact) ? null : pluginArtifact.toFile().getAbsolutePath();
89                      }
90  
91                      @Override
92                      public Long getDateLoaded()
93                      {
94                          final Date dateLoaded = plugin.getDateLoaded();
95  
96                          return (null == dateLoaded) ? null : dateLoaded.getTime();
97                      }
98  
99                      @Override
100                     public Long getDateInstalled()
101                     {
102                         final Date dateInstalled = plugin.getDateInstalled();
103 
104                         return (null == dateInstalled) ? null : dateInstalled.getTime();
105                     }
106 
107                     @Override
108                     public boolean isEnabled()
109                     {
110                         return defaultPluginManager.isPluginEnabled(plugin.getKey());
111                     }
112 
113                     @Override
114                     public boolean isEnabledByDefault()
115                     {
116                         return plugin.isEnabledByDefault();
117                     }
118 
119                     @Override
120                     public boolean isBundledPlugin()
121                     {
122                         return plugin.isBundledPlugin();
123                     }
124                 };
125             }
126         });
127         return toArray(pluginDatas, PluginData.class);
128     }
129 
130     @Override
131     public int scanForNewPlugins()
132     {
133         return defaultPluginManager.scanForNewPlugins();
134     }
135 }