View Javadoc

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