1 package com.atlassian.plugin.parsers;
2
3 import com.atlassian.plugin.*;
4 import com.atlassian.plugin.impl.UnloadablePluginFactory;
5 import com.atlassian.plugin.descriptors.UnloadableModuleDescriptor;
6 import com.atlassian.plugin.descriptors.UnrecognisedModuleDescriptor;
7 import com.atlassian.plugin.descriptors.UnrecognisedModuleDescriptorFactory;
8 import com.atlassian.plugin.descriptors.UnloadableModuleDescriptorFactory;
9 import org.dom4j.Element;
10 import org.dom4j.Document;
11 import org.dom4j.DocumentException;
12 import org.dom4j.io.SAXReader;
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15
16 import java.util.Iterator;
17 import java.io.InputStream;
18
19
20
21
22
23
24
25
26
27 public class XmlDescriptorParser implements DescriptorParser
28 {
29 private static Log log = LogFactory.getLog(XmlDescriptorParser.class);
30
31 boolean recogniseSystemPlugins = false;
32 private Document document;
33
34
35
36
37 public XmlDescriptorParser(InputStream source) throws PluginParseException
38 {
39 if (source == null)
40 throw new IllegalArgumentException("source cannot be null");
41 document = createDocument(source);
42 }
43
44 protected Document createDocument(InputStream source) throws PluginParseException
45 {
46 SAXReader reader = new SAXReader();
47 try
48 {
49 return reader.read(source);
50 }
51 catch (DocumentException e)
52 {
53 throw new PluginParseException("Cannot parse XML plugin descriptor", e);
54 }
55 }
56
57 protected Document getDocument()
58 {
59 return document;
60 }
61
62 public Plugin configurePlugin(ModuleDescriptorFactory moduleDescriptorFactory, Plugin plugin) throws PluginParseException
63 {
64
65 Element pluginElement = getPluginElement();
66 plugin.setName(pluginElement.attributeValue("name"));
67 plugin.setKey(getKey());
68
69 if (pluginElement.attributeValue("i18n-name-key") != null)
70 {
71 plugin.setI18nNameKey(pluginElement.attributeValue("i18n-name-key"));
72 }
73
74 if (plugin.getKey().indexOf(":") > 0)
75 throw new PluginParseException("Plugin keys cannot contain ':'. Key is '" + plugin.getKey() + "'");
76
77 if ("disabled".equalsIgnoreCase(pluginElement.attributeValue("state")))
78 plugin.setEnabledByDefault(false);
79
80 for (Iterator i = pluginElement.elementIterator(); i.hasNext();)
81 {
82 Element element = (Element) i.next();
83
84 if ("plugin-info".equalsIgnoreCase(element.getName()))
85 {
86 plugin.setPluginInformation(createPluginInformation(element));
87 }
88 else if (!"resource".equalsIgnoreCase(element.getName()))
89 {
90 ModuleDescriptor moduleDescriptor = createModuleDescriptor(plugin, element, moduleDescriptorFactory);
91
92
93 if (moduleDescriptor == null)
94 continue;
95
96 if (plugin.getModuleDescriptor(moduleDescriptor.getKey()) != null)
97 throw new PluginParseException("Found duplicate key '" + moduleDescriptor.getKey() + "' within plugin '" + plugin.getKey() + "'");
98
99 plugin.addModuleDescriptor(moduleDescriptor);
100
101
102 if (moduleDescriptor instanceof UnloadableModuleDescriptor)
103 {
104 log.error("There were errors loading the plugin '" + plugin.getName() + "'. The plugin has been disabled.");
105 return UnloadablePluginFactory.createUnloadablePlugin(plugin);
106 }
107 }
108 }
109
110 plugin.setResources(Resources.fromXml(pluginElement));
111
112 return plugin;
113 }
114
115 private Element getPluginElement()
116 {
117 return document.getRootElement();
118 }
119
120 protected ModuleDescriptor createModuleDescriptor(Plugin plugin, Element element, ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
121 {
122 String name = element.getName();
123
124 ModuleDescriptor moduleDescriptorDescriptor;
125
126
127 try
128 {
129 moduleDescriptorDescriptor = moduleDescriptorFactory.getModuleDescriptor(name);
130 }
131
132 catch (Throwable e)
133 {
134 UnrecognisedModuleDescriptor descriptor = UnrecognisedModuleDescriptorFactory.createUnrecognisedModuleDescriptor(plugin, element, e, moduleDescriptorFactory);
135
136 log.error("There were problems loading the module '" + name + "' in plugin '" + plugin.getName() + "'. The module has been disabled.");
137 log.error(descriptor.getErrorText(), e);
138
139 return descriptor;
140 }
141
142
143 if (moduleDescriptorDescriptor == null)
144 {
145 log.info("The module '" + name + "' in plugin '" + plugin.getName() + "' is in the list of excluded module descriptors, so not enabling.");
146 return null;
147 }
148
149
150 try
151 {
152 moduleDescriptorDescriptor.init(plugin, element);
153 }
154
155 catch (PluginParseException e)
156 {
157 UnloadableModuleDescriptor descriptor = UnloadableModuleDescriptorFactory.createUnloadableModuleDescriptor(plugin, element, e, moduleDescriptorFactory);
158
159 log.error("There were problems loading the module '" + name + "'. The module and its plugin have been disabled.");
160 log.error(descriptor.getErrorText(), e);
161
162 return descriptor;
163 }
164
165 return moduleDescriptorDescriptor;
166 }
167
168
169 protected PluginInformation createPluginInformation(Element element)
170 {
171 PluginInformation pluginInfo = new PluginInformation();
172
173 if (element.element("description") != null)
174 {
175 pluginInfo.setDescription(element.element("description").getTextTrim());
176 if (element.element("description").attributeValue("key") != null)
177 {
178 pluginInfo.setDescriptionKey(element.element("description").attributeValue("key"));
179 }
180 }
181
182 if (element.element("version") != null)
183 pluginInfo.setVersion(element.element("version").getTextTrim());
184
185 if (element.element("vendor") != null)
186 {
187 final Element vendor = element.element("vendor");
188 pluginInfo.setVendorName(vendor.attributeValue("name"));
189 pluginInfo.setVendorUrl(vendor.attributeValue("url"));
190 }
191
192
193 for (Iterator iterator = element.elements("param").iterator(); iterator.hasNext();)
194 {
195 Element param = (Element) iterator.next();
196
197
198 if (param.attribute("name") != null)
199 pluginInfo.addParameter(param.attribute("name").getData().toString(), param.getText());
200 }
201
202 if (element.element("application-version") != null)
203 {
204 pluginInfo.setMaxVersion(Float.parseFloat(element.element("application-version").attributeValue("max")));
205 pluginInfo.setMinVersion(Float.parseFloat(element.element("application-version").attributeValue("min")));
206 }
207
208 if (element.element("java-version") != null)
209 {
210 pluginInfo.setMinJavaVersion(Float.valueOf(element.element("java-version").attributeValue("min")));
211 }
212
213 return pluginInfo;
214 }
215
216 public String getKey()
217 {
218 return getPluginElement().attributeValue("key");
219 }
220
221 public int getPluginsVersion()
222 {
223 String val = getPluginElement().attributeValue("pluginsVersion");
224 if (val != null) {
225 return Integer.parseInt(val);
226 } else {
227 return 1;
228 }
229 }
230
231 public boolean isSystemPlugin()
232 {
233 return "true".equalsIgnoreCase(getPluginElement().attributeValue("system"));
234 }
235 }