View Javadoc

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