View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   */
19  package org.apache.rat.testhelpers;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.io.OutputStreamWriter;
27  import java.io.PrintStream;
28  import java.io.StringReader;
29  import java.io.UnsupportedEncodingException;
30  import java.lang.reflect.UndeclaredThrowableException;
31  
32  import javax.xml.parsers.DocumentBuilder;
33  import javax.xml.parsers.DocumentBuilderFactory;
34  import javax.xml.parsers.FactoryConfigurationError;
35  import javax.xml.parsers.ParserConfigurationException;
36  import javax.xml.parsers.SAXParserFactory;
37  import javax.xml.transform.OutputKeys;
38  import javax.xml.transform.Transformer;
39  import javax.xml.transform.TransformerException;
40  import javax.xml.transform.TransformerFactory;
41  import javax.xml.transform.dom.DOMSource;
42  import javax.xml.transform.stream.StreamResult;
43  import javax.xml.xpath.XPath;
44  import javax.xml.xpath.XPathConstants;
45  import javax.xml.xpath.XPathExpressionException;
46  
47  import org.apache.rat.license.ILicenseFamily;
48  import org.apache.rat.report.xml.writer.IXmlWriter;
49  import org.w3c.dom.Document;
50  import org.w3c.dom.Node;
51  import org.w3c.dom.NodeList;
52  import org.xml.sax.InputSource;
53  import org.xml.sax.SAXException;
54  import org.xml.sax.XMLReader;
55  
56  public final class XmlUtils {
57      /**
58       * Private constructor, to prevent accidental instantiation.
59       */
60      private XmlUtils() {
61          // Does nothing
62      }
63  
64      public static final boolean isWellFormedXml(final String string) throws Exception {
65          return isWellFormedXml(new InputSource(new StringReader(string)));
66      }
67  
68      public static final XMLReader newXMLReader() throws SAXException, ParserConfigurationException {
69          final SAXParserFactory spf = SAXParserFactory.newInstance();
70          spf.setValidating(false);
71          spf.setNamespaceAware(true);
72          return spf.newSAXParser().getXMLReader();
73      }
74  
75      public static final boolean isWellFormedXml(final InputSource isource) {
76          try {
77              newXMLReader().parse(isource);
78              return true;
79          } catch (SAXException e) {
80              e.printStackTrace();
81              return false;
82          } catch (IOException | ParserConfigurationException e) {
83              throw new UndeclaredThrowableException(e);
84          }
85      }
86  
87      /**
88       * Finds a node via xpath on the document. And then checks family, approval and
89       * type of elements of the node.
90       * 
91       * @param doc The document to check/
92       * @param xpath the XPath instance to use.
93       * @param resource the xpath statement to locate the node.
94       * @param family the expected family for the node (may be null)
95       * @param approval the expected approval value (may be null)
96       * @param type the type of resource located.
97       * @return The node that was located
98       * @throws Exception on XPath error.
99       */
100     public static Node checkNode(Document doc, XPath xpath, String resource, String family, String approval,
101             String type) throws Exception {
102         Node root = getNode(doc, xpath, String.format("/rat-report/resource[@name='%s']", resource));
103         if (family != null) {
104             getNode(root, xpath, String.format("header-type[@name='%s']", ILicenseFamily.makeCategory(family)));
105             getNode(root, xpath, "license-family[@name]");
106             if (family.equals("?????")) {
107                 getNode(root, xpath, "header-sample");
108             }
109         }
110         if (approval != null) {
111             getNode(root, xpath, String.format("license-approval[@name='%s']", approval));
112         }
113         getNode(root, xpath, String.format("type[@name='%s']", type));
114         return root;
115     }
116 
117     public static Node getNode(Object source, XPath xPath, String xpath) throws XPathExpressionException {
118         NodeList nodeList = (NodeList) xPath.compile(xpath).evaluate(source, XPathConstants.NODESET);
119         assertEquals(1, nodeList.getLength(), "Could not find " + xpath);
120         return nodeList.item(0);
121     }
122 
123     public static final boolean isWellFormedXml(final InputStream in) throws Exception {
124         return isWellFormedXml(new InputSource(in));
125     }
126 
127     public static final Document toDom(final InputStream in)
128             throws SAXException, IOException, ParserConfigurationException, FactoryConfigurationError {
129         final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
130         Document result;
131         result = builder.parse(in);
132         return result;
133     }
134 
135     public static final void writeAttribute(final IXmlWriter writer, final String name, final boolean booleanValue)
136             throws IOException {
137         final String value = Boolean.toString(booleanValue);
138         writer.attribute(name, value);
139     }
140 
141     /**
142      * Print the and XML document to the output stream
143      * 
144      * @param out the OutputStream to print the document to.
145      * @param document The XML DOM document to print
146      */
147     public static void printDocument(OutputStream out, Document document) {
148         TransformerFactory tf = TransformerFactory.newInstance();
149         Transformer transformer;
150         try {
151             transformer = tf.newTransformer();
152 
153             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
154             transformer.setOutputProperty(OutputKeys.METHOD, "xml");
155             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
156             transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
157             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
158 
159             transformer.transform(new DOMSource(document), new StreamResult(new OutputStreamWriter(out, "UTF-8")));
160         } catch (TransformerException | UnsupportedEncodingException e) {
161             e.printStackTrace(new PrintStream(out));
162         }
163     }
164 
165 }