1 package com.atlassian.plugin.impl;
2
3 import static com.atlassian.plugin.util.concurrent.CopyOnWriteMap.newLinkedMap;
4
5 import com.atlassian.plugin.*;
6 import com.atlassian.plugin.elements.ResourceDescriptor;
7 import com.atlassian.plugin.elements.ResourceLocation;
8 import com.atlassian.plugin.util.VersionStringComparator;
9
10 import java.util.*;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14
15 public abstract class AbstractPlugin implements Plugin, Comparable<Plugin>
16 {
17 private final Map<String, ModuleDescriptor<?>> modules = newLinkedMap();
18 private String name;
19 private String i18nNameKey;
20 private String key;
21 private boolean enabledByDefault = true;
22 private PluginInformation pluginInformation = new PluginInformation();
23 private boolean system;
24 private Resourced resources = Resources.EMPTY_RESOURCES;
25 private int pluginsVersion = 1;
26 private final Date dateLoaded = new Date();
27 private volatile PluginState pluginState = PluginState.UNINSTALLED;
28
29 private final Log log = LogFactory.getLog(this.getClass());
30
31 public String getName()
32 {
33 return name;
34 }
35
36 public void setName(final String name)
37 {
38 this.name = name;
39 }
40
41
42
43
44 protected Log getLog()
45 {
46 return log;
47 }
48
49 public String getI18nNameKey()
50 {
51 return i18nNameKey;
52 }
53
54 public void setI18nNameKey(final String i18nNameKey)
55 {
56 this.i18nNameKey = i18nNameKey;
57 }
58
59 public String getKey()
60 {
61 return key;
62 }
63
64 public void setKey(final String aPackage)
65 {
66 key = aPackage;
67 }
68
69 public void addModuleDescriptor(final ModuleDescriptor<?> moduleDescriptor)
70 {
71 modules.put(moduleDescriptor.getKey(), moduleDescriptor);
72 }
73
74 protected void removeModuleDescriptor(final String key)
75 {
76 modules.remove(key);
77 }
78
79
80
81
82
83 public Collection<ModuleDescriptor<?>> getModuleDescriptors()
84 {
85 return new ArrayList<ModuleDescriptor<?>>(modules.values());
86 }
87
88 public ModuleDescriptor<?> getModuleDescriptor(final String key)
89 {
90 return modules.get(key);
91 }
92
93 public <T> List<ModuleDescriptor<T>> getModuleDescriptorsByModuleClass(final Class<T> aClass)
94 {
95 final List<ModuleDescriptor<T>> result = new ArrayList<ModuleDescriptor<T>>();
96 for (final ModuleDescriptor<?> moduleDescriptor : modules.values())
97 {
98 final Class<?> moduleClass = moduleDescriptor.getModuleClass();
99 if (aClass.isAssignableFrom(moduleClass))
100 {
101 @SuppressWarnings("unchecked")
102 final ModuleDescriptor<T> typedModuleDescriptor = (ModuleDescriptor<T>) moduleDescriptor;
103 result.add(typedModuleDescriptor);
104 }
105 }
106 return result;
107 }
108
109 public PluginState getPluginState()
110 {
111 return pluginState;
112 }
113
114 protected void setPluginState(PluginState state)
115 {
116 pluginState = state;
117 }
118
119 public boolean isEnabledByDefault()
120 {
121 return enabledByDefault && ((pluginInformation == null) || pluginInformation.satisfiesMinJavaVersion());
122 }
123
124 public void setEnabledByDefault(final boolean enabledByDefault)
125 {
126 this.enabledByDefault = enabledByDefault;
127 }
128
129 public int getPluginsVersion()
130 {
131 return pluginsVersion;
132 }
133
134 public void setPluginsVersion(final int pluginsVersion)
135 {
136 this.pluginsVersion = pluginsVersion;
137 }
138
139 public PluginInformation getPluginInformation()
140 {
141 return pluginInformation;
142 }
143
144 public void setPluginInformation(final PluginInformation pluginInformation)
145 {
146 this.pluginInformation = pluginInformation;
147 }
148
149 public void setResources(final Resourced resources)
150 {
151 this.resources = resources != null ? resources : Resources.EMPTY_RESOURCES;
152 }
153
154 public List<ResourceDescriptor> getResourceDescriptors()
155 {
156 return resources.getResourceDescriptors();
157 }
158
159 public List<ResourceDescriptor> getResourceDescriptors(final String type)
160 {
161 return resources.getResourceDescriptors(type);
162 }
163
164 public ResourceLocation getResourceLocation(final String type, final String name)
165 {
166 return resources.getResourceLocation(type, name);
167 }
168
169
170
171
172 @Deprecated
173 public ResourceDescriptor getResourceDescriptor(final String type, final String name)
174 {
175 return resources.getResourceDescriptor(type, name);
176 }
177
178
179
180
181 @Deprecated
182 public boolean isEnabled()
183 {
184 return getPluginState() == PluginState.ENABLED;
185 }
186
187 public final void enable()
188 {
189 if (pluginState == PluginState.ENABLED || pluginState == PluginState.ENABLING)
190 {
191 return;
192 }
193 if (getLog().isDebugEnabled())
194 {
195 getLog().debug("Enabling plugin '" + getKey() + "'");
196 }
197 try
198 {
199 pluginState = enableInternal();
200 }
201 catch (PluginException ex)
202 {
203 log.warn("Unable to enable plugin '" + getKey() + "'", ex);
204 throw ex;
205 }
206 if (getLog().isDebugEnabled())
207 {
208 getLog().debug("Enabled plugin '" + getKey() + "'");
209 }
210 }
211
212
213
214
215
216
217
218
219 protected PluginState enableInternal() throws PluginException
220 {
221 return PluginState.ENABLED;
222 }
223
224 public final void disable()
225 {
226 if (pluginState == PluginState.DISABLED)
227 {
228 return;
229 }
230 if (getLog().isDebugEnabled())
231 {
232 getLog().debug("Disabling plugin '" + getKey() + "'");
233 }
234 try
235 {
236 disableInternal();
237 pluginState = PluginState.DISABLED;
238 }
239 catch (PluginException ex)
240 {
241 log.warn("Unable to disable plugin '" + getKey() + "'", ex);
242 throw ex;
243 }
244 if (getLog().isDebugEnabled())
245 {
246 getLog().debug("Disabled plugin '" + getKey() + "'");
247 }
248 }
249
250
251
252
253
254
255
256 protected void disableInternal() throws PluginException
257 {
258 }
259
260 public Set<String> getRequiredPlugins()
261 {
262 return Collections.emptySet();
263 }
264
265 public void close()
266 {
267 uninstall();
268 }
269
270 public final void install()
271 {
272 if (pluginState == PluginState.INSTALLED)
273 {
274 return;
275 }
276 if (getLog().isDebugEnabled())
277 {
278 getLog().debug("Installing plugin '" + getKey() + "'");
279 }
280 try
281 {
282 installInternal();
283 pluginState = PluginState.INSTALLED;
284 }
285 catch (PluginException ex)
286 {
287 log.warn("Unable to install plugin '" + getKey() + "'", ex);
288 throw ex;
289 }
290 if (getLog().isDebugEnabled())
291 {
292 getLog().debug("Installed plugin '" + getKey() + "'");
293 }
294 }
295
296
297
298
299
300
301
302 protected void installInternal() throws PluginException
303 {
304 }
305
306 public final void uninstall()
307 {
308 if (pluginState == PluginState.UNINSTALLED)
309 {
310 return;
311 }
312 if (getLog().isDebugEnabled())
313 {
314 getLog().debug("Uninstalling plugin '" + getKey() + "'");
315 }
316 try
317 {
318 uninstallInternal();
319 pluginState = PluginState.UNINSTALLED;
320 }
321 catch (PluginException ex)
322 {
323 log.warn("Unable to uninstall plugin '" + getKey() + "'", ex);
324 throw ex;
325 }
326 if (getLog().isDebugEnabled())
327 {
328 getLog().debug("Uninstalled plugin '" + getKey() + "'");
329 }
330 }
331
332
333
334
335
336
337
338 protected void uninstallInternal() throws PluginException
339 {
340 }
341
342
343
344
345 @Deprecated
346 public void setEnabled(final boolean enabled)
347 {
348 if (enabled)
349 {
350 enable();
351 }
352 else
353 {
354 disable();
355 }
356 }
357
358 public boolean isSystemPlugin()
359 {
360 return system;
361 }
362
363 public boolean containsSystemModule()
364 {
365 for (final ModuleDescriptor<?> moduleDescriptor : modules.values())
366 {
367 if (moduleDescriptor.isSystemModule())
368 {
369 return true;
370 }
371 }
372 return false;
373 }
374
375 public void setSystemPlugin(final boolean system)
376 {
377 this.system = system;
378 }
379
380 public Date getDateLoaded()
381 {
382 return dateLoaded;
383 }
384
385 public boolean isBundledPlugin()
386 {
387 return false;
388 }
389
390
391
392
393
394
395
396
397
398
399 public int compareTo(final Plugin otherPlugin)
400 {
401 if (otherPlugin.getKey() == null)
402 {
403 if (getKey() == null)
404 {
405
406 return 0;
407 }
408 return 1;
409 }
410 if (getKey() == null)
411 {
412 return -1;
413 }
414
415
416 if (!otherPlugin.getKey().equals(getKey()))
417 {
418 return getKey().compareTo(otherPlugin.getKey());
419 }
420
421 final String thisVersion = cleanVersionString((getPluginInformation() != null ? getPluginInformation().getVersion() : null));
422 final String otherVersion = cleanVersionString((otherPlugin.getPluginInformation() != null ? otherPlugin.getPluginInformation().getVersion() : null));
423
424
425 if (!VersionStringComparator.isValidVersionString(thisVersion))
426 {
427 if (!VersionStringComparator.isValidVersionString(otherVersion))
428 {
429
430 return 0;
431 }
432 return -1;
433 }
434 if (!VersionStringComparator.isValidVersionString(otherVersion))
435 {
436 return 1;
437 }
438
439 return new VersionStringComparator().compare(thisVersion, otherVersion);
440 }
441
442 private String cleanVersionString(final String version)
443 {
444 if ((version == null) || version.trim().equals(""))
445 {
446 return "0";
447 }
448 return version.replaceAll(" ", "");
449 }
450
451 @Override
452 public String toString()
453 {
454 final PluginInformation info = getPluginInformation();
455 return getKey() + ":" + (info == null ? "?" : info.getVersion());
456 }
457 }