1 package com.atlassian.plugin.descriptors;
2
3 import com.atlassian.plugin.*;
4 import com.atlassian.plugin.elements.ResourceLocation;
5 import com.atlassian.plugin.elements.ResourceDescriptor;
6 import com.atlassian.plugin.loaders.LoaderUtils;
7 import com.atlassian.plugin.util.JavaVersionUtils;
8 import org.dom4j.Element;
9
10 import java.lang.reflect.Constructor;
11 import java.util.List;
12 import java.util.Map;
13
14 public abstract class AbstractModuleDescriptor<T> implements ModuleDescriptor<T>, StateAware
15 {
16 protected Plugin plugin;
17 String key;
18 String name;
19 String moduleClassName;
20 Class moduleClass;
21 String description;
22 boolean enabledByDefault = true;
23 boolean systemModule = false;
24 protected boolean singleton = true;
25 Map<String,String> params;
26 protected Resources resources = Resources.EMPTY_RESOURCES;
27 private Float minJavaVersion;
28 private String i18nNameKey;
29 private String descriptionKey;
30 private String completeKey;
31 boolean enabled = false;
32
33 public void init(Plugin plugin, Element element) throws PluginParseException
34 {
35 this.plugin = plugin;
36 this.key = element.attributeValue("key");
37 this.name = element.attributeValue("name");
38 this.i18nNameKey = element.attributeValue("i18n-name-key");
39 this.completeKey = buildCompleteKey(plugin, key);
40 this.description = element.elementTextTrim("description");
41 this.moduleClassName = element.attributeValue("class");
42 Element descriptionElement = element.element("description");
43 this.descriptionKey = (descriptionElement != null) ? descriptionElement.attributeValue("key") : null;
44 params = LoaderUtils.getParams(element);
45
46 if ("disabled".equalsIgnoreCase(element.attributeValue("state")))
47 {
48 enabledByDefault = false;
49 }
50
51 if ("true".equalsIgnoreCase(element.attributeValue("system")))
52 {
53 systemModule = true;
54 }
55
56 if (element.element("java-version") != null)
57 {
58 minJavaVersion = Float.valueOf(element.element("java-version").attributeValue("min"));
59 }
60
61 if ("false".equalsIgnoreCase(element.attributeValue("singleton")))
62 {
63 singleton = false;
64 }
65 else if ("true".equalsIgnoreCase(element.attributeValue("singleton")))
66 {
67 singleton = true;
68 }
69 else
70 {
71 singleton = isSingletonByDefault();
72 }
73
74 resources = Resources.fromXml(element);
75 }
76
77
78
79
80
81
82
83 protected void loadClass(Plugin plugin, Element element) throws PluginParseException {
84 loadClass(plugin, element.attributeValue("class"));
85 }
86
87
88
89
90
91
92
93 protected void loadClass(Plugin plugin, String clazz) throws PluginParseException {
94 try
95 {
96 if (clazz != null)
97 {
98
99 moduleClass = plugin.loadClass(clazz, getClass());
100
101
102 try
103 {
104 Constructor noargConstructor = moduleClass.getConstructor(new Class[]{});
105 if(noargConstructor != null)
106 {
107 moduleClass.newInstance();
108 }
109 }
110 catch (NoSuchMethodException e)
111 {
112
113 }
114 }
115 }
116 catch (ClassNotFoundException e)
117 {
118 throw new PluginParseException("Could not load class: " + clazz, e);
119 }
120 catch (NoClassDefFoundError e)
121 {
122 throw new PluginParseException("Error retrieving dependency of class: " + clazz + ". Missing class: " + e.getMessage());
123 }
124 catch (UnsupportedClassVersionError e)
125 {
126 throw new PluginParseException("Class version is incompatible with current JVM: " + clazz, e);
127 }
128 catch (Throwable t)
129 {
130 throw new PluginParseException(t);
131 }
132 }
133
134
135
136
137
138
139
140
141 private String buildCompleteKey(Plugin plugin, String moduleKey)
142 {
143 if (plugin == null)
144 return null;
145
146 final StringBuffer completeKeyBuffer = new StringBuffer(32);
147 completeKeyBuffer.append(plugin.getKey()).append(":").append(moduleKey);
148 return completeKeyBuffer.toString();
149 }
150
151
152
153
154 public void destroy(Plugin plugin)
155 {}
156
157 public boolean isEnabledByDefault()
158 {
159 return enabledByDefault && satisfiesMinJavaVersion();
160 }
161
162 public boolean isSystemModule()
163 {
164 return systemModule;
165 }
166
167 public boolean isSingleton()
168 {
169 return singleton;
170 }
171
172
173
174
175
176
177 protected boolean isSingletonByDefault()
178 {
179 return true;
180 }
181
182
183
184
185
186
187 final protected void assertModuleClassImplements(Class requiredModuleClazz) throws PluginParseException
188 {
189 if (!enabled)
190 {
191 throw new PluginParseException("Plugin module " + getKey() + " not enabled");
192 }
193 if (!requiredModuleClazz.isAssignableFrom(getModuleClass()))
194 {
195 throw new PluginParseException("Given module class: " + getModuleClass().getName() + " does not implement " + requiredModuleClazz.getName());
196 }
197 }
198
199 public String getCompleteKey()
200 {
201 return completeKey;
202 }
203
204 public String getPluginKey()
205 {
206 return plugin.getKey();
207 }
208
209 public String getKey()
210 {
211 return key;
212 }
213
214 public String getName()
215 {
216 return name;
217 }
218
219 public Class<T> getModuleClass()
220 {
221 return moduleClass;
222 }
223
224 public abstract T getModule();
225
226 public String getDescription()
227 {
228 return description;
229 }
230
231 public Map getParams()
232 {
233 return params;
234 }
235
236 public String getI18nNameKey()
237 {
238 return i18nNameKey;
239 }
240
241 public String getDescriptionKey()
242 {
243 return descriptionKey;
244 }
245
246 public List<ResourceDescriptor> getResourceDescriptors()
247 {
248 return resources.getResourceDescriptors();
249 }
250
251 public List<ResourceDescriptor> getResourceDescriptors(String type)
252 {
253 return resources.getResourceDescriptors(type);
254 }
255
256 public ResourceLocation getResourceLocation(String type, String name)
257 {
258 return resources.getResourceLocation(type, name);
259 }
260
261
262
263
264 public ResourceDescriptor getResourceDescriptor(String type, String name)
265 {
266 return resources.getResourceDescriptor(type, name);
267 }
268
269 public Float getMinJavaVersion()
270 {
271 return minJavaVersion;
272 }
273
274 public boolean satisfiesMinJavaVersion()
275 {
276 if(minJavaVersion != null)
277 {
278 return JavaVersionUtils.satisfiesMinVersion(minJavaVersion);
279 }
280 return true;
281 }
282
283
284
285
286 public void setPlugin(Plugin plugin)
287 {
288 this.completeKey = buildCompleteKey(plugin, key);
289 this.plugin = plugin;
290 }
291
292
293
294
295 public Plugin getPlugin()
296 {
297 return plugin;
298 }
299
300 public String toString()
301 {
302 return getCompleteKey() + " (" + getDescription() + ")";
303 }
304
305
306
307
308
309
310
311 public void enabled()
312 {
313 loadClass(plugin, moduleClassName);
314 enabled = true;
315 }
316
317
318
319
320
321 public void disabled()
322 {
323 enabled = false;
324 }
325 }