1 package com.atlassian.plugins.codegen.util;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.io.OutputStreamWriter;
10 import java.util.List;
11 import java.util.Map;
12
13 import com.atlassian.plugins.codegen.ClassId;
14 import com.atlassian.plugins.codegen.ComponentDeclaration;
15 import com.atlassian.plugins.codegen.ComponentImport;
16
17 import org.apache.commons.lang.Validate;
18 import org.dom4j.Document;
19 import org.dom4j.DocumentException;
20 import org.dom4j.DocumentHelper;
21 import org.dom4j.Element;
22 import org.dom4j.Node;
23 import org.dom4j.io.OutputFormat;
24 import org.dom4j.io.SAXReader;
25 import org.dom4j.io.XMLWriter;
26
27 import static org.apache.commons.io.IOUtils.closeQuietly;
28
29
30
31
32 public class PluginXmlHelper
33 {
34 private final Document document;
35
36 public PluginXmlHelper(File pluginXml) throws DocumentException, IOException
37 {
38 this(new FileInputStream(pluginXml));
39 }
40
41 public PluginXmlHelper(InputStream input) throws DocumentException, IOException
42 {
43 Validate.notNull(input);
44
45 this.document = createDocument(input);
46 }
47
48 public void addModuleAsLastChild(String fragment) throws DocumentException
49 {
50 Document fragDoc = DocumentHelper.parseText(fragment);
51 Element pluginRoot = document.getRootElement();
52 pluginRoot.add(fragDoc.getRootElement());
53 }
54
55 public void addI18nResource(String name) throws DocumentException, IOException
56 {
57 String xpath = "//resource[@type='i18n' and @location='" + name + "']";
58 Node resourceNode = document.selectSingleNode(xpath);
59
60 if (null == resourceNode)
61 {
62 Element pluginRoot = document.getRootElement();
63 Document fragDoc = DocumentHelper.parseText("<resource type=\"i18n\" name=\"i18n\" location=\"" + name + "\" />");
64 pluginRoot.add(fragDoc.getRootElement());
65 }
66 }
67
68 public void addPluginInfoParam(String name, String value)
69 {
70 Element pluginInfo = (Element) document.selectSingleNode("//plugin-info");
71 if (pluginInfo == null)
72 {
73 pluginInfo = document.addElement("plugin-info");
74 }
75 pluginInfo.addElement("param").addAttribute("name", name).setText(value);
76 }
77
78 public void addComponentImport(ComponentImport componentImport) throws DocumentException
79 {
80 String key = componentImport.getKey().getOrElse(createKeyFromClass(componentImport.getInterfaceClass()));
81 Element element = createModule("component-import");
82 element.addAttribute("key", key);
83 element.addAttribute("interface", componentImport.getInterfaceClass().getFullName());
84 for (String filter : componentImport.getFilter())
85 {
86 element.addAttribute("filter", filter);
87 }
88 }
89
90 public void addComponentDeclaration(ComponentDeclaration component) throws DocumentException
91 {
92 Element element = createModule("component");
93 element.addAttribute("key", component.getKey());
94 element.addAttribute("class", component.getClassId().getFullName());
95 for (String name : component.getName())
96 {
97 element.addAttribute("name", name);
98 }
99 for (String nameI18nKey : component.getNameI18nKey())
100 {
101 element.addAttribute("i18n-name-key", nameI18nKey);
102 }
103 if (component.getVisibility() == ComponentDeclaration.Visibility.PUBLIC)
104 {
105 element.addAttribute("public", "true");
106 }
107 for (String alias : component.getAlias())
108 {
109 element.addAttribute("alias", alias);
110 }
111 for (String description : component.getDescription())
112 {
113 Element eDesc = element.addElement("description");
114 eDesc.setText(description);
115 for (String descI18nKey : component.getDescriptionI18nKey())
116 {
117 eDesc.addAttribute("key", descI18nKey);
118 }
119 }
120 for (ClassId interfaceId : component.getInterfaceId())
121 {
122 element.addElement("interface").setText(interfaceId.getFullName());
123 }
124 if (!component.getServiceProperties().isEmpty())
125 {
126 Element eProps = element.addElement("service-properties");
127 for (Map.Entry<String, String> entry : component.getServiceProperties().entrySet())
128 {
129 Element eEntry = eProps.addElement("entry");
130 eEntry.addAttribute("key", entry.getKey());
131 eEntry.addAttribute("value", entry.getValue());
132 }
133 }
134 }
135
136 protected String createKeyFromClass(ClassId classId)
137 {
138 return lowercaseFirst(classId.getName());
139 }
140
141 protected String lowercaseFirst(String input)
142 {
143 return input.equals("") ? input : (input.substring(0, 1).toLowerCase() + input.substring(1));
144 }
145
146 public String getPluginXmlAsString()
147 {
148 return document.asXML();
149 }
150
151 protected Document getDocument()
152 {
153 return document;
154 }
155
156 protected Document createDocument(final InputStream source) throws DocumentException, IOException
157 {
158 final SAXReader reader = new SAXReader();
159 reader.setMergeAdjacentText(true);
160 reader.setStripWhitespaceText(false);
161 return reader.read(source);
162 }
163
164 protected Element createModule(String type)
165 {
166 Element newElement = document.getRootElement().addElement(type);
167 List existingModules = document.getRootElement().elements(type);
168 if (!existingModules.isEmpty())
169 {
170 newElement.detach();
171 existingModules.add(newElement);
172 }
173 return newElement;
174 }
175
176 public void savePluginXml(File file) throws IOException
177 {
178 FileOutputStream out = new FileOutputStream(file);
179 try
180 {
181 savePluginXml(out);
182 }
183 finally
184 {
185 closeQuietly(out);
186 }
187 }
188
189 public void savePluginXml(OutputStream out) throws IOException
190 {
191 OutputFormat format = OutputFormat.createPrettyPrint();
192 XMLWriter writer = new XMLWriter(new OutputStreamWriter(out), format);
193 try
194 {
195 writer.write(document);
196 }
197 finally
198 {
199 writer.close();
200 }
201 }
202 }