Coverage Report - net.mtu.eggplant.xml.XMLUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLUtils
10%
8/77
0%
0/16
2.455
XMLUtils$1
50%
1/2
N/A
2.455
XMLUtils$2
20%
1/5
N/A
2.455
XMLUtils$3
0%
0/5
N/A
2.455
XMLUtils$4
0%
0/5
N/A
2.455
XMLUtils$5
0%
0/5
N/A
2.455
 
 1  
 /*
 2  
  * Copyright (c) 2008
 3  
  *      Jon Schewe.  All rights reserved
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met:
 8  
  * 1. Redistributions of source code must retain the above copyright
 9  
  *    notice, this list of conditions and the following disclaimer.
 10  
  * 2. Redistributions in binary form must reproduce the above copyright
 11  
  *    notice, this list of conditions and the following disclaimer in the
 12  
  *    documentation and/or other materials provided with the distribution.
 13  
  *
 14  
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 15  
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16  
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 17  
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 18  
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 19  
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 20  
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 21  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 22  
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 23  
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 24  
  * SUCH DAMAGE.
 25  
  *
 26  
  * I'd appreciate comments/suggestions on the code jpschewe@mtu.net
 27  
  */
 28  
 package net.mtu.eggplant.xml;
 29  
 
 30  
 import java.io.IOException;
 31  
 import java.io.InputStream;
 32  
 import java.io.Reader;
 33  
 import java.io.StringReader;
 34  
 import java.io.Writer;
 35  
 import java.text.DateFormat;
 36  
 import java.text.SimpleDateFormat;
 37  
 
 38  
 import javax.xml.parsers.DocumentBuilder;
 39  
 import javax.xml.parsers.DocumentBuilderFactory;
 40  
 import javax.xml.parsers.ParserConfigurationException;
 41  
 import javax.xml.transform.OutputKeys;
 42  
 import javax.xml.transform.Transformer;
 43  
 import javax.xml.transform.TransformerException;
 44  
 import javax.xml.transform.TransformerFactory;
 45  
 import javax.xml.transform.dom.DOMSource;
 46  
 import javax.xml.transform.stream.StreamResult;
 47  
 import javax.xml.validation.Schema;
 48  
 
 49  
 import org.slf4j.Logger;
 50  
 import org.slf4j.LoggerFactory;
 51  
 import org.w3c.dom.Document;
 52  
 import org.w3c.dom.Element;
 53  
 import org.xml.sax.ErrorHandler;
 54  
 import org.xml.sax.InputSource;
 55  
 import org.xml.sax.SAXException;
 56  
 import org.xml.sax.SAXParseException;
 57  
 
 58  
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 59  
 import net.mtu.eggplant.io.IOUtils;
 60  
 
 61  
 /**
 62  
  * Some utilities for working with XML.
 63  
  */
 64  0
 public class XMLUtils {
 65  
 
 66  1
   private static final Logger LOGGER = LoggerFactory.getLogger(XMLUtils.class);
 67  
 
 68  
   /**
 69  
    * Date format for time type.
 70  
    */
 71  1
   public static final ThreadLocal<DateFormat> XML_TIME_FORMAT = new ThreadLocal<DateFormat>() {
 72  
     @Override
 73  
     protected DateFormat initialValue() {
 74  0
       return new SimpleDateFormat("HH:mm:ss");
 75  
     }
 76  
   };
 77  
 
 78  
   public static final DocumentBuilder DOCUMENT_BUILDER;
 79  
 
 80  
   // create basic document builder
 81  
   static {
 82  
     try {
 83  1
       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 84  1
       factory.setNamespaceAware(true);
 85  1
       DOCUMENT_BUILDER = factory.newDocumentBuilder();
 86  1
       DOCUMENT_BUILDER.setErrorHandler(new ErrorHandler() {
 87  
         public void error(final SAXParseException spe) throws SAXParseException {
 88  0
           throw spe;
 89  
         }
 90  
 
 91  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 92  0
           throw spe;
 93  
         }
 94  
 
 95  
         public void warning(final SAXParseException spe) throws SAXParseException {
 96  0
           System.err.println(spe.getMessage());
 97  0
         }
 98  
       });
 99  0
     } catch (final ParserConfigurationException pce) {
 100  0
       throw new RuntimeException(pce.getMessage(), pce);
 101  1
     }
 102  1
   }
 103  
 
 104  
   /**
 105  
    * Parse the document from the given stream. The document is validated with
 106  
    * the specified schema. Does not close the stream after reading. Warnings are
 107  
    * output to the logger for this class.
 108  
    * 
 109  
    * @param stream a stream containing document
 110  
    * @return the document
 111  
    * @throws IOException if there is an error reading the stream
 112  
    * @throws SAXException if there is an error parsing the document or it
 113  
    *           doesn't match the schema
 114  
    * @throws RuntimeException if there is an error configuring the XML parser,
 115  
    *           this shouldn't happen
 116  
    */
 117  
   public static Document parse(final Reader stream,
 118  
                                final Schema schema)
 119  
       throws IOException, SAXException {
 120  
     try {
 121  0
       final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 122  0
       builderFactory.setNamespaceAware(true);
 123  0
       builderFactory.setSchema(schema);
 124  0
       builderFactory.setIgnoringComments(true);
 125  0
       builderFactory.setIgnoringElementContentWhitespace(true);
 126  0
       final DocumentBuilder parser = builderFactory.newDocumentBuilder();
 127  
 
 128  0
       parser.setErrorHandler(new ErrorHandler() {
 129  
         public void error(final SAXParseException spe) throws SAXParseException {
 130  0
           throw spe;
 131  
         }
 132  
 
 133  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 134  0
           throw spe;
 135  
         }
 136  
 
 137  
         public void warning(final SAXParseException spe) throws SAXParseException {
 138  0
           LOGGER.error(spe.getMessage(), spe);
 139  0
         }
 140  
       });
 141  
 
 142  
       // parse
 143  0
       final String content = IOUtils.readIntoString(stream);
 144  0
       final Document document = parser.parse(new InputSource(new StringReader(content)));
 145  
 
 146  0
       return document;
 147  0
     } catch (ParserConfigurationException e) {
 148  0
       throw new RuntimeException("Error configuring the XML parser", e);
 149  
     }
 150  
   }
 151  
 
 152  
   /**
 153  
    * Parse xmlDoc an XML document. Just does basic parsing, no validity checks.
 154  
    * Does not close the stream after parsing. Warnings are output to the logger
 155  
    * for this class.
 156  
    * 
 157  
    * @throws IOException if there is an error reading the stream
 158  
    * @throws SAXException if the document is found to be invalid
 159  
    * @throws RuntimeException if there is an error configuring the XML parser,
 160  
    *           this shouldn't happen
 161  
    */
 162  
   public static Document parseXMLDocument(final InputStream xmlDocStream) throws SAXException, IOException {
 163  
     try {
 164  0
       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 165  0
       factory.setNamespaceAware(true);
 166  0
       factory.setIgnoringComments(true);
 167  0
       factory.setIgnoringElementContentWhitespace(true);
 168  
 
 169  0
       final DocumentBuilder parser = factory.newDocumentBuilder();
 170  0
       parser.setErrorHandler(new ErrorHandler() {
 171  
         public void error(final SAXParseException spe) throws SAXParseException {
 172  0
           throw spe;
 173  
         }
 174  
 
 175  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 176  0
           throw spe;
 177  
         }
 178  
 
 179  
         public void warning(final SAXParseException spe) throws SAXParseException {
 180  0
           LOGGER.error(spe.getMessage());
 181  0
         }
 182  
       });
 183  
 
 184  0
       final Document document = parser.parse(xmlDocStream);
 185  0
       return document;
 186  0
     } catch (final ParserConfigurationException pce) {
 187  0
       throw new RuntimeException("Error configuring the XML parser", pce);
 188  
     }
 189  
   }
 190  
 
 191  
   /**
 192  
    * Parse xmlDoc an XML document. Just does basic parsing, no validity checks.
 193  
    * Does not close the stream after parsing. Warnings are output to the logger
 194  
    * for this class.
 195  
    * 
 196  
    * @throws IOException if there is an error reading the stream
 197  
    * @throws SAXException if the document is found to be invalid
 198  
    * @throws RuntimeException if there is an error configuring the XML parser,
 199  
    *           this shouldn't happen
 200  
    */
 201  
   public static Document parseXMLDocument(final Reader xmlDocStream) throws SAXException, IOException {
 202  0
     final String content = IOUtils.readIntoString(xmlDocStream);
 203  0
     return parseXMLDocument(new InputSource(new StringReader(content)));
 204  
   }
 205  
 
 206  
   /**
 207  
    * Parse xmlDoc an XML document. Just does basic parsing, no validity checks.
 208  
    * Does not close the stream after parsing. Warnings are output to the logger
 209  
    * for this class.
 210  
    * 
 211  
    * @throws IOException if there is an error reading the stream
 212  
    * @throws SAXException if the document is found to be invalid
 213  
    * @throws RuntimeException if there is an error configuring the XML parser,
 214  
    *           this shouldn't happen
 215  
    */
 216  
   public static Document parseXMLDocument(final InputSource xmlDocStream) throws SAXException, IOException {
 217  
     try {
 218  0
       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 219  0
       factory.setNamespaceAware(true);
 220  0
       factory.setIgnoringComments(true);
 221  0
       factory.setIgnoringElementContentWhitespace(true);
 222  
 
 223  0
       final DocumentBuilder parser = factory.newDocumentBuilder();
 224  0
       parser.setErrorHandler(new ErrorHandler() {
 225  
         public void error(final SAXParseException spe) throws SAXParseException {
 226  0
           throw spe;
 227  
         }
 228  
 
 229  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 230  0
           throw spe;
 231  
         }
 232  
 
 233  
         public void warning(final SAXParseException spe) throws SAXParseException {
 234  0
           LOGGER.error(spe.getMessage());
 235  0
         }
 236  
       });
 237  
 
 238  0
       final Document document = parser.parse(xmlDocStream);
 239  0
       return document;
 240  0
     } catch (final ParserConfigurationException pce) {
 241  0
       throw new RuntimeException("Error configuring the XML parser", pce);
 242  
     }
 243  
   }
 244  
 
 245  
   /**
 246  
    * @see #getDoubleAttributeValue(Element, String)
 247  
    */
 248  
   public static String getStringAttributeValue(final Element element,
 249  
                                                final String attributeName) {
 250  0
     if (null == element) {
 251  0
       return null;
 252  
     }
 253  0
     final String str = element.getAttribute(attributeName);
 254  0
     return str;
 255  
   }
 256  
 
 257  
   /**
 258  
    * @see #getDoubleAttributeValue(Element, String)
 259  
    */
 260  
   @SuppressFBWarnings(value = { "NP_BOOLEAN_RETURN_NULL" }, justification = "Need to return Null so that we can determine when there is no score")
 261  
   public static Boolean getBooleanAttributeValue(final Element element,
 262  
                                                  final String attributeName) {
 263  0
     if (null == element) {
 264  0
       return null;
 265  
     }
 266  0
     final String str = element.getAttribute(attributeName);
 267  0
     if (null == str
 268  0
         || "".equals(str)) {
 269  0
       return null;
 270  
     } else {
 271  0
       return Boolean.valueOf(str);
 272  
     }
 273  
   }
 274  
 
 275  
   /**
 276  
    * Get a double value from an attribute.
 277  
    * 
 278  
    * @param element the element to get the attribute from, may be null
 279  
    * @param attributeName the attribute name to get
 280  
    * @return the value, null if element is null or the attribute value is null
 281  
    *         or empty
 282  
    */
 283  
   public static Double getDoubleAttributeValue(final Element element,
 284  
                                                final String attributeName) {
 285  0
     if (null == element) {
 286  0
       return null;
 287  
     }
 288  0
     final String str = element.getAttribute(attributeName);
 289  0
     if (null == str
 290  0
         || "".equals(str)) {
 291  0
       return null;
 292  
     } else {
 293  0
       return Double.valueOf(str);
 294  
     }
 295  
   }
 296  
 
 297  
   /**
 298  
    * Write the document to a writer.
 299  
    * 
 300  
    * @param doc the document to write
 301  
    * @param writer where to write the document
 302  
    */
 303  
   public static void writeXML(final Document doc,
 304  
                               final Writer writer) {
 305  0
     writeXML(doc, writer, null);
 306  0
   }
 307  
 
 308  
   /**
 309  
    * Write the document to a writer.
 310  
    * 
 311  
    * @param doc the document to write
 312  
    * @param writer where to write the document
 313  
    * @param encoding if non-null use this as the encoding for the text
 314  
    * @throws RuntimeException if a {@link TransformerException} occurs.
 315  
    */
 316  
   public static void writeXML(final Document doc,
 317  
                               final Writer writer,
 318  
                               final String encoding) {
 319  
     try {
 320  0
       final TransformerFactory transformerFactory = TransformerFactory.newInstance();
 321  0
       final Transformer transformer = transformerFactory.newTransformer();
 322  0
       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
 323  0
       if (null != encoding) {
 324  0
         transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
 325  
       }
 326  0
       final DOMSource source = new DOMSource(doc);
 327  0
       final StreamResult result = new StreamResult(writer);
 328  0
       transformer.transform(source, result);
 329  0
     } catch (final TransformerException e) {
 330  0
       throw new RuntimeException("Internal error writing xml", e);
 331  0
     }
 332  0
   }
 333  
 }