This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git


The following commit(s) were added to refs/heads/master by this push:
     new 842ec05  Migrating xml tools to standard API
842ec05 is described below

commit 842ec05b5d9c5ff3bcff0d5052384994a478cc27
Author: Martin Stockhammer <[email protected]>
AuthorDate: Sat Sep 28 16:34:10 2019 +0200

    Migrating xml tools to standard API
---
 .../metadata/RepositoryMetadataWriter.java         |  39 +--
 .../archiva-base/archiva-xml-tools/pom.xml         |  17 +-
 .../apache/archiva/xml/ElementTextListClosure.java |  52 ----
 .../java/org/apache/archiva/xml/XMLReader.java     | 313 +++++++++++----------
 .../java/org/apache/archiva/xml/XMLWriter.java     |  95 ++++---
 .../main/java/org/apache/archiva/xml/XmlUtil.java  |  78 +++++
 .../xml/LatinEntityResolutionReaderTest.java       |  26 --
 .../java/org/apache/archiva/xml/XMLReaderTest.java |  21 +-
 .../java/org/apache/archiva/xml/XMLWriterTest.java |  25 +-
 .../maven2/metadata/MavenMetadataReader.java       |  30 +-
 .../RepositoryServletRepositoryGroupTest.java      |   5 +-
 pom.xml                                            |   4 +-
 12 files changed, 371 insertions(+), 334 deletions(-)

diff --git 
a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java
 
b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java
index 5c433ea..0b55736 100644
--- 
a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java
+++ 
b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/metadata/RepositoryMetadataWriter.java
@@ -19,25 +19,23 @@ package org.apache.archiva.repository.metadata;
  * under the License.
  */
 
-import org.apache.archiva.common.utils.FileUtils;
 import org.apache.archiva.model.ArchivaRepositoryMetadata;
 import org.apache.archiva.model.Plugin;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.xml.XMLException;
 import org.apache.archiva.xml.XMLWriter;
+import org.apache.archiva.xml.XmlUtil;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.dom4j.Document;
-import org.dom4j.DocumentHelper;
-import org.dom4j.Element;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
-import java.io.FileWriter;
+import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
-import java.nio.file.Path;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
@@ -81,10 +79,15 @@ public class RepositoryMetadataWriter
     public static void write( ArchivaRepositoryMetadata metadata, Writer 
writer )
         throws RepositoryMetadataException
     {
-        Document doc = DocumentHelper.createDocument();
+        Document doc = null;
+        try {
+            doc = XmlUtil.createDocument();
+        } catch (ParserConfigurationException e) {
+            throw new RepositoryMetadataException("Could not create xml doc " 
+ e.getMessage(), e);
+        }
 
-        Element root = DocumentHelper.createElement( "metadata" );
-        doc.setRootElement( root );
+        Element root = doc.createElement( "metadata" );
+        doc.appendChild(root);
 
         addOptionalElementText( root, "groupId", metadata.getGroupId() );
         addOptionalElementText( root, "artifactId", metadata.getArtifactId() );
@@ -92,16 +95,16 @@ public class RepositoryMetadataWriter
 
         if ( CollectionUtils.isNotEmpty( metadata.getPlugins() ) )
         {
-            Element plugins = root.addElement( "plugins" );
+            Element plugins = XmlUtil.addChild(root, "plugins" );
 
             List<Plugin> pluginList = metadata.getPlugins();
             Collections.sort( pluginList, PluginComparator.INSTANCE );
 
             for ( Plugin plugin : metadata.getPlugins() )
             {
-                Element p = plugins.addElement( "plugin" );
-                p.addElement( "prefix" ).setText( plugin.getPrefix() );
-                p.addElement( "artifactId" ).setText( plugin.getArtifactId() );
+                Element p = XmlUtil.addChild(plugins, "plugin" );
+                XmlUtil.addChild(doc, p, "prefix" ).setTextContent( 
plugin.getPrefix() );
+                XmlUtil.addChild(doc, p, "artifactId" ).setTextContent( 
plugin.getArtifactId() );
                 addOptionalElementText( p, "name", plugin.getName() );
             }
         }
@@ -112,14 +115,14 @@ public class RepositoryMetadataWriter
             || StringUtils.isNotBlank( metadata.getLastUpdated() ) //
             || ( metadata.getSnapshotVersion() != null ) )
         {
-            Element versioning = root.addElement( "versioning" );
+            Element versioning = XmlUtil.addChild(root, "versioning" );
 
             addOptionalElementText( versioning, "latest", 
metadata.getLatestVersion() );
             addOptionalElementText( versioning, "release", 
metadata.getReleasedVersion() );
 
             if ( metadata.getSnapshotVersion() != null )
             {
-                Element snapshot = versioning.addElement( "snapshot" );
+                Element snapshot = XmlUtil.addChild(versioning, "snapshot" );
                 String bnum = String.valueOf( 
metadata.getSnapshotVersion().getBuildNumber() );
                 addOptionalElementText( snapshot, "buildNumber", bnum );
                 addOptionalElementText( snapshot, "timestamp", 
metadata.getSnapshotVersion().getTimestamp() );
@@ -127,12 +130,12 @@ public class RepositoryMetadataWriter
 
             if ( CollectionUtils.isNotEmpty( metadata.getAvailableVersions() ) 
)
             {
-                Element versions = versioning.addElement( "versions" );
+                Element versions = XmlUtil.addChild(versioning, "versions" );
                 Iterator<String> it = 
metadata.getAvailableVersions().iterator();
                 while ( it.hasNext() )
                 {
                     String version = it.next();
-                    versions.addElement( "version" ).setText( version );
+                    XmlUtil.addChild(versions, "version" ).setTextContent( 
version );
                 }
             }
 
@@ -156,7 +159,7 @@ public class RepositoryMetadataWriter
             return;
         }
 
-        elem.addElement( elemName ).setText( text );
+        XmlUtil.addChild(elem, elemName ).setTextContent( text );
     }
 
     private static class PluginComparator
diff --git a/archiva-modules/archiva-base/archiva-xml-tools/pom.xml 
b/archiva-modules/archiva-base/archiva-xml-tools/pom.xml
index 8dc7550..6423d26 100644
--- a/archiva-modules/archiva-base/archiva-xml-tools/pom.xml
+++ b/archiva-modules/archiva-base/archiva-xml-tools/pom.xml
@@ -42,22 +42,11 @@
        <artifactId>commons-collections4</artifactId>
     </dependency>
     <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>dom4j</groupId>
-      <artifactId>dom4j</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>jaxen</groupId>
-      <artifactId>jaxen</artifactId>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
     </dependency>
+
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-utils</artifactId>
-    </dependency>
-     <dependency>
       <groupId>org.apache.archiva</groupId>
       <artifactId>archiva-test-utils</artifactId>
       <version>${project.version}</version>
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/ElementTextListClosure.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/ElementTextListClosure.java
deleted file mode 100644
index 10adbd8..0000000
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/ElementTextListClosure.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.apache.archiva.xml;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import org.apache.commons.collections4.Closure;
-import org.dom4j.Element;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Gather the text from a collection of {@link Element}'s into a {@link List}
- *
- *
- */
-public class ElementTextListClosure
-    implements Closure
-{
-    private List<String> list = new ArrayList<>();
-
-    @Override
-    public void execute( Object input )
-    {
-        if ( input instanceof Element )
-        {
-            Element elem = (Element) input;
-            list.add( elem.getTextTrim() );
-        }
-    }
-
-    public List<String> getList()
-    {
-        return list;
-    }
-}
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLReader.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLReader.java
index ef7b9b2..49073d9 100644
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLReader.java
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLReader.java
@@ -20,29 +20,28 @@ package org.apache.archiva.xml;
  */
 
 import org.apache.commons.lang3.StringUtils;
-import org.dom4j.Attribute;
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.Element;
-import org.dom4j.Namespace;
-import org.dom4j.Node;
-import org.dom4j.QName;
-import org.dom4j.XPath;
-import org.dom4j.io.SAXReader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.*;
+import java.io.*;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * XMLReader - a set of common xml utility methods for reading content out of 
an xml file.
@@ -56,6 +55,25 @@ public class XMLReader
     private Document document;
 
     private Map<String, String> namespaceMap = new HashMap<>();
+    private Map<String, String> reverseNamespaceMap = new HashMap<>();
+
+    private class NamespaceCtx implements NamespaceContext {
+
+        @Override
+        public String getNamespaceURI(String prefix) {
+            return namespaceMap.get(prefix);
+        }
+
+        @Override
+        public String getPrefix(String namespaceURI) {
+            return reverseNamespaceMap.get(namespaceURI);
+        }
+
+        @Override
+        public Iterator getPrefixes(String namespaceURI) {
+            return namespaceMap.keySet().iterator();
+        }
+    }
 
     public XMLReader( String type, Path file )
         throws XMLException
@@ -97,41 +115,69 @@ public class XMLReader
         this.documentType = type;
         this.xmlUrl = url;
 
-        SAXReader reader = new SAXReader();
+        // SAXReader reader = new SAXReader();
 
-        try (InputStream in = url.openStream())
-        {
-            InputStreamReader inReader = new InputStreamReader( in, 
Charset.forName( "UTF-8" ) );
-            LatinEntityResolutionReader latinReader = new 
LatinEntityResolutionReader( inReader );
-            this.document = reader.read( latinReader );
-        }
-        catch ( DocumentException e )
+
+
+        try (InputStream in = url.openStream(); Reader reader = new 
LatinEntityResolutionReader(new BufferedReader(new InputStreamReader(in, 
"UTF-8"))))
         {
-            throw new XMLException( "Unable to parse " + documentType + " xml 
" + xmlUrl + ": " + e.getMessage(), e );
+
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setNamespaceAware(true);
+            dbf.setExpandEntityReferences(false);
+            dbf.setValidating(false);
+            // dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,"false");
+            dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);
+            // 
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            // To suppress error output at System.err
+            db.setErrorHandler(new ErrorHandler() {
+                @Override
+                public void warning(SAXParseException exception) throws 
SAXException {
+
+                }
+
+                @Override
+                public void error(SAXParseException exception) throws 
SAXException {
+                    throw exception;
+                }
+
+                @Override
+                public void fatalError(SAXParseException exception) throws 
SAXException {
+                    throw exception;
+                }
+            });
+            this.document = db.parse(new InputSource(reader));
+
         }
         catch ( IOException e )
         {
             throw new XMLException( "Unable to open stream to " + url + ": " + 
e.getMessage(), e );
+        } catch (ParserConfigurationException e) {
+            throw new XMLException("Unable to start parser "+e.getMessage());
+        } catch (SAXException e) {
+            throw new XMLException("Unable to parse file "+e.getMessage());
         }
 
-        Element root = this.document.getRootElement();
+        Element root = this.document.getDocumentElement();
         if ( root == null )
         {
             throw new XMLException( "Invalid " + documentType + " xml: root 
element is null." );
         }
 
-        if ( !StringUtils.equals( root.getName(), documentType ) )
+        if ( !StringUtils.equals( root.getLocalName(), documentType ) )
         {
             throw new XMLException(
-                "Invalid " + documentType + " xml: Unexpected root element <" 
+ root.getName() + ">, expected <"
-                    + documentType + ">" );
+                "Invalid " + documentType + " xml: Unexpected root element <" 
+ root.getLocalName() + ">, expected <"
+                    + documentType + ">" + root.getNodeName() );
         }
     }
 
     public String getDefaultNamespaceURI()
     {
-        Namespace namespace = this.document.getRootElement().getNamespace();
-        return namespace.getURI();
+        String namespace = this.document.getNamespaceURI();
+        return namespace;
     }
 
     public void addNamespaceMapping( String elementName, String uri )
@@ -142,48 +188,55 @@ public class XMLReader
     public Element getElement( String xpathExpr )
         throws XMLException
     {
-        XPath xpath = createXPath( xpathExpr );
-        Object evaluated = xpath.selectSingleNode( document );
+        XPathExpression xpath = null;
+        try {
+            xpath = createXPath( xpathExpr );
+            Object evaluated = xpath.evaluate( document, XPathConstants.NODE);
 
-        if ( evaluated == null )
-        {
-            return null;
-        }
+            if ( evaluated == null )
+            {
+                return null;
+            }
 
-        if ( evaluated instanceof Element )
-        {
-            return (Element) evaluated;
-        }
-        else
-        {
-            // Unknown evaluated type.
-            throw new XMLException( ".getElement( Expr: " + xpathExpr + " ) 
resulted in non-Element type -> ("
-                                        + evaluated.getClass().getName() + ") 
" + evaluated );
+            if ( evaluated instanceof Element )
+            {
+                return (Element) evaluated;
+            }
+            else
+            {
+                // Unknown evaluated type.
+                throw new XMLException( ".getElement( Expr: " + xpathExpr + " 
) resulted in non-Element type -> ("
+                        + evaluated.getClass().getName() + ") " + evaluated );
+            }
+        } catch (XPathExpressionException e) {
+            throw new XMLException("Could not parse xpath expression");
         }
     }
 
-    private XPath createXPath( String xpathExpr )
-    {
-        XPath xpath = document.createXPath( xpathExpr );
+    private XPathExpression createXPath(String xpathExpr ) throws 
XPathExpressionException {
+        XPath xpath = XPathFactory.newInstance().newXPath();
         if ( !this.namespaceMap.isEmpty() )
         {
-            xpath.setNamespaceURIs( this.namespaceMap );
+            xpath.setNamespaceContext(new NamespaceCtx());
         }
-        return xpath;
+        return xpath.compile(xpathExpr);
     }
 
     public boolean hasElement( String xpathExpr )
         throws XMLException
     {
-        XPath xpath = createXPath( xpathExpr );
-        Object evaluated = xpath.selectSingleNode( document );
-
-        if ( evaluated == null )
-        {
-            return false;
+        XPathExpression xpath = null;
+        try {
+            xpath = createXPath( xpathExpr );
+            Object evaluated = xpath.evaluate( document, XPathConstants.NODE );
+            if ( evaluated == null )
+            {
+                return false;
+            }
+            return true;
+        } catch (XPathExpressionException e) {
+            throw new XMLException("Could not create xpath expression");
         }
-
-        return true;
     }
 
     /**
@@ -191,32 +244,26 @@ public class XMLReader
      */
     public void removeNamespaces()
     {
-        removeNamespaces( this.document.getRootElement() );
+        removeNamespaces( this.document.getDocumentElement() );
     }
 
     /**
      * Remove namespaces from element recursively.
      */
     @SuppressWarnings("unchecked")
-    public void removeNamespaces( Element elem )
+    public void removeNamespaces( Node elem )
     {
-        elem.setQName( QName.get( elem.getName(), Namespace.NO_NAMESPACE, 
elem.getQualifiedName() ) );
+        if (elem.getNodeType() == Node.ELEMENT_NODE || elem.getNodeType() == 
Node.ATTRIBUTE_NODE) {
+            document.renameNode(elem, null, elem.getLocalName());
 
-        Node n;
+            Node n;
 
-        Iterator<Node> it = elem.elementIterator();
-        while ( it.hasNext() )
-        {
-            n = it.next();
+            NodeList nodeList = elem.getChildNodes();
 
-            switch ( n.getNodeType() )
-            {
-                case Node.ATTRIBUTE_NODE:
-                    ( (Attribute) n ).setNamespace( Namespace.NO_NAMESPACE );
-                    break;
-                case Node.ELEMENT_NODE:
-                    removeNamespaces( (Element) n );
-                    break;
+
+            for (int i = 0; i < nodeList.getLength(); i++) {
+                n = nodeList.item(i);
+                removeNamespaces(n);
             }
         }
     }
@@ -224,102 +271,74 @@ public class XMLReader
     public String getElementText( Node context, String xpathExpr )
         throws XMLException
     {
-        XPath xpath = createXPath( xpathExpr );
-        Object evaluated = xpath.selectSingleNode( context );
+        XPathExpression xpath = null;
+        try {
+            xpath = createXPath( xpathExpr );
+            Object evaluated = xpath.evaluate( context, XPathConstants.NODE );
 
-        if ( evaluated == null )
-        {
-            return null;
-        }
+            if ( evaluated == null )
+            {
+                return null;
+            }
 
-        if ( evaluated instanceof Element )
-        {
-            Element evalElem = (Element) evaluated;
-            return evalElem.getTextTrim();
-        }
-        else
-        {
-            // Unknown evaluated type.
-            throw new XMLException( ".getElementText( Node, Expr: " + 
xpathExpr + " ) resulted in non-Element type -> ("
-                                        + evaluated.getClass().getName() + ") 
" + evaluated );
+            if ( evaluated instanceof Element )
+            {
+                Element evalElem = (Element) evaluated;
+                return XmlUtil.getText(evalElem);
+            }
+            else
+            {
+                // Unknown evaluated type.
+                throw new XMLException( ".getElementText( Node, Expr: " + 
xpathExpr + " ) resulted in non-Element type -> ("
+                        + evaluated.getClass().getName() + ") " + evaluated );
+            }
+        } catch (XPathExpressionException e) {
+            throw new XMLException("Could not parse xpath expression");
         }
     }
 
     public String getElementText( String xpathExpr )
         throws XMLException
     {
-        XPath xpath = createXPath( xpathExpr );
-        Object evaluated = xpath.selectSingleNode( document );
-
-        if ( evaluated == null )
-        {
-            return null;
-        }
-
-        if ( evaluated instanceof Element )
-        {
-            Element evalElem = (Element) evaluated;
-            return evalElem.getTextTrim();
-        }
-        else
-        {
-            // Unknown evaluated type.
-            throw new XMLException( ".getElementText( Expr: " + xpathExpr + " 
) resulted in non-Element type -> ("
-                                        + evaluated.getClass().getName() + ") 
" + evaluated );
-        }
+        return getElementText(document, xpathExpr);
     }
 
     @SuppressWarnings("unchecked")
-    public List<Element> getElementList( String xpathExpr )
+    public List<Node> getElementList( String xpathExpr )
         throws XMLException
     {
-        XPath xpath = createXPath( xpathExpr );
-        Object evaluated = xpath.evaluate( document );
+        XPathExpression xpath = null;
+        try {
+            xpath = createXPath( xpathExpr );
+            Object evaluated = xpath.evaluate( document, 
XPathConstants.NODESET);
 
-        if ( evaluated == null )
-        {
-            return null;
-        }
+            if ( evaluated == null )
+            {
+                return Collections.emptyList();
+            }
 
-        /* The xpath.evaluate(Context) method can return:
-         *   1) A Collection or List of dom4j Nodes. 
-         *   2) A single dom4j Node.
-         */
+            NodeList nl = (NodeList) evaluated;
+            List<Node> nodeList = new ArrayList<>();
+            for (int i = 0 ; i<nl.getLength(); i++) {
+                nodeList.add(nl.item(i));
+            }
+            return nodeList;
 
-        if ( evaluated instanceof List )
-        {
-            return (List<Element>) evaluated;
-        }
-        else if ( evaluated instanceof Node )
-        {
-            List<Element> ret = new ArrayList<>();
-            ret.add( (Element) evaluated );
-            return ret;
-        }
-        else
-        {
-            // Unknown evaluated type.
-            throw new XMLException( ".getElementList( Expr: " + xpathExpr + " 
) resulted in non-List type -> ("
-                                        + evaluated.getClass().getName() + ") 
" + evaluated );
+        } catch (XPathExpressionException e) {
+            throw new XMLException("Could not parse xpath expression");
         }
     }
 
     public List<String> getElementListText( String xpathExpr )
         throws XMLException
     {
-        List<Element> elemList = getElementList( xpathExpr );
+        List<Node> elemList = getElementList( xpathExpr );
         if ( elemList == null )
         {
             return null;
         }
 
-        List<String> ret = new ArrayList<>();
-        for ( Iterator<Element> iter = elemList.iterator(); iter.hasNext(); )
-        {
-            Element listelem = iter.next();
-            ret.add( listelem.getTextTrim() );
-        }
-        return ret;
+        return elemList.stream().filter(n -> n instanceof Element).map(n -> 
XmlUtil.getText(n)).collect(Collectors.toList());
     }
 
 }
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLWriter.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLWriter.java
index 0f02ee4..93c8ce8 100644
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLWriter.java
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XMLWriter.java
@@ -19,67 +19,78 @@ package org.apache.archiva.xml;
  * under the License.
  */
 
-import org.dom4j.Document;
-import org.dom4j.io.OutputFormat;
+import org.w3c.dom.Document;
 
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 import java.io.IOException;
 import java.io.Writer;
 
 /**
- * XMLWriter - Making writing XML files easier. 
- *
- *
+ * XMLWriter - Making writing XML files easier.
  */
-public class XMLWriter
-{
+public class XMLWriter {
     /**
      * Write the Document to the provided Writer, leaving the Writer open.
-     * 
-     * @param doc the document to write.
+     *
+     * @param doc    the document to write.
      * @param writer the writer to write to.
      * @throws XMLException if there was a problem writing the xml to the 
writer.
      */
-    public static void write( Document doc, Writer writer )
-        throws XMLException
-    {
-        write( doc, writer, false );
+    public static void write(Document doc, Writer writer)
+            throws XMLException {
+        write(doc, writer, false);
     }
 
     /**
      * Write the Document to the provided Writer, with an option to close the 
writer upon completion.
-     * 
-     * @param doc the document to write.
+     *
+     * @param doc    the document to write.
      * @param writer the writer to write to.
-     * @param close true to close the writer on completion.
+     * @param close  true to close the writer on completion.
      * @throws XMLException if there was a problem writing the xml to the 
writer.
      */
-    public static void write( Document doc, Writer writer, boolean close )
-        throws XMLException
-    {
-        org.dom4j.io.XMLWriter xmlwriter = null;
+    public static void write(Document doc, Writer writer, boolean close)
+            throws XMLException {
 
-        try
-        {
-            OutputFormat outputFormat = OutputFormat.createPrettyPrint();
-            xmlwriter = new org.dom4j.io.XMLWriter( writer, outputFormat );
-            xmlwriter.write( doc );
-            xmlwriter.flush();
-        }
-        catch ( IOException e )
-        {
-            throw new XMLException( "Unable to write xml contents to writer: " 
+ e.getMessage(), e );
-        }
-        finally
-        {
-            if ( close && ( xmlwriter != null ) )
-            {
-                try
-                {
-                    xmlwriter.close();
-                }
-                catch ( IOException e )
-                {
-                    /* quietly ignore */
+        try {
+            TransformerFactory transformerFactory = 
TransformerFactory.newInstance();
+            Transformer transformer = transformerFactory.newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            try {
+                
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount";, "2");
+            } catch (IllegalArgumentException ex) {
+                // Indent not supported
+            }
+            // Writing the XML declaration, because the JDK implementation 
does not create a newline
+            writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+            StreamResult result = new StreamResult(writer);
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, 
"yes");
+            DOMSource source = new DOMSource(doc);
+            transformer.transform(source, result);
+
+
+        } catch (TransformerException e) {
+            throw new XMLException("Could not create the xml transformer: " + 
e.getMessage(), e);
+        } catch (IOException e) {
+            throw new XMLException("Could not write to xml output: " + 
e.getMessage(), e);
+        } finally {
+            if (writer!=null) {
+                if (close) {
+                    try {
+                        writer.flush();
+                    } catch (IOException e) {
+                        /* quietly ignore */
+                    }
+                    try {
+                        writer.close();
+                    } catch (IOException e) {
+                        /* quietly ignore */
+                    }
                 }
             }
         }
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XmlUtil.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XmlUtil.java
new file mode 100644
index 0000000..86024fb
--- /dev/null
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XmlUtil.java
@@ -0,0 +1,78 @@
+package org.apache.archiva.xml;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.w3c.dom.*;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class XmlUtil {
+
+
+    public static Document createDocument() throws 
ParserConfigurationException {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        return builder.newDocument();
+    }
+
+    public static Element addChild(Document doc, Element parent, String name) {
+        Element el = doc.createElement(name);
+        parent.appendChild(el);
+        return el;
+    }
+
+    public static Element addChild(Element parent, String name) {
+        Document doc = parent.getOwnerDocument();
+        Element el = doc.createElement(name);
+        parent.appendChild(el);
+        return el;
+    }
+
+    public static String getText(Node element) {
+        if (element!=null) {
+            element.normalize();
+            try {
+                String txt = element.getTextContent();
+                if (txt!=null) {
+                    return txt.trim();
+                }
+            } catch (DOMException e) {
+                return "";
+            }
+        }
+        return "";
+    }
+
+    public static Node getChild(Element parent, String name) {
+        NodeList elList = parent.getElementsByTagName(name);
+        if (elList.getLength()>0) {
+            return elList.item(0);
+        } else {
+            return null;
+        }
+    }
+
+    public static String getChildText(Element parent, String name) {
+        return getText(getChild(parent, name));
+    }
+
+}
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/LatinEntityResolutionReaderTest.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/LatinEntityResolutionReaderTest.java
index c3c7dd0..8b99066 100644
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/LatinEntityResolutionReaderTest.java
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/LatinEntityResolutionReaderTest.java
@@ -19,8 +19,6 @@ package org.apache.archiva.xml;
  * under the License.
  */
 
-import org.dom4j.DocumentException;
-import org.dom4j.io.SAXReader;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -204,30 +202,6 @@ public class LatinEntityResolutionReaderTest
         assertProperRead( expected, "no-prolog-with-entities.xml", 409600 );
     }
 
-    @Test
-    public void testReaderLeftOver()
-        throws IOException
-    {
-        Path inputFile = getExampleXml( "maven-metadata-leftover.xml" );
-        //Bits from RepositoryMetadataReader.read
-        InputStream in = null;
-        SAXReader reader = new SAXReader();
-        URL url = inputFile.toUri().toURL();
-        in = url.openStream();
-        InputStreamReader inReader = new InputStreamReader( in, 
Charset.forName( "UTF-8" ) );
-        LatinEntityResolutionReader latinReader = new 
LatinEntityResolutionReader( inReader );
-        try
-        {
-            reader.read( latinReader );
-        }
-        catch ( DocumentException e )
-        {
-            Assert.fail( "Should not have failed here." + e );
-            IOException ioe = new IOException();
-            ioe.initCause( e );
-            throw ioe;
-        }
-    }
 
     @Test
     public void testNoLatinEntitiesHugeLine()
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLReaderTest.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLReaderTest.java
index 3dc1382..610ffcb 100644
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLReaderTest.java
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLReaderTest.java
@@ -19,8 +19,9 @@ package org.apache.archiva.xml;
  * under the License.
  */
 
-import org.dom4j.Element;
 import org.junit.Test;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -34,14 +35,14 @@ import java.util.List;
 public class XMLReaderTest
     extends AbstractArchivaXmlTestCase
 {
-    private void assertElementTexts( List<Element> elementList, String[] 
expectedTexts )
+    private void assertElementTexts( List<Node> elementList, String[] 
expectedTexts )
     {
         assertEquals( "Element List Size", expectedTexts.length, 
elementList.size() );
 
         List<String> texts = new ArrayList<>();
-        for ( Element element : elementList )
+        for ( Node element : elementList )
         {
-            texts.add( element.getTextTrim() );
+            texts.add( element.getTextContent().trim());
         }
 
         for ( int i = 0; i < expectedTexts.length; i++ )
@@ -58,7 +59,7 @@ public class XMLReaderTest
         Path xmlFile = getExampleXml( "no-prolog-basic.xml" );
         XMLReader reader = new XMLReader( "basic", xmlFile );
 
-        List<Element> fruits = reader.getElementList( "//basic/fruits/fruit" );
+        List<Node> fruits = reader.getElementList( "//basic/fruits/fruit" );
         assertElementTexts( fruits, new String[] { "apple", "cherry", "pear", 
"peach" } );
     }
 
@@ -69,7 +70,7 @@ public class XMLReaderTest
         Path xmlFile = getExampleXml( "no-prolog-with-entities.xml" );
         XMLReader reader = new XMLReader( "basic", xmlFile );
 
-        List<Element> names = reader.getElementList( "//basic/names/name" );
+        List<Node> names = reader.getElementList( "//basic/names/name" );
         assertElementTexts( names, new String[] { TRYGVIS, INFINITE_ARCHIVA } 
);
     }
 
@@ -80,7 +81,7 @@ public class XMLReaderTest
         Path xmlFile = getExampleXml( "no-prolog-with-utf8.xml" );
         XMLReader reader = new XMLReader( "basic", xmlFile );
 
-        List<Element> names = reader.getElementList( "//basic/names/name" );
+        List<Node> names = reader.getElementList( "//basic/names/name" );
         assertElementTexts( names, new String[] { TRYGVIS, INFINITE_ARCHIVA } 
);
     }
 
@@ -91,7 +92,7 @@ public class XMLReaderTest
         Path xmlFile = getExampleXml( "prolog-with-utf8.xml" );
         XMLReader reader = new XMLReader( "basic", xmlFile );
 
-        List<Element> names = reader.getElementList( "//basic/names/name" );
+        List<Node> names = reader.getElementList( "//basic/names/name" );
         assertElementTexts( names, new String[] { TRYGVIS, INFINITE_ARCHIVA } 
);
     }
     
@@ -104,9 +105,9 @@ public class XMLReaderTest
         XMLReader reader = new XMLReader( "metadata", xmlFile );
         reader.removeNamespaces();
         
-        Element groupId = reader.getElement( "//metadata/groupId" );        
+        Element groupId = (Element) reader.getElement( "//metadata/groupId" );
         assertNotNull( groupId );
-        assertEquals( "org.codehaus.mojo", groupId.getTextTrim() );   
+        assertEquals( "org.codehaus.mojo", groupId.getTextContent().trim() );
     }
 
 }
diff --git 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLWriterTest.java
 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLWriterTest.java
index 9ff014b..9ab1a4c 100644
--- 
a/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLWriterTest.java
+++ 
b/archiva-modules/archiva-base/archiva-xml-tools/src/test/java/org/apache/archiva/xml/XMLWriterTest.java
@@ -19,11 +19,12 @@ package org.apache.archiva.xml;
  * under the License.
  */
 
-import org.dom4j.Document;
-import org.dom4j.DocumentHelper;
-import org.dom4j.Element;
 import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.StringWriter;
 
 /**
@@ -41,7 +42,6 @@ public class XMLWriterTest
         StringBuilder expected = new StringBuilder();
 
         expected.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
-        expected.append( "\n" );
         expected.append( "<basic>\n" );
         expected.append( "  <names>\n" );
         expected.append( "    <name>" ).append( TRYGVIS ).append( "</name>\n" 
);
@@ -49,12 +49,19 @@ public class XMLWriterTest
         expected.append( "  </names>\n" );
         expected.append( "</basic>\n" );
 
-        Element basic = DocumentHelper.createElement( "basic" );
-        Document doc = DocumentHelper.createDocument( basic );
+        DocumentBuilder docBuilder = 
DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+        Element basic = doc.createElement("basic");
+        doc.appendChild(basic);
+        Element names = doc.createElement( "names" );
+        basic.appendChild(names);
+        Element name = doc.createElement("name");
+        name.setTextContent(TRYGVIS);
+        names.appendChild(name);
+        name = doc.createElement("name");
+        name.setTextContent(INFINITE_ARCHIVA);
 
-        Element names = basic.addElement( "names" );
-        names.addElement( "name" ).setText( TRYGVIS );
-        names.addElement( "name" ).setText( INFINITE_ARCHIVA );
+        names.appendChild(name);
 
         StringWriter actual = new StringWriter();
         XMLWriter.write( doc, actual );
diff --git 
a/archiva-modules/archiva-maven/archiva-maven-metadata/src/main/java/org/apache/archiva/maven2/metadata/MavenMetadataReader.java
 
b/archiva-modules/archiva-maven/archiva-maven-metadata/src/main/java/org/apache/archiva/maven2/metadata/MavenMetadataReader.java
index 76939e3..405c947 100644
--- 
a/archiva-modules/archiva-maven/archiva-maven-metadata/src/main/java/org/apache/archiva/maven2/metadata/MavenMetadataReader.java
+++ 
b/archiva-modules/archiva-maven/archiva-maven-metadata/src/main/java/org/apache/archiva/maven2/metadata/MavenMetadataReader.java
@@ -24,10 +24,12 @@ import org.apache.archiva.model.SnapshotVersion;
 import org.apache.archiva.repository.storage.StorageAsset;
 import org.apache.archiva.xml.XMLException;
 import org.apache.archiva.xml.XMLReader;
+import org.apache.archiva.xml.XmlUtil;
 import org.apache.commons.lang3.math.NumberUtils;
-import org.dom4j.Element;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -115,22 +117,28 @@ public class MavenMetadataReader
         if ( snapshotElem != null )
         {
             SnapshotVersion snapshot = new SnapshotVersion();
-            snapshot.setTimestamp( snapshotElem.elementTextTrim( "timestamp" ) 
);
-            String tmp = snapshotElem.elementTextTrim( "buildNumber" );
-            if ( NumberUtils.isNumber( tmp ) )
+            snapshot.setTimestamp(XmlUtil.getChildText(snapshotElem, 
"timestamp"));
+            String buildNumber = XmlUtil.getChildText(snapshotElem, 
"buildNumber");
+            if ( NumberUtils.isCreatable( buildNumber ) )
             {
-                snapshot.setBuildNumber( NumberUtils.toInt( tmp ) );
+                snapshot.setBuildNumber( NumberUtils.toInt( buildNumber ) );
             }
             metadata.setSnapshotVersion( snapshot );
         }
 
-        for ( Element plugin : xml.getElementList( "//metadata/plugins/plugin" 
) )
+        for ( Node node : xml.getElementList( "//metadata/plugins/plugin" ) )
         {
-            Plugin p = new Plugin();
-            p.setPrefix( plugin.elementTextTrim( "prefix" ) );
-            p.setArtifactId( plugin.elementTextTrim( "artifactId" ) );
-            p.setName( plugin.elementTextTrim( "name" ) );
-            metadata.addPlugin( p );
+            if (node instanceof Element) {
+                Element plugin = (Element) node;
+                Plugin p = new Plugin();
+                String prefix = 
plugin.getElementsByTagName("prefix").item(0).getTextContent().trim();
+                p.setPrefix(prefix);
+                String artifactId = 
plugin.getElementsByTagName("artifactId").item(0).getTextContent().trim();
+                p.setArtifactId(artifactId);
+                String name = 
plugin.getElementsByTagName("name").item(0).getTextContent().trim();
+                p.setName(name);
+                metadata.addPlugin(p);
+            }
         }
 
         return metadata;
diff --git 
a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletRepositoryGroupTest.java
 
b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletRepositoryGroupTest.java
index e8273c4..b634bfd 100644
--- 
a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletRepositoryGroupTest.java
+++ 
b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/RepositoryServletRepositoryGroupTest.java
@@ -258,7 +258,6 @@ public class RepositoryServletRepositoryGroupTest
         WebResponse response = getServletUnitClient().getResource( request );
 
         Path returnedMetadata = getProjectBase().resolve( 
"target/test-classes/retrievedMetadataFile.xml" );
-        System.out.println( response.getContentAsString() );
         org.apache.archiva.common.utils.FileUtils.writeStringToFile( 
returnedMetadata, Charset.defaultCharset(), response.getContentAsString() );
         ArchivaRepositoryMetadata metadata = MavenMetadataReader.read( 
returnedMetadata );
 
@@ -285,7 +284,7 @@ public class RepositoryServletRepositoryGroupTest
         assertResponseOK( response );
 
         assertThat( response.getContentAsString() )
-            .startsWith( "add113b0d7f8c6adb92a5015a7a3701081edf998" );
+            .startsWith( "f8a7a858a46887368adf0b30874de1f807d91453" );
 
         // request the md5 checksum of the metadata
         request = new GetMethodWebRequest( "http://machine.com/repository/"; + 
REPO_GROUP_WITH_VALID_REPOS + "/dummy/"
@@ -295,7 +294,7 @@ public class RepositoryServletRepositoryGroupTest
         assertResponseOK( response );
 
         assertThat( response.getContentAsString() )
-            .startsWith( "5b85ea4aa5f52bb76760041a52f98de8" );
+            .startsWith( "cec864b66849153dd45fddb7cdde12b2" );
     }
 
     // MRM-901
diff --git a/pom.xml b/pom.xml
index a853c52..0414084 100644
--- a/pom.xml
+++ b/pom.xml
@@ -800,9 +800,9 @@
         <version>${derbyVersion}</version>
       </dependency>
       <dependency>
-        <groupId>dom4j</groupId>
+        <groupId>org.dom4j</groupId>
         <artifactId>dom4j</artifactId>
-        <version>1.6.1</version>
+        <version>2.1.1</version>
       </dependency>
       <dependency>
         <groupId>org.hsqldb</groupId>

Reply via email to