Coverage Report - net.mtu.eggplant.xml.XMLUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLUtils
12%
8/63
0%
0/16
2.588
XMLUtils$1
50%
1/2
N/A
2.588
XMLUtils$2
20%
1/5
N/A
2.588
XMLUtils$3
0%
0/5
N/A
2.588
XMLUtils$4
0%
0/5
N/A
2.588
 
 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 net.mtu.eggplant.io.IOUtils;
 50  
 
 51  
 import org.slf4j.Logger;
 52  
 import org.slf4j.LoggerFactory;
 53  
 import org.w3c.dom.Document;
 54  
 import org.w3c.dom.Element;
 55  
 import org.xml.sax.ErrorHandler;
 56  
 import org.xml.sax.InputSource;
 57  
 import org.xml.sax.SAXException;
 58  
 import org.xml.sax.SAXParseException;
 59  
 
 60  
 /**
 61  
  * Some utilities for working with XML.
 62  
  */
 63  0
 public class XMLUtils {
 64  
 
 65  1
   private static final Logger LOGGER = LoggerFactory.getLogger(XMLUtils.class);
 66  
 
 67  
   /**
 68  
    * Date format for time type.
 69  
    */
 70  1
   public static final ThreadLocal<DateFormat> XML_TIME_FORMAT = new ThreadLocal<DateFormat>() {
 71  
     @Override
 72  
     protected DateFormat initialValue() {
 73  0
       return new SimpleDateFormat("HH:mm:ss");
 74  
     }
 75  
   };
 76  
   
 77  
   public static final DocumentBuilder DOCUMENT_BUILDER;
 78  
 
 79  
   // create basic document builder
 80  
   static {
 81  
     try {
 82  1
       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 83  1
       factory.setNamespaceAware(true);
 84  1
       DOCUMENT_BUILDER = factory.newDocumentBuilder();
 85  1
       DOCUMENT_BUILDER.setErrorHandler(new ErrorHandler() {
 86  
         public void error(final SAXParseException spe) throws SAXParseException {
 87  0
           throw spe;
 88  
         }
 89  
 
 90  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 91  0
           throw spe;
 92  
         }
 93  
 
 94  
         public void warning(final SAXParseException spe) throws SAXParseException {
 95  0
           System.err.println(spe.getMessage());
 96  0
         }
 97  
       });
 98  0
     } catch (final ParserConfigurationException pce) {
 99  0
       throw new RuntimeException(pce.getMessage(), pce);
 100  1
     }
 101  1
   }
 102  
 
 103  
   /**
 104  
    * Parse the document from the given stream. The document is validated with
 105  
    * the specified schema. Does not close the stream after reading. Warnings are
 106  
    * output to the logger for this class.
 107  
    * 
 108  
    * @param stream a stream containing document
 109  
    * @return the challengeDocument, null on an error
 110  
    * @throws IOException if there is an error reading the stream
 111  
    * @throws SAXException if there is an error parsing the document or it
 112  
    *           doesn't match the schema
 113  
    * @throws RuntimeException if there is an error configuring the XML parser,
 114  
    *           this shouldn't happen
 115  
    */
 116  
   public static Document parse(final Reader stream,
 117  
                                final Schema schema) throws IOException, SAXException {
 118  
     try {
 119  0
       final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 120  0
       builderFactory.setNamespaceAware(true);
 121  0
       builderFactory.setSchema(schema);
 122  0
       builderFactory.setIgnoringComments(true);
 123  0
       builderFactory.setIgnoringElementContentWhitespace(true);
 124  0
       final DocumentBuilder parser = builderFactory.newDocumentBuilder();
 125  
 
 126  0
       parser.setErrorHandler(new ErrorHandler() {
 127  
         public void error(final SAXParseException spe) throws SAXParseException {
 128  0
           throw spe;
 129  
         }
 130  
 
 131  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 132  0
           throw spe;
 133  
         }
 134  
 
 135  
         public void warning(final SAXParseException spe) throws SAXParseException {
 136  0
           LOGGER.error(spe.getMessage(), spe);
 137  0
         }
 138  
       });
 139  
 
 140  
       // parse
 141  0
       final String content = IOUtils.readIntoString(stream);
 142  0
       final Document document = parser.parse(new InputSource(new StringReader(content)));
 143  
 
 144  0
       return document;
 145  0
     } catch (ParserConfigurationException e) {
 146  0
       throw new RuntimeException("Error configuring the XML parser", e);
 147  
     }
 148  
   }
 149  
 
 150  
   /**
 151  
    * Parse xmlDoc an XML document. Just does basic parsing, no validity checks.
 152  
    * Does not close the stream after parsing. Warnings are output to the logger
 153  
    * for this class.
 154  
    * 
 155  
    * @throws IOException if there is an error reading the stream
 156  
    * @throws SAXException if the document is found to be invalid
 157  
    * @throws RuntimeException if there is an error configuring the XML parser,
 158  
    *           this shouldn't happen
 159  
    */
 160  
   public static Document parseXMLDocument(final InputStream xmlDocStream) throws SAXException, IOException {
 161  
     try {
 162  0
       final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 163  0
       factory.setNamespaceAware(true);
 164  0
       factory.setIgnoringComments(true);
 165  0
       factory.setIgnoringElementContentWhitespace(true);
 166  
 
 167  0
       final DocumentBuilder parser = factory.newDocumentBuilder();
 168  0
       parser.setErrorHandler(new ErrorHandler() {
 169  
         public void error(final SAXParseException spe) throws SAXParseException {
 170  0
           throw spe;
 171  
         }
 172  
 
 173  
         public void fatalError(final SAXParseException spe) throws SAXParseException {
 174  0
           throw spe;
 175  
         }
 176  
 
 177  
         public void warning(final SAXParseException spe) throws SAXParseException {
 178  0
           LOGGER.error(spe.getMessage());
 179  0
         }
 180  
       });
 181  
 
 182  0
       final Document document = parser.parse(xmlDocStream);
 183  0
       return document;
 184  0
     } catch (final ParserConfigurationException pce) {
 185  0
       throw new RuntimeException("Error configuring the XML parser", pce);
 186  
     }
 187  
   }
 188  
 
 189  
   /**
 190  
    * @see #getDoubleAttributeValue(Element, String)
 191  
    */
 192  
   public static String getStringAttributeValue(final Element element,
 193  
                                                final String attributeName) {
 194  0
     if (null == element) {
 195  0
       return null;
 196  
     }
 197  0
     final String str = element.getAttribute(attributeName);
 198  0
     return str;
 199  
   }
 200  
 
 201  
   /**
 202  
    * @see #getDoubleAttributeValue(Element, String)
 203  
    */
 204  
   @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = { "NP_BOOLEAN_RETURN_NULL" }, justification = "Need to return Null so that we can determine when there is no score")
 205  
   public static Boolean getBooleanAttributeValue(final Element element,
 206  
                                                  final String attributeName) {
 207  0
     if (null == element) {
 208  0
       return null;
 209  
     }
 210  0
     final String str = element.getAttribute(attributeName);
 211  0
     if (null == str
 212  
         || "".equals(str)) {
 213  0
       return null;
 214  
     } else {
 215  0
       return Boolean.valueOf(str);
 216  
     }
 217  
   }
 218  
 
 219  
   /**
 220  
    * Get a double value from an attribute.
 221  
    * 
 222  
    * @param element the element to get the attribute from, may be null
 223  
    * @param attributeName the attribute name to get
 224  
    * @return the value, null if element is null or the attribute value is null
 225  
    *         or empty
 226  
    */
 227  
   public static Double getDoubleAttributeValue(final Element element,
 228  
                                                final String attributeName) {
 229  0
     if (null == element) {
 230  0
       return null;
 231  
     }
 232  0
     final String str = element.getAttribute(attributeName);
 233  0
     if (null == str
 234  
         || "".equals(str)) {
 235  0
       return null;
 236  
     } else {
 237  0
       return Double.valueOf(str);
 238  
     }
 239  
   }
 240  
 
 241  
   /**
 242  
    * Write the document to a writer.
 243  
    * 
 244  
    * @param doc the document to write
 245  
    * @param writer where to write the document
 246  
    */
 247  
   public static void writeXML(final Document doc,
 248  
                               final Writer writer) {
 249  0
     writeXML(doc, writer, null);
 250  0
   }
 251  
 
 252  
   /**
 253  
    * Write the document to a writer.
 254  
    * 
 255  
    * @param doc the document to write
 256  
    * @param writer where to write the document
 257  
    * @param encoding if non-null use this as the encoding for the text
 258  
    * @throws RuntimeException if a {@link TransformerException} occurs.
 259  
    */
 260  
   public static void writeXML(final Document doc,
 261  
                               final Writer writer,
 262  
                               final String encoding) {
 263  
     try {
 264  0
       final TransformerFactory transformerFactory = TransformerFactory.newInstance();
 265  0
       final Transformer transformer = transformerFactory.newTransformer();
 266  0
       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
 267  0
       if (null != encoding) {
 268  0
         transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
 269  
       }
 270  0
       final DOMSource source = new DOMSource(doc);
 271  0
       final StreamResult result = new StreamResult(writer);
 272  0
       transformer.transform(source, result);
 273  0
     } catch (final TransformerException e) {
 274  0
       throw new RuntimeException("Internal error writing xml", e);
 275  0
     }
 276  0
   }
 277  
 }