View Javadoc
1   package com.atlassian.plugin.metadata;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   import com.atlassian.plugin.Plugin;
5   import com.atlassian.plugin.descriptors.CannotDisable;
6   
7   import javax.annotation.concurrent.Immutable;
8   
9   import static com.google.common.base.Preconditions.checkNotNull;
10  
11  /**
12   * A default implementation that uses the {@link com.atlassian.plugin.metadata.ClasspathFilePluginMetadata}
13   * plugin metadata implementation to resolve the application provided plugin metadata.
14   *
15   * @since 2.6
16   */
17  @Immutable
18  public final class DefaultPluginMetadataManager implements PluginMetadataManager {
19      private final PluginMetadata metadata;
20  
21      /**
22       * Production ctor. Loads from the class path.
23       */
24      public DefaultPluginMetadataManager() {
25          this(new ClasspathFilePluginMetadata());
26      }
27  
28      /**
29       * Test ctor.
30       */
31      DefaultPluginMetadataManager(final PluginMetadata metadata) {
32          this.metadata = checkNotNull(metadata, "metadata");
33      }
34  
35      /**
36       * A plugin is determined to be non-user if
37       * {@link com.atlassian.plugin.Plugin#isBundledPlugin()} is true or if the
38       * host application has indicated to the plugins system that a plugin was
39       * provided by it.
40       * <p>
41       * <strong>NOTE:</strong> If a user has upgraded a bundled plugin then the
42       * decision of whether it is user installed plugin is determined by if the
43       * application has indicated to the plugins system that a plugin was
44       * provided or not.
45       */
46      public boolean isUserInstalled(final Plugin plugin) {
47          checkNotNull(plugin, "plugin");
48          // It is user installed if it has not been marked as provided by the
49          // application and it was not bundled.
50          return !plugin.isBundledPlugin() && !metadata.applicationProvided(plugin);
51      }
52  
53      /**
54       * A plugin is determined to be &quot;system&quot; if
55       * {@link #isUserInstalled(com.atlassian.plugin.Plugin)} is false.
56       */
57      public boolean isSystemProvided(Plugin plugin) {
58          return !isUserInstalled(plugin);
59      }
60  
61      /**
62       * A plugin is determined to be optional if the host application has not
63       * indicated to the plugins system that it is required or if any of its
64       * modules have been flagged as not optional.
65       */
66      public boolean isOptional(final Plugin plugin) {
67          checkNotNull(plugin, "plugin");
68          // If the application has marked the plugin as required then we know we
69          // are required
70          if (!optionalAccordingToHostApplication(plugin)) {
71              return false;
72          }
73  
74          // We need to check if any of the plugins modules are not optional
75          for (final ModuleDescriptor<?> moduleDescriptor : plugin.getModuleDescriptors()) {
76              if (!optionalAccordingToHostApplication(moduleDescriptor)) {
77                  return false;
78              }
79          }
80          return true;
81      }
82  
83      /**
84       * A module is determined to be optional if the host application has not
85       * indicated to the plugins system that it is required. If the call to
86       * {@code isOptional} with the module descriptor's plugin is {@code false},
87       * then this method will also return {@code false}. Also if the module
88       * descriptor is annotated with
89       * {@link com.atlassian.plugin.descriptors.CannotDisable} then it can not be
90       * optional.
91       */
92      public boolean isOptional(final ModuleDescriptor<?> moduleDescriptor) {
93          checkNotNull(moduleDescriptor, "moduleDescriptor");
94          // It is not optional if the host application has marked it as required
95          if (!optionalAccordingToHostApplication(moduleDescriptor)) {
96              return false;
97          }
98  
99          // A module can not be optional if it is marked
100         // by the CannotDisable annotation
101         if (!optionalAccordingToModuleDescriptorType(moduleDescriptor)) {
102             return false;
103         }
104 
105         // A module can only be optional if its parent plugin is not declared by
106         // the host application as required
107         return optionalAccordingToHostApplication(moduleDescriptor.getPlugin());
108     }
109 
110     private boolean optionalAccordingToHostApplication(final Plugin plugin) {
111         return !metadata.required(plugin);
112     }
113 
114     private boolean optionalAccordingToHostApplication(final ModuleDescriptor<?> moduleDescriptor) {
115         return !metadata.required(moduleDescriptor);
116     }
117 
118     private boolean optionalAccordingToModuleDescriptorType(final ModuleDescriptor<?> moduleDescriptor) {
119         return !moduleDescriptor.getClass().isAnnotationPresent(CannotDisable.class);
120     }
121 }