View Javadoc

1   package com.atlassian.plugin.util;
2   
3   import com.atlassian.plugin.Application;
4   import com.atlassian.plugin.ModuleDescriptor;
5   import com.atlassian.plugin.Plugin;
6   import com.atlassian.plugin.descriptors.RequiresRestart;
7   import com.google.common.base.Function;
8   import com.google.common.base.Joiner;
9   import com.google.common.base.Objects;
10  import com.google.common.collect.Iterables;
11  import org.apache.commons.lang.Validate;
12  import org.dom4j.Element;
13  import org.slf4j.Logger;
14  import org.slf4j.LoggerFactory;
15  
16  import javax.annotation.Nullable;
17  import java.util.HashSet;
18  import java.util.Set;
19  
20  import static com.google.common.base.Preconditions.checkNotNull;
21  
22  /**
23   * General plugin utility methods
24   *
25   * @since 2.1
26   */
27  public class PluginUtils
28  {
29      private static final Logger logger = LoggerFactory.getLogger(PluginUtils.class);
30  
31      public static final String ATLASSIAN_DEV_MODE = "atlassian.dev.mode";
32  
33      /**
34       * System property for storing and retrieving the time the plugin system will wait for the enabling of a plugin in
35       * seconds
36       *
37       * @since 2.3.6
38       */
39      public static final String ATLASSIAN_PLUGINS_ENABLE_WAIT = "atlassian.plugins.enable.wait";
40  
41      /**
42       * Used to customise the size of the LRU cache for batch web resources.
43       * This effectively controls how many files will be created
44       * by the file cache. Providing a negative number results in undefined behaviour.
45       *
46       * @since 2.13.0
47       */
48      public static final String WEBRESOURCE_FILE_CACHE_SIZE = new String("atlassian.webresource.file.cache.size");
49  
50      /**
51       * Used to disable the file cache should that be desired. Setting this value to true will disable the
52       * file caching completely for all places it is used.
53       *
54       * @since 2.13.0
55       */
56      public static final String WEBRESOURCE_DISABLE_FILE_CACHE = new String("atlassian.webresource.file.cache.disable");
57  
58  
59      /**
60       * Determines if a plugin requires a restart after being installed at runtime.  Looks for the annotation
61       * {@link RequiresRestart} on the plugin's module descriptors.
62       *
63       * @param plugin The plugin that was just installed at runtime, but not yet enabled
64       * @return True if a restart is required
65       * @since 2.1
66       */
67      public static boolean doesPluginRequireRestart(final Plugin plugin)
68      {
69          //PLUG-451: When in dev mode, plugins should not require a restart.
70          if (Boolean.getBoolean(ATLASSIAN_DEV_MODE))
71          {
72              return false;
73          }
74  
75          for (final ModuleDescriptor<?> descriptor : plugin.getModuleDescriptors())
76          {
77              if (descriptor.getClass().getAnnotation(RequiresRestart.class) != null)
78              {
79                  return true;
80              }
81          }
82          return false;
83      }
84  
85      /**
86       * Gets a list of all the module keys in a plugin that require restart.  Looks for the annotation
87       * {@link RequiresRestart} on the plugin's module descriptors.
88       *
89       * @param plugin The plugin
90       * @return A unique set of module keys
91       * @since 2.5.0
92       */
93      public static Set<String> getPluginModulesThatRequireRestart(final Plugin plugin)
94      {
95          Set<String> keys = new HashSet<String>();
96          for (final ModuleDescriptor<?> descriptor : plugin.getModuleDescriptors())
97          {
98              if (descriptor.getClass().getAnnotation(RequiresRestart.class) != null)
99              {
100                 keys.add(descriptor.getKey());
101             }
102         }
103         return keys;
104     }
105 
106     /**
107      * Determines if a module element applies to the current application by matching the 'application' attribute
108      * to the set of applications.  If the application is specified, but isn't in the set, we return false
109      *
110      * @param element The module element
111      * @param applications The set of application applications
112      * @return True if it should apply, false otherwise
113      * @since 2.2.0
114      */
115     public static boolean doesModuleElementApplyToApplication(Element element, Set<Application> applications)
116     {
117         Validate.notNull(applications);
118         Validate.notNull(element);
119 
120         final ModuleRestricts restricts = ModuleRestricts.parse(element);
121         final boolean valid = restricts.isValidFor(applications);
122         if (!valid)
123         {
124             logger.debug("Module '{}' with key '{}' is restricted to the following " +
125                     "applications {} and therefore does not apply to applications {}",
126                     new Object[]{
127                             element.getName(),
128                             element.attributeValue("key"),
129                             restricts,
130                             asString(applications)
131                     });
132         }
133         return valid;
134     }
135 
136     private static String asString(Set<Application> applications)
137     {
138         return "[" + Joiner.on(",").join(Iterables.transform(applications, new Function<Application, String>()
139         {
140             @Override
141             public String apply(Application app)
142             {
143                 return Objects.toStringHelper(app.getKey())
144                         .add("version", app.getVersion())
145                         .add("build", app.getBuildNumber())
146                         .toString();
147             }
148         })) + "]";
149     }
150 
151     /**
152      * @return The default enabling waiting period in seconds
153      * @since 2.3.6
154      */
155     public static int getDefaultEnablingWaitPeriod()
156     {
157         return Integer.parseInt(System.getProperty(ATLASSIAN_PLUGINS_ENABLE_WAIT, "60"));
158     }
159 }