From 842ec05b5d9c5ff3bcff0d5052384994a478cc27 Mon Sep 17 00:00:00 2001 From: Martin Stockhammer Date: Sat, 28 Sep 2019 16:34:10 +0200 Subject: [PATCH] Migrating xml tools to standard API --- .../metadata/RepositoryMetadataWriter.java | 39 ++- .../archiva-base/archiva-xml-tools/pom.xml | 17 +- .../archiva/xml/ElementTextListClosure.java | 52 --- .../org/apache/archiva/xml/XMLReader.java | 313 ++++++++++-------- .../org/apache/archiva/xml/XMLWriter.java | 95 +++--- .../java/org/apache/archiva/xml/XmlUtil.java | 78 +++++ .../xml/LatinEntityResolutionReaderTest.java | 26 -- .../org/apache/archiva/xml/XMLReaderTest.java | 21 +- .../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(-) delete mode 100644 archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/ElementTextListClosure.java create mode 100644 archiva-modules/archiva-base/archiva-xml-tools/src/main/java/org/apache/archiva/xml/XmlUtil.java 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 5c433ea5d..0b5573676 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 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 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 8dc755071..6423d268e 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 @@ commons-collections4 - commons-io - commons-io - - - dom4j - dom4j - - - jaxen - jaxen + org.apache.commons + commons-lang3 + - org.codehaus.plexus - plexus-utils - - org.apache.archiva archiva-test-utils ${project.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 10adbd85c..000000000 --- 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 list = new ArrayList<>(); - - @Override - public void execute( Object input ) - { - if ( input instanceof Element ) - { - Element elem = (Element) input; - list.add( elem.getTextTrim() ); - } - } - - public List 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 ef7b9b2a5..49073d930 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 namespaceMap = new HashMap<>(); + private Map 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 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 getElementList( String xpathExpr ) + public List 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 nodeList = new ArrayList<>(); + for (int i = 0 ; i) evaluated; - } - else if ( evaluated instanceof Node ) - { - List 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 getElementListText( String xpathExpr ) throws XMLException { - List elemList = getElementList( xpathExpr ); + List elemList = getElementList( xpathExpr ); if ( elemList == null ) { return null; } - List ret = new ArrayList<>(); - for ( Iterator 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 0f02ee44a..93c8ce84c 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("\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 000000000..86024fb49 --- /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 c3c7dd0de..8b99066b1 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 3dc13825d..610ffcbb1 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 elementList, String[] expectedTexts ) + private void assertElementTexts( List elementList, String[] expectedTexts ) { assertEquals( "Element List Size", expectedTexts.length, elementList.size() ); List 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 fruits = reader.getElementList( "//basic/fruits/fruit" ); + List 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 names = reader.getElementList( "//basic/names/name" ); + List 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 names = reader.getElementList( "//basic/names/name" ); + List 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 names = reader.getElementList( "//basic/names/name" ); + List 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 9ff014b6f..9ab1a4cf6 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( "\n" ); - expected.append( "\n" ); expected.append( "\n" ); expected.append( " \n" ); expected.append( " " ).append( TRYGVIS ).append( "\n" ); @@ -49,12 +49,19 @@ public class XMLWriterTest expected.append( " \n" ); expected.append( "\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 76939e31e..405c94712 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 e8273c485..b634bfd3e 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 a853c52f9..0414084c4 100644 --- a/pom.xml +++ b/pom.xml @@ -800,9 +800,9 @@ ${derbyVersion} - dom4j + org.dom4j dom4j - 1.6.1 + 2.1.1 org.hsqldb -- 2.39.5