View Javadoc

1   package com.atlassian.plugin;
2   
3   import java.io.InputStream;
4   import java.net.URL;
5   import java.util.*;
6   
7   import javax.annotation.Nullable;
8   
9   import com.atlassian.annotations.ExperimentalApi;
10  
11  public interface Plugin extends Resourced, Comparable<Plugin>
12  {
13      /**
14       * This is the historical version of plugins. Which is mostly static plugins loaded from the same classpath to the
15       * application.
16       */
17      static final int VERSION_1 = 1;
18  
19      /**
20       * This is the version of plugins which introduced dynamic plugins for all. Based on OSGi and Spring DM. Those plugins
21       * undergo some transformations to make the plugin artifact compatible with the OSGi + Spring DM container.
22       */
23      static final int VERSION_2 = 2;
24  
25      /**
26       * This is the versions of plugins that adds remotes plugins (developed outside of the plugin framework itself).
27       * Plugins version 3 don't undergo any transformation so it is up to the plugin developer to write their own Spring
28       * configuration files if this is their chosen framework, but other frameworks can be introduced.
29       */
30      static final int VERSION_3 = 3;
31  
32      /**
33       * @deprecated since 2.2.0.  This comparator only takes into account the plugin name and assumes it is not null,
34       * yet a) that constraint is not validated anywhere in plugin loading and b) the plugin could have used the i18n
35       * name, and only the application can resolve that to a name useful for comparisons.
36       */
37      public static final Comparator<Plugin> NAME_COMPARATOR = new PluginNameComparator();
38  
39      /**
40       * Gets the version of the plugins system to handle this plugin
41       * @return The plugins version.  If undefined, assumed to be 1.
42       */
43      int getPluginsVersion();
44  
45      /**
46       * Sets the version of the plugins system
47       * @param version The version
48       */
49      void setPluginsVersion(int version);
50  
51      /**
52       * Returns the non-localised name of this plugin if defined.
53       *
54       * <p> This corresponds to the value of the {@code name} field in the plugin's XML configuration file.
55       *
56       * <p> You would expect a plugin developer to fill in one of either {@code name}, or {@code i18n-name-key}, 
57       * but the framework does no validation and makes no guarantees that this is the case.
58       *
59       * @return the non-localised name of this plugin if defined, or null.
60       * @see #getI18nNameKey()
61       */
62      String getName();
63  
64      /**
65       * Sets the non-localised name of this plugin.
66       *
67       * @param name the name.
68       * @see #getName()
69       */
70      void setName(String name);
71  
72      /**
73       * Returns the i18nKey used to get an internationalised name for this plugin.
74       *
75       * <p> This corresponds to the value of the {@code i18n-name-key} field in the plugin's XML configuration file.
76       *
77       * <p> You would expect a plugin developer to fill in one of either {@code name}, or {@code i18n-name-key},
78       * but the framework does no validation and makes no guarantees that this is the case.
79       *
80       * @return the i18n Name Key for this plugin if defined, or null.
81       * @see #getName()
82       */
83      String getI18nNameKey();
84  
85      /**
86       * Sets the i18nKey used to get an internationalised name for this plugin.
87       *
88       * @param i18nNameKey the i18n Name Key.
89       * @see #getI18nNameKey()
90       */
91      void setI18nNameKey(String i18nNameKey);
92  
93      String getKey();
94  
95      void setKey(String aPackage);
96  
97      void addModuleDescriptor(ModuleDescriptor<?> moduleDescriptor);
98  
99      /**
100      * Get the {@link Collection} of {@link ModuleDescriptor descriptors}.
101      *
102      * <p> The iteration order of the collection is
103      * the order that the modules will be enabled, and should be the same order that the modules appear in the
104      * plugin descriptor.
105      *
106      * @return the modules contained by this plugin in the order they are to be enabled
107      */
108     Collection<ModuleDescriptor<?>> getModuleDescriptors();
109 
110     /**
111      * Get the {@link ModuleDescriptor} for a particular key. Returns <tt>null</tt> if the plugin does not exist.
112      * <p>
113      * Note: The {@link ModuleDescriptor#getModule()} may throw {@link ClassCastException} if the expected type is incorrect.
114      *
115      * @param key the {@link String} complete key of the module, in the form "org.example.plugin:module-key".
116      * @return the {@link ModuleDescriptor} of the expected type.
117      */
118     ModuleDescriptor<?> getModuleDescriptor(String key);
119 
120     /**
121      * Get the {@link ModuleDescriptor descriptors} whose module class implements or is assignable from the supplied {@link Class}.
122      * <p>
123      * Note: The {@link ModuleDescriptor#getModule()} may throw {@link ClassCastException} if the expected type is incorrect.
124      * Normally this method would not be supplied with anything other than {@link Object} or &lt;?&gt;, unless you are
125      * confident in the super type of the module classes this {@link Plugin} provides.
126      *
127      * @param <M> The expected module type of the returned {@link ModuleDescriptor descriptors}.
128      * @param moduleClass the {@link Class super class} the {@link ModuleDescriptor descriptors} return.
129      * @return the {@link List} of {@link ModuleDescriptor descriptors} of the expected type.
130      */
131     <M> List<ModuleDescriptor<M>> getModuleDescriptorsByModuleClass(Class<M> moduleClass);
132 
133     /**
134      * Gets the installation mode
135      * @return the plugin's installation mode, local or remote.
136      *
137      * @since 3.0
138      */
139     InstallationMode getInstallationMode();
140 
141     boolean isEnabledByDefault();
142 
143     void setEnabledByDefault(boolean enabledByDefault);
144 
145     PluginInformation getPluginInformation();
146 
147     void setPluginInformation(PluginInformation pluginInformation);
148 
149     void setResources(Resourced resources);
150 
151     /**
152      * Returns this plugin's current state.
153      *
154      * @return the current state of the plugin.
155      * @since 2.2.0
156      */
157     PluginState getPluginState();
158 
159     /**
160      * @deprecated since 2.2.0, use {@link #getPluginState()} instead
161      * @return {@code true} if this plugin is enabled.
162      */
163     boolean isEnabled();
164 
165 
166     /**
167      * Whether the plugin is a "system" plugin that shouldn't be made visible to the user.
168      *
169      * @return {@code true} if this plugin is a "system" plugin.
170      * @deprecated since 2.6.0 use {@link com.atlassian.plugin.metadata.PluginMetadataManager#isSystemProvided(Plugin)}}
171      * instead.
172      */
173     boolean isSystemPlugin();
174 
175     /**
176      * @param system whether the plugin is a "system" plugin that shouldn't be made visible to the user.
177      * @deprecated since 2.6.0 provide {@link com.atlassian.plugin.metadata.PluginMetadataManager} with information about the
178      * plugin instead. There is no way to programatically set this value now.
179      */
180     void setSystemPlugin(boolean system);
181 
182     boolean containsSystemModule();
183 
184     /**
185      * Whether the plugin is a "bundled" plugin that can't be removed.
186      *
187      * @return {@code true} if this plugin is a "bundled" plugin.
188      */
189     boolean isBundledPlugin();
190 
191     /**
192      * The date this plugin was loaded into the system.
193      *
194      * @return The date this plugin was loaded into the system.
195      */
196     Date getDateLoaded();
197 
198 
199     /**
200      * The date this plugin was installed into the system, is the same as the loaded date for non artifact backed plugins
201      *
202      * @return  The date this plugin was installed into the system
203      * @since 3.0.0
204      */
205     Date getDateInstalled();
206 
207     /**
208      * Whether or not this plugin can be 'uninstalled'.
209      *
210      * @return {@code true} if this plugin can be 'uninstalled'.
211      */
212     boolean isUninstallable();
213 
214     /**
215      * Should the plugin file be deleted on unistall?
216      *
217      * @return {@code true} if this plugin file should be deleted on unistall.
218      */
219     boolean isDeleteable();
220 
221     /**
222      * Whether or not this plugin is loaded dynamically at runtime.
223      *
224      * @return {@code true} if this plugin is loaded dynamically at runtime.
225      */
226     boolean isDynamicallyLoaded();
227 
228     /**
229      * Get the plugin to load a specific class.
230      *
231      * @param clazz        The name of the class to be loaded
232      * @param callingClass The class calling the loading (used to help find a classloader)
233      * @return The loaded class.
234      * @throws ClassNotFoundException if the class cannot be located.
235      */
236     <T> Class<T> loadClass(String clazz, Class<?> callingClass) throws ClassNotFoundException;
237 
238     /**
239      * Get the classloader for the plugin.
240      *
241      * @return The classloader used to load classes for this plugin
242      */
243     ClassLoader getClassLoader();
244 
245     /**
246      * Retrieve the URL of the resource from the plugin.
247      *
248      * @param path the name of the resource to be loaded
249      * @return The URL to the resource, or null if the resource is not found
250      */
251     URL getResource(String path);
252 
253     /**
254      * Load a given resource from the plugin. Plugins that are loaded dynamically will need
255      * to implement this in a way that loads the resource from the same context as the plugin.
256      * Static plugins can just pull them from their own classloader.
257      *
258      * @param name The name of the resource to be loaded.
259      * @return An InputStream for the resource, or null if the resource is not found.
260      */
261     InputStream getResourceAsStream(String name);
262 
263     /**
264      * @param enabled new enabled state
265      * @deprecated Since 2.2.0, use {@link #enable()} or {@link #disable()} instead
266      */
267     void setEnabled(boolean enabled);
268 
269     /**
270      * Free any resources held by this plugin.  To be called during uninstallation of the {@link Plugin}.
271      * @deprecated Since 2.2.0, use {@link #uninstall()} instead
272      */
273     void close();
274 
275     /**
276      * Installs the plugin into any internal, managing container.  This method will be called on every startup.  Unless
277      * an exception is thrown, the plugin should be in the {@link PluginState#INSTALLED} state.  If the plugin is already
278      * in the {@link PluginState#INSTALLED} state, nothing will happen.
279      *
280      * @since 2.2.0
281      * @throws PluginException If the plugin could not be installed
282      */
283     void install() throws PluginException;
284 
285     /**
286      * Uninstalls the plugin from any internal container.  This method will be called on every shutdown.  Unless an
287      * exception is thrown, the plugin should be in the {@link PluginState#UNINSTALLED} state.  If the plugin is already
288      * in the {@link PluginState#UNINSTALLED} state, nothing will happen.
289      *
290      * @since 2.2.0
291      * @throws PluginException If the plugin could not be uninstalled
292      */
293     void uninstall() throws PluginException;
294 
295     /**
296      * Enables the plugin.  Unless an exception is thrown, the plugin should then be in either the
297      * {@link PluginState#ENABLING} or {@link PluginState#ENABLED} state.  If the plugin is already in the
298      * {@link PluginState#ENABLING} or {@link PluginState#ENABLED} state, nothing will happen.
299      *
300      *
301      * @since 2.2.0
302      * @throws PluginException If the plugin could not be enabled
303      */
304     void enable() throws PluginException;
305 
306     /**
307      * Disables the plugin.  Unless an exception is thrown, the plugin should be in the {@link PluginState#DISABLED}
308      * state. If the plugin is already in the {@link PluginState#DISABLED} state, nothing will happen.
309      *
310      * @since 2.2.0 If the plugin could not be disabled
311      * @throws PluginException If the plugin could not be disabled
312      */
313     void disable() throws PluginException;
314 
315     /**
316      * @return A list of plugin keys that this plugin is dependent upon, or an empty list if none
317      * @since 2.2.0
318      */
319     Set<String> getRequiredPlugins();
320 
321     /**
322      * @return the list of permissions currently valid for the plugin
323      * @since 3.0
324      */
325     Set<String> getActivePermissions();
326 
327     /**
328      * @return {@code true} if the plugin has all the permissions
329      * @since 3.0
330      */
331     boolean hasAllPermissions();
332 
333     /**
334      * Extension interface providing access to enable time metrics.
335      *
336      * @since 3.2.0
337      */
338     @ExperimentalApi
339     interface HasEnableMetrics
340     {
341         /**
342          * Obtain the date that the plugin system most recently commenced enabling this plugin.
343          *
344          * This may return null if the plugin has never commenced enabling, or if the value is
345          * unavailable for other reasons, such as wrappers around legacy implementations.
346          *
347          * @return the date that the plugin most recently entered #{@link PluginState#ENABLING}.
348          */
349         @Nullable Date getDateEnabling();
350 
351         /**
352          * Obtain the date that the plugin system most recently completed enabling of this plugin.
353          *
354          * This will return null if the plugin has never been enabled, has not completed enabling
355          * since it most recently started enabling, or if the value is unavailable for any other
356          * reason, such as wrappers around legacy implementations.
357          *
358          * @return the date that the plugin most recently entered #{@link PluginState#ENABLED},
359          * if this was not before the most recent #{@link PluginState#ENABLING}, otherwise null.
360          */
361         @Nullable Date getDateEnabled();
362 
363         /**
364          * Host to default implementations of the #{@link HasEnableMetrics} methods.
365          */
366         class Default
367         {
368             /**
369              * Default implementation for #{@link HasEnableMetrics#getDateEnabling}.
370              *
371              * @param plugin the plugin to query, which may implement HasEnableMetrics.
372              * @return plugin.getDateEnabling if available, otherwise null.
373              */
374             public static @Nullable Date getDateEnabling(final Plugin plugin)
375             {
376                 if (plugin instanceof HasEnableMetrics)
377                 {
378                     return ((HasEnableMetrics) plugin).getDateEnabling();
379                 }
380                 else
381                 {
382                     return null;
383                 }
384             }
385 
386             /**
387              * Default implementation for #{@link HasEnableMetrics#getDateEnabled}.
388              *
389              * @param plugin the plugin to query, which may implement HasEnableMetrics.
390              * @return plugin.getDateEnabled if available, otherwise null.
391              */
392             public static @Nullable Date getDateEnabled(final Plugin plugin)
393             {
394                 if (plugin instanceof HasEnableMetrics)
395                 {
396                     return ((HasEnableMetrics) plugin).getDateEnabled();
397                 }
398                 else
399                 {
400                     return null;
401                 }
402             }
403         }
404     }
405 }