1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.extension.repository.internal

File DefaultExtensionSerializer.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

124
299
28
1
806
593
97
0.32
10.68
28
3.46

Classes

Class Line # Actions
DefaultExtensionSerializer 86 299 0% 97 14
0.968957996.9%
 

Contributing tests

This file is covered by 120 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.extension.repository.internal;
21   
22    import java.io.IOException;
23    import java.io.InputStream;
24    import java.io.OutputStream;
25    import java.io.StringReader;
26    import java.io.StringWriter;
27    import java.net.URL;
28    import java.util.ArrayList;
29    import java.util.Collection;
30    import java.util.Collections;
31    import java.util.Date;
32    import java.util.HashMap;
33    import java.util.LinkedHashMap;
34    import java.util.LinkedList;
35    import java.util.List;
36    import java.util.Map;
37    import java.util.Set;
38   
39    import javax.inject.Inject;
40    import javax.inject.Singleton;
41    import javax.xml.parsers.DocumentBuilder;
42    import javax.xml.parsers.DocumentBuilderFactory;
43    import javax.xml.parsers.ParserConfigurationException;
44    import javax.xml.transform.OutputKeys;
45    import javax.xml.transform.Result;
46    import javax.xml.transform.Transformer;
47    import javax.xml.transform.TransformerException;
48    import javax.xml.transform.TransformerFactory;
49    import javax.xml.transform.dom.DOMSource;
50    import javax.xml.transform.stream.StreamResult;
51   
52    import org.apache.commons.io.IOUtils;
53    import org.w3c.dom.Document;
54    import org.w3c.dom.Element;
55    import org.w3c.dom.Node;
56    import org.w3c.dom.NodeList;
57    import org.xwiki.component.annotation.Component;
58    import org.xwiki.extension.DefaultExtensionScm;
59    import org.xwiki.extension.DefaultExtensionScmConnection;
60    import org.xwiki.extension.Extension;
61    import org.xwiki.extension.ExtensionAuthor;
62    import org.xwiki.extension.ExtensionDependency;
63    import org.xwiki.extension.ExtensionId;
64    import org.xwiki.extension.ExtensionIssueManagement;
65    import org.xwiki.extension.ExtensionLicense;
66    import org.xwiki.extension.ExtensionLicenseManager;
67    import org.xwiki.extension.ExtensionScm;
68    import org.xwiki.extension.ExtensionScmConnection;
69    import org.xwiki.extension.InstalledExtension;
70    import org.xwiki.extension.InvalidExtensionException;
71    import org.xwiki.extension.MutableExtension;
72    import org.xwiki.extension.internal.ExtensionFactory;
73    import org.xwiki.extension.repository.internal.core.DefaultCoreExtension;
74    import org.xwiki.extension.repository.internal.core.DefaultCoreExtensionRepository;
75    import org.xwiki.extension.repository.internal.local.DefaultLocalExtension;
76    import org.xwiki.extension.repository.internal.local.DefaultLocalExtensionRepository;
77   
78    /**
79    * Local repository storage serialization tool.
80    *
81    * @version $Id: 9b8e7c6ead8b4c5c1ca8ab499134635973299dbd $
82    * @since 6.4M1
83    */
84    @Component
85    @Singleton
 
86    public class DefaultExtensionSerializer implements ExtensionSerializer
87    {
88    private static final String ELEMENT_ID = "id";
89   
90    private static final String ELEMENT_VERSION = "version";
91   
92    private static final String ELEMENT_TYPE = "type";
93   
94    private static final String ELEMENT_LICENSES = "licenses";
95   
96    private static final String ELEMENT_LLICENSE = "license";
97   
98    private static final String ELEMENT_LLNAME = "name";
99   
100    private static final String ELEMENT_LLCONTENT = "content";
101   
102    private static final String ELEMENT_NAME = "name";
103   
104    private static final String ELEMENT_SUMMARY = "summary";
105   
106    private static final String ELEMENT_CATEGORY = "category";
107   
108    private static final String ELEMENT_DESCRIPTION = "description";
109   
110    private static final String ELEMENT_WEBSITE = "website";
111   
112    private static final String ELEMENT_AUTHORS = "authors";
113   
114    private static final String ELEMENT_AAUTHOR = "author";
115   
116    private static final String ELEMENT_AANAME = "name";
117   
118    private static final String ELEMENT_AAURL = "url";
119   
120    private static final String ELEMENT_DEPENDENCIES = "dependencies";
121   
122    private static final String ELEMENT_MANAGEDDEPENDENCIES = "manageddependencies";
123   
124    private static final String ELEMENT_DDEPENDENCY = "dependency";
125   
126    private static final String ELEMENT_DDOPTIONAL = "optional";
127   
128    private static final String ELEMENT_EXTENSIONFEATURES = "extensionfeatures";
129   
130    private static final String ELEMENT_EFFEATURE = "feature";
131   
132    private static final String ELEMENT_EFFID = "feature";
133   
134    private static final String ELEMENT_EFFVERSION = "version";
135   
136    private static final String ELEMENT_ALLOWEDNAMESPACES = "allowednamespaces";
137   
138    private static final String ELEMENT_ANNAMESPACE = "namespace";
139   
140    private static final String ELEMENT_SCM = "scm";
141   
142    private static final String ELEMENT_SCONNECTION = "connection";
143   
144    private static final String ELEMENT_SDEVELOPERCONNECTION = "developerconnection";
145   
146    private static final String ELEMENT_SCSYSTEM = "system";
147   
148    private static final String ELEMENT_SCPATH = "path";
149   
150    private static final String ELEMENT_SURL = "url";
151   
152    private static final String ELEMENT_ISSUEMANAGEMENT = "issuemanagement";
153   
154    private static final String ELEMENT_ISYSTEM = "system";
155   
156    private static final String ELEMENT_IURL = "url";
157   
158    private static final String ELEMENT_PROPERTIES = "properties";
159   
160    @Deprecated
161    private static final String ELEMENT_FEATURES = "features";
162   
163    @Deprecated
164    private static final String ELEMENT_FFEATURE = "feature";
165   
166    @Deprecated
167    private static final String ELEMENT_INSTALLED = "installed";
168   
169    @Deprecated
170    private static final String ELEMENT_NAMESPACES = "namespaces";
171   
172    @Deprecated
173    private static final String ELEMENT_NNAMESPACE = "namespace";
174   
175    @Inject
176    private ExtensionLicenseManager licenseManager;
177   
178    @Inject
179    private ExtensionFactory factory;
180   
181    /**
182    * Used to parse XML descriptor file.
183    */
184    private DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
185   
186    protected Map<String, ExtensionPropertySerializer> serializerById;
187   
188    protected Map<Class<?>, ExtensionPropertySerializer> serializerByClass;
189   
 
190  272 toggle {
191    {
192  272 this.serializerById = new HashMap<String, ExtensionPropertySerializer>();
193  272 this.serializerByClass = new LinkedHashMap<Class<?>, ExtensionPropertySerializer>();
194   
195  272 StringExtensionPropertySerializer stringSerializer = new StringExtensionPropertySerializer();
196  272 IntegerExtensionPropertySerializer integerSerializer = new IntegerExtensionPropertySerializer();
197  272 BooleanExtensionPropertySerializer booleanSerializer = new BooleanExtensionPropertySerializer();
198  272 DateExtensionPropertySerializer dateSerializer = new DateExtensionPropertySerializer();
199  272 URLExtensionPropertySerializer urlSerializer = new URLExtensionPropertySerializer();
200  272 CollectionExtensionPropertySerializer collectionSerializer =
201    new CollectionExtensionPropertySerializer(this.serializerById, this.serializerByClass);
202  272 SetExtensionPropertySerializer setSerializer =
203    new SetExtensionPropertySerializer(this.serializerById, this.serializerByClass);
204  272 StringKeyMapExtensionPropertySerializer mapSerializer =
205    new StringKeyMapExtensionPropertySerializer(this.serializerById, this.serializerByClass);
206   
207  272 this.serializerById.put(null, stringSerializer);
208  272 this.serializerById.put("", stringSerializer);
209  272 this.serializerById.put(integerSerializer.getType(), integerSerializer);
210  272 this.serializerById.put(booleanSerializer.getType(), booleanSerializer);
211  272 this.serializerById.put(dateSerializer.getType(), dateSerializer);
212  272 this.serializerById.put(urlSerializer.getType(), urlSerializer);
213  272 this.serializerById.put(collectionSerializer.getType(), collectionSerializer);
214  272 this.serializerById.put(setSerializer.getType(), setSerializer);
215  272 this.serializerById.put(mapSerializer.getType(), mapSerializer);
216   
217  272 this.serializerByClass.put(String.class, stringSerializer);
218  272 this.serializerByClass.put(Integer.class, integerSerializer);
219  272 this.serializerByClass.put(Boolean.class, booleanSerializer);
220  272 this.serializerByClass.put(Date.class, dateSerializer);
221  272 this.serializerByClass.put(URL.class, urlSerializer);
222  272 this.serializerByClass.put(Set.class, setSerializer);
223  272 this.serializerByClass.put(Collection.class, collectionSerializer);
224  272 this.serializerByClass.put(Map.class, mapSerializer);
225    }
226    }
227   
 
228  18285 toggle @Override
229    public DefaultCoreExtension loadCoreExtensionDescriptor(DefaultCoreExtensionRepository repository, URL url,
230    InputStream descriptor) throws InvalidExtensionException
231    {
232  18285 Element extensionElement = getExtensionElement(descriptor);
233   
234  18285 DefaultCoreExtension coreExtension = new DefaultCoreExtension(repository, url, getExtensionId(extensionElement),
235    getExtensionType(extensionElement));
236   
237  18285 loadExtensionDescriptor(coreExtension, extensionElement);
238   
239  18285 coreExtension.setComplete(true);
240   
241  18285 return coreExtension;
242    }
243   
 
244  2719 toggle @Override
245    public DefaultLocalExtension loadLocalExtensionDescriptor(DefaultLocalExtensionRepository repository,
246    InputStream descriptor) throws InvalidExtensionException
247    {
248  2719 Element extensionElement = getExtensionElement(descriptor);
249   
250  2719 DefaultLocalExtension localExtension =
251    new DefaultLocalExtension(repository, getExtensionId(extensionElement), getExtensionType(extensionElement));
252   
253  2719 loadExtensionDescriptor(localExtension, extensionElement);
254   
255  2719 return localExtension;
256    }
257   
 
258  21004 toggle private Element getExtensionElement(InputStream descriptor) throws InvalidExtensionException
259    {
260  21004 DocumentBuilder documentBuilder;
261  21004 try {
262  21004 documentBuilder = this.documentBuilderFactory.newDocumentBuilder();
263    } catch (ParserConfigurationException e) {
264  0 throw new InvalidExtensionException("Failed to create new DocumentBuilder", e);
265    }
266   
267  21004 Document document;
268  21004 try {
269  21004 document = documentBuilder.parse(descriptor);
270    } catch (Exception e) {
271  0 throw new InvalidExtensionException("Failed to parse descriptor", e);
272    }
273   
274  21004 return document.getDocumentElement();
275    }
276   
 
277  21004 toggle private ExtensionId getExtensionId(Element extensionElement)
278    {
279  21004 Node idNode = extensionElement.getElementsByTagName(ELEMENT_ID).item(0);
280  21004 Node versionNode = extensionElement.getElementsByTagName(ELEMENT_VERSION).item(0);
281   
282  21004 return new ExtensionId(idNode.getTextContent(), this.factory.getVersion(versionNode.getTextContent()));
283    }
284   
 
285  21004 toggle private String getExtensionType(Element extensionElement)
286    {
287  21004 Node typeNode = extensionElement.getElementsByTagName(ELEMENT_TYPE).item(0);
288   
289  21004 return typeNode.getTextContent();
290    }
291   
 
292  21004 toggle private void loadExtensionDescriptor(MutableExtension extension, Element extensionElement)
293    throws InvalidExtensionException
294    {
295  21004 Node nameNode = getNode(extensionElement, ELEMENT_NAME);
296  21004 if (nameNode != null) {
297  18900 extension.setName(nameNode.getTextContent());
298    }
299  21004 Node categoryNode = getNode(extensionElement, ELEMENT_CATEGORY);
300  21004 if (categoryNode != null) {
301  42 extension.setCategory(categoryNode.getTextContent());
302    }
303  21004 Node summaryNode = getNode(extensionElement, ELEMENT_SUMMARY);
304  21004 if (summaryNode != null) {
305  18950 extension.setSummary(summaryNode.getTextContent());
306    }
307  21004 Node descriptionNode = getNode(extensionElement, ELEMENT_DESCRIPTION);
308  21004 if (descriptionNode != null) {
309  216 extension.setDescription(descriptionNode.getTextContent());
310    }
311  21004 Node websiteNode = getNode(extensionElement, ELEMENT_WEBSITE);
312  21004 if (websiteNode != null) {
313  19208 extension.setWebsite(websiteNode.getTextContent());
314    }
315   
316    // Licenses
317  21004 Node licensesNode = getNode(extensionElement, ELEMENT_LICENSES);
318  21004 if (licensesNode != null) {
319  18992 NodeList licenseNodeList = licensesNode.getChildNodes();
320  79146 for (int i = 0; i < licenseNodeList.getLength(); ++i) {
321  60154 Node licenseNode = licenseNodeList.item(i);
322   
323  60154 if (licenseNode.getNodeName().equals(ELEMENT_LLICENSE)) {
324  20581 Node licenseNameNode = getNode(licenseNode, ELEMENT_LLNAME);
325  20581 Node licenceContentNode = getNode(licenseNode, ELEMENT_LLCONTENT);
326   
327  20581 String licenseName = licenseNameNode.getTextContent();
328  20581 ExtensionLicense license = this.licenseManager.getLicense(licenseName);
329  20581 if (license == null) {
330  3447 try {
331  3447 license = new ExtensionLicense(licenseName, licenceContentNode != null
332    ? IOUtils.readLines(new StringReader(licenceContentNode.getTextContent())) : null);
333    } catch (IOException e) {
334    // That should never happen
335  0 throw new InvalidExtensionException("Failed to write license content", e);
336    }
337    }
338   
339  20581 extension.addLicense(license);
340    }
341    }
342    }
343   
344    // Authors
345  21004 Node authorsNode = getNode(extensionElement, ELEMENT_AUTHORS);
346  21004 if (authorsNode != null) {
347  16455 NodeList authors = authorsNode.getChildNodes();
348  181642 for (int i = 0; i < authors.getLength(); ++i) {
349  165187 Node authorNode = authors.item(i);
350   
351  165187 if (authorNode.getNodeName().equals(ELEMENT_AAUTHOR)) {
352  74366 Node authorNameNode = getNode(authorNode, ELEMENT_AANAME);
353  74366 Node authorURLNode = getNode(authorNode, ELEMENT_AAURL);
354   
355  74366 String authorName = authorNameNode != null ? authorNameNode.getTextContent() : null;
356  74366 String authorURL;
357  74366 if (authorURLNode != null) {
358  3056 authorURL = authorURLNode.getTextContent();
359    } else {
360  71310 authorURL = null;
361    }
362   
363  74366 extension.addAuthor(this.factory.getExtensionAuthor(authorName, authorURL));
364    }
365    }
366    }
367   
368    // Extension features
369  21004 Node featuresNode = getNode(extensionElement, ELEMENT_EXTENSIONFEATURES);
370  21004 if (featuresNode != null) {
371  1279 NodeList extensionFeatures = featuresNode.getChildNodes();
372  6218 for (int i = 0; i < extensionFeatures.getLength(); ++i) {
373  4939 Node featureNode = extensionFeatures.item(i);
374   
375  4939 if (featureNode.getNodeName().equals(ELEMENT_EFFEATURE)) {
376  1830 Node idNode = getNode(featureNode, ELEMENT_EFFID);
377  1830 Node versionNode = getNode(featureNode, ELEMENT_EFFVERSION);
378   
379  1830 String id = idNode != null ? idNode.getTextContent() : null;
380  1830 String version = versionNode != null ? versionNode.getTextContent() : null;
381   
382  1830 if (version != null) {
383  1830 extension.addExtensionFeature(new ExtensionId(id, this.factory.getVersion(version)));
384    } else {
385  0 extension.addExtensionFeature(new ExtensionId(id, extension.getId().getVersion()));
386    }
387    }
388    }
389    }
390  21004 if (featuresNode == null) {
391    // @Deprecated Features
392  19725 List<String> legacyFeatures = parseList(extensionElement, ELEMENT_FEATURES, ELEMENT_FFEATURE);
393  19725 if (legacyFeatures != null) {
394  399 extension.setFeatures(legacyFeatures);
395    }
396    }
397   
398    // Allowed namespaces
399  21004 List<String> allowedNamespaces = parseList(extensionElement, ELEMENT_ALLOWEDNAMESPACES, ELEMENT_ANNAMESPACE);
400  21004 if (allowedNamespaces != null) {
401  22 extension.setAllowedNamespaces(allowedNamespaces);
402    }
403   
404    // Scm
405  21004 extension.setScm(loadlScm(extensionElement));
406   
407    // Issue Management
408  21004 extension.setIssueManagement(loadIssueManagement(extensionElement));
409   
410    // Dependencies
411  21004 extension.setDependencies(loadDependencies(extensionElement, ELEMENT_DEPENDENCIES));
412   
413    // Managed dependencies
414  21004 extension.setManagedDependencies(loadDependencies(extensionElement, ELEMENT_MANAGEDDEPENDENCIES));
415   
416    // Properties
417  21004 Map<String, Object> properties = parseProperties(extensionElement);
418  21004 if (properties != null) {
419  20528 extension.setProperties(properties);
420    }
421   
422    // @Deprecated Install fields
423   
424  21004 Node enabledNode = getNode(extensionElement, ELEMENT_INSTALLED);
425  21004 if (enabledNode != null) {
426  261 extension.putProperty(InstalledExtension.PKEY_INSTALLED, Boolean.valueOf(enabledNode.getTextContent()));
427    }
428   
429    // @Deprecated Namespaces
430  21004 List<String> namespaces = parseList(extensionElement, ELEMENT_NAMESPACES, ELEMENT_NNAMESPACE);
431  21004 if (namespaces != null) {
432  0 extension.putProperty(InstalledExtension.PKEY_NAMESPACES, namespaces);
433    }
434    }
435   
 
436  42008 toggle private Collection<ExtensionDependency> loadDependencies(Element extensionElement, String dependenciesFiel)
437    {
438  42008 Node dependenciesNode = getNode(extensionElement, dependenciesFiel);
439  42008 if (dependenciesNode != null) {
440  27857 NodeList dependenciesNodeList = dependenciesNode.getChildNodes();
441   
442  27857 List<ExtensionDependency> dependencies = new ArrayList<>(dependenciesNodeList.getLength());
443   
444  3838564 for (int i = 0; i < dependenciesNodeList.getLength(); ++i) {
445  3810707 Node dependency = dependenciesNodeList.item(i);
446   
447  3810707 if (dependency.getNodeName().equals(ELEMENT_DDEPENDENCY)) {
448  1891425 Node dependencyIdNode = getNode(dependency, ELEMENT_ID);
449  1891425 Node dependencyVersionNode = getNode(dependency, ELEMENT_VERSION);
450  1891425 Node dependencyOptionalNode = getNode(dependency, ELEMENT_DDOPTIONAL);
451   
452  1891425 dependencies.add(this.factory.getExtensionDependency(dependencyIdNode.getTextContent(),
453  1891425 dependencyVersionNode != null
454    ? this.factory.getVersionConstraint(dependencyVersionNode.getTextContent()) : null,
455  1891425 dependencyOptionalNode != null ? Boolean.valueOf(dependencyOptionalNode.getTextContent())
456    : false,
457    parseProperties((Element) dependency)));
458    }
459    }
460   
461  27857 return dependencies;
462    }
463   
464  14151 return Collections.emptyList();
465    }
466   
 
467  21004 toggle private ExtensionScm loadlScm(Element extensionElement)
468    {
469  21004 Node node = getNode(extensionElement, ELEMENT_SCM);
470   
471  21004 if (node != null) {
472  18577 Node connectionNode = getNode(node, ELEMENT_SCONNECTION);
473  18577 Node developerConnectionNode = getNode(node, ELEMENT_SDEVELOPERCONNECTION);
474  18577 Node urlNode = getNode(node, ELEMENT_SURL);
475   
476  18577 return new DefaultExtensionScm(urlNode != null ? urlNode.getTextContent() : null,
477    loadlScmConnection(connectionNode), loadlScmConnection(developerConnectionNode));
478    }
479   
480  2427 return null;
481    }
482   
 
483  37154 toggle private ExtensionScmConnection loadlScmConnection(Node scmConnectionElement)
484    {
485  37154 if (scmConnectionElement != null) {
486  34769 Node system = getNode(scmConnectionElement, ELEMENT_SCSYSTEM);
487  34769 Node path = getNode(scmConnectionElement, ELEMENT_SCPATH);
488   
489  34769 if (system != null) {
490  34769 return new DefaultExtensionScmConnection(system.getTextContent(),
491  34769 path != null ? path.getTextContent() : null);
492    }
493    }
494   
495  2385 return null;
496    }
497   
 
498  21004 toggle private ExtensionIssueManagement loadIssueManagement(Element extensionElement)
499    {
500  21004 Node node = getNode(extensionElement, ELEMENT_ISSUEMANAGEMENT);
501   
502  21004 if (node != null) {
503  14104 Node systemNode = getNode(node, ELEMENT_ISYSTEM);
504  14104 Node urlNode = getNode(node, ELEMENT_IURL);
505   
506  14104 if (systemNode != null) {
507  13525 return this.factory.getExtensionIssueManagement(systemNode.getTextContent(),
508  13525 urlNode != null ? urlNode.getTextContent() : null);
509    }
510    }
511   
512  7479 return null;
513    }
514   
 
515  61733 toggle private List<String> parseList(Element extensionElement, String rootElement, String childElement)
516    {
517  61733 List<String> list;
518   
519  61733 Node featuresNode = getNode(extensionElement, rootElement);
520  61733 if (featuresNode != null) {
521  421 list = new LinkedList<String>();
522   
523  421 NodeList features = featuresNode.getChildNodes();
524  1686 for (int i = 0; i < features.getLength(); ++i) {
525  1265 Node featureNode = features.item(i);
526   
527  1265 if (featureNode.getNodeName() == childElement) {
528  422 list.add(featureNode.getTextContent());
529    }
530    }
531    } else {
532  61312 list = null;
533    }
534   
535  61733 return list;
536    }
537   
 
538  1912429 toggle private Map<String, Object> parseProperties(Element parentElement)
539    {
540  1912429 Map<String, Object> properties = null;
541   
542  1912429 Node propertiesNode = getNode(parentElement, ELEMENT_PROPERTIES);
543  1912429 if (propertiesNode != null) {
544  1910770 properties = new HashMap<String, Object>();
545  1910770 NodeList propertyNodeList = propertiesNode.getChildNodes();
546  2566575 for (int i = 0; i < propertyNodeList.getLength(); ++i) {
547  655805 Node propertyNode = propertyNodeList.item(i);
548   
549  655805 if (propertyNode.getNodeType() == Node.ELEMENT_NODE) {
550  234239 Object value =
551    CollectionExtensionPropertySerializer.toValue((Element) propertyNode, this.serializerById);
552   
553  234239 if (value != null) {
554  234239 properties.put(propertyNode.getNodeName(), value);
555    }
556    }
557    }
558    }
559   
560  1912429 return properties;
561    }
562   
 
563  8268520 toggle private Node getNode(Node parentNode, String elementName)
564    {
565  8268520 NodeList children = parentNode.getChildNodes();
566  45986156 for (int i = 0; i < children.getLength(); ++i) {
567  45702381 Node node = children.item(i);
568   
569  45702381 if (node.getNodeName().equals(elementName)) {
570  7984745 return node;
571    }
572    }
573   
574  283775 return null;
575    }
576   
 
577  16698 toggle @Override
578    public void saveExtensionDescriptor(Extension extension, OutputStream fos)
579    throws ParserConfigurationException, TransformerException
580    {
581  16698 DocumentBuilder documentBuilder = this.documentBuilderFactory.newDocumentBuilder();
582  16698 Document document = documentBuilder.newDocument();
583   
584  16698 Element extensionElement = document.createElement("extension");
585  16698 document.appendChild(extensionElement);
586   
587  16698 addElement(document, extensionElement, ELEMENT_ID, extension.getId().getId());
588  16698 addElement(document, extensionElement, ELEMENT_VERSION, extension.getId().getVersion().getValue());
589  16698 addElement(document, extensionElement, ELEMENT_TYPE, extension.getType());
590  16698 addElement(document, extensionElement, ELEMENT_NAME, extension.getName());
591  16698 addElement(document, extensionElement, ELEMENT_CATEGORY, extension.getCategory());
592  16698 addElement(document, extensionElement, ELEMENT_SUMMARY, extension.getSummary());
593  16698 addElement(document, extensionElement, ELEMENT_DESCRIPTION, extension.getDescription());
594  16698 addElement(document, extensionElement, ELEMENT_WEBSITE, extension.getWebSite());
595   
596  16698 addExtensionFeatures(document, extensionElement, extension);
597  16698 addLegacyFeatures(document, extensionElement, extension);
598   
599  16698 addAuthors(document, extensionElement, extension);
600   
601  16698 addAllowedNamespaces(document, extensionElement, extension);
602   
603  16698 addLicenses(document, extensionElement, extension);
604   
605  16698 addScm(document, extensionElement, extension);
606   
607  16698 addIssueManagement(document, extensionElement, extension);
608   
609  16698 addDependencies(document, extensionElement, extension);
610  16698 addManagedDependencies(document, extensionElement, extension);
611   
612  16698 addProperties(document, extensionElement, extension.getProperties());
613   
614    // save
615   
616  16698 TransformerFactory transfac = TransformerFactory.newInstance();
617  16698 Transformer trans = transfac.newTransformer();
618  16698 trans.setOutputProperty(OutputKeys.INDENT, "yes");
619   
620  16698 DOMSource source = new DOMSource(document);
621  16698 Result result = new StreamResult(fos);
622  16698 trans.transform(source, result);
623    }
624   
 
625  16698 toggle private void addLicenses(Document document, Element parentElement, Extension extension)
626    {
627  16698 if (extension.getLicenses() != null && !extension.getLicenses().isEmpty()) {
628  15950 Element licensesElement = document.createElement(ELEMENT_LICENSES);
629  15950 parentElement.appendChild(licensesElement);
630   
631  15950 for (ExtensionLicense license : extension.getLicenses()) {
632  17512 Element licenseElement = document.createElement(ELEMENT_LLICENSE);
633  17512 licensesElement.appendChild(licenseElement);
634   
635  17512 addElement(document, licenseElement, ELEMENT_LLNAME, license.getName());
636  17512 if (this.licenseManager.getLicense(license.getName()) == null && license.getContent() != null) {
637    // Only store content if it's a custom license (license content is pretty big generally)
638  2 StringWriter content = new StringWriter();
639  2 try {
640  2 IOUtils.writeLines(license.getContent(), IOUtils.LINE_SEPARATOR_UNIX, content);
641    } catch (IOException e) {
642    // That should never happen
643    }
644  2 addElement(document, licenseElement, ELEMENT_LLCONTENT, content.toString());
645    }
646    }
647    }
648    }
649   
 
650  16698 toggle @Deprecated
651    private void addLegacyFeatures(Document document, Element parentElement, Extension extension)
652    {
653  16698 Collection<String> features = extension.getFeatures();
654  16698 if (!features.isEmpty()) {
655  1125 Element featuresElement = document.createElement(ELEMENT_FEATURES);
656  1125 parentElement.appendChild(featuresElement);
657   
658  1125 for (String feature : features) {
659  1315 addElement(document, featuresElement, ELEMENT_FFEATURE, feature);
660    }
661    }
662    }
663   
 
664  16698 toggle private void addAllowedNamespaces(Document document, Element parentElement, Extension extension)
665    {
666  16698 Collection<String> namespaces = extension.getAllowedNamespaces();
667  16698 if (namespaces != null) {
668  15 Element namespacesElement = document.createElement(ELEMENT_ALLOWEDNAMESPACES);
669  15 parentElement.appendChild(namespacesElement);
670   
671  15 for (String namespace : namespaces) {
672  15 addElement(document, namespacesElement, ELEMENT_ANNAMESPACE, namespace);
673    }
674    }
675    }
676   
 
677  16698 toggle private void addExtensionFeatures(Document document, Element parentElement, Extension extension)
678    {
679  16698 Collection<ExtensionId> features = extension.getExtensionFeatures();
680  16698 if (!features.isEmpty()) {
681  1125 Element featuresElement = document.createElement(ELEMENT_EXTENSIONFEATURES);
682  1125 parentElement.appendChild(featuresElement);
683   
684  1125 for (ExtensionId feature : features) {
685  1315 Element authorElement = document.createElement(ELEMENT_EFFEATURE);
686  1315 featuresElement.appendChild(authorElement);
687   
688  1315 addElement(document, authorElement, ELEMENT_EFFID, feature.getId());
689  1315 addElement(document, authorElement, ELEMENT_EFFVERSION, feature.getVersion().getValue());
690    }
691    }
692    }
693   
 
694  16698 toggle private void addAuthors(Document document, Element parentElement, Extension extension)
695    {
696  16698 Collection<ExtensionAuthor> authors = extension.getAuthors();
697  16698 if (!authors.isEmpty()) {
698  13797 Element authorsElement = document.createElement(ELEMENT_AUTHORS);
699  13797 parentElement.appendChild(authorsElement);
700   
701  13797 for (ExtensionAuthor author : authors) {
702  55938 Element authorElement = document.createElement(ELEMENT_AAUTHOR);
703  55938 authorsElement.appendChild(authorElement);
704   
705  55938 addElement(document, authorElement, ELEMENT_AANAME, author.getName());
706   
707  55938 String authorURL = author.getURLString();
708  55938 if (authorURL != null) {
709  2638 addElement(document, authorElement, ELEMENT_AAURL, authorURL.toString());
710    }
711    }
712    }
713    }
714   
 
715  16698 toggle private void addScm(Document document, Element extensionElement, Extension extension)
716    {
717  16698 ExtensionScm scm = extension.getScm();
718   
719  16698 if (scm != null) {
720  15610 Element scmElement = document.createElement(ELEMENT_SCM);
721  15610 extensionElement.appendChild(scmElement);
722   
723  15610 addElement(document, scmElement, ELEMENT_SURL, scm.getUrl());
724  15610 addScmConnection(document, scmElement, scm.getConnection(), ELEMENT_SCONNECTION);
725  15610 addScmConnection(document, scmElement, scm.getDeveloperConnection(), ELEMENT_SDEVELOPERCONNECTION);
726    }
727    }
728   
 
729  31220 toggle private void addScmConnection(Document document, Element scmElement, ExtensionScmConnection connection,
730    String elementName)
731    {
732  31220 if (connection != null) {
733  29080 Element connectionElement = document.createElement(elementName);
734  29080 scmElement.appendChild(connectionElement);
735   
736  29080 addElement(document, connectionElement, ELEMENT_SCSYSTEM, connection.getSystem());
737  29080 addElement(document, connectionElement, ELEMENT_SCPATH, connection.getPath());
738    }
739    }
740   
 
741  16698 toggle private void addIssueManagement(Document document, Element extensionElement, Extension extension)
742    {
743  16698 ExtensionIssueManagement issueManagement = extension.getIssueManagement();
744   
745  16698 if (issueManagement != null) {
746  11576 Element issuemanagementElement = document.createElement(ELEMENT_ISSUEMANAGEMENT);
747  11576 extensionElement.appendChild(issuemanagementElement);
748   
749  11576 addElement(document, issuemanagementElement, ELEMENT_ISYSTEM, issueManagement.getSystem());
750  11576 addElement(document, issuemanagementElement, ELEMENT_IURL, issueManagement.getURL());
751    }
752    }
753   
 
754  16698 toggle private void addDependencies(Document document, Element parentElement, Extension extension)
755    {
756  16698 addDependencies(document, parentElement, ELEMENT_DEPENDENCIES, extension.getDependencies());
757    }
758   
 
759  16698 toggle private void addManagedDependencies(Document document, Element parentElement, Extension extension)
760    {
761  16698 addDependencies(document, parentElement, ELEMENT_MANAGEDDEPENDENCIES, extension.getManagedDependencies());
762    }
763   
 
764  33396 toggle private void addDependencies(Document document, Element parentElement, String fieldName,
765    Collection<ExtensionDependency> dependencies)
766    {
767  33396 if (dependencies != null && !dependencies.isEmpty()) {
768  22028 Element dependenciesElement = document.createElement(fieldName);
769  22028 parentElement.appendChild(dependenciesElement);
770   
771  22028 for (ExtensionDependency dependency : dependencies) {
772  1498328 Element dependencyElement = document.createElement(ELEMENT_DDEPENDENCY);
773  1498328 dependenciesElement.appendChild(dependencyElement);
774   
775  1498328 addElement(document, dependencyElement, ELEMENT_ID, dependency.getId());
776  1498328 addElement(document, dependencyElement, ELEMENT_VERSION, dependency.getVersionConstraint().getValue());
777  1498328 addElement(document, dependencyElement, ELEMENT_DDOPTIONAL, dependency.isOptional());
778  1498328 addProperties(document, dependencyElement, dependency.getProperties());
779    }
780    }
781    }
782   
 
783  1515026 toggle private void addProperties(Document document, Element parentElement, Map<String, Object> properties)
784    {
785  1515026 if (!properties.isEmpty()) {
786  1484266 Element propertiesElement = document.createElement(ELEMENT_PROPERTIES);
787  1484266 parentElement.appendChild(propertiesElement);
788   
789  1484266 for (Map.Entry<String, Object> entry : properties.entrySet()) {
790  3122487 addElement(document, propertiesElement, entry.getKey(), entry.getValue());
791    }
792    }
793    }
794   
795    // Tools
796   
 
797  7928027 toggle private void addElement(Document document, Element parentElement, String elementName, Object elementValue)
798    {
799  7928027 Element element = CollectionExtensionPropertySerializer.toElement(elementValue, document, elementName,
800    this.serializerByClass);
801   
802  7928027 if (element != null) {
803  4960772 parentElement.appendChild(element);
804    }
805    }
806    }