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