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