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