Coverage Report - org.mule.module.xml.util.XMLUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLUtils
47%
74/156
43%
57/132
9.364
XMLUtils$1
71%
5/7
N/A
9.364
 
 1  
 /*
 2  
  * $Id: XMLUtils.java 12370 2008-07-17 13:11:17Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.module.xml.util;
 12  
 
 13  
 import org.mule.RequestContext;
 14  
 import org.mule.api.transport.OutputHandler;
 15  
 import org.mule.module.xml.stax.DelegateXMLStreamReader;
 16  
 import org.mule.module.xml.stax.StaxSource;
 17  
 import org.mule.module.xml.transformer.DelayedResult;
 18  
 import org.mule.module.xml.transformer.XmlToDomDocument;
 19  
 import org.mule.util.IOUtils;
 20  
 
 21  
 import java.io.ByteArrayInputStream;
 22  
 import java.io.File;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.StringReader;
 26  
 
 27  
 import javax.xml.stream.XMLStreamConstants;
 28  
 import javax.xml.stream.XMLStreamException;
 29  
 import javax.xml.stream.XMLStreamReader;
 30  
 import javax.xml.stream.XMLStreamWriter;
 31  
 import javax.xml.transform.Source;
 32  
 import javax.xml.transform.Transformer;
 33  
 import javax.xml.transform.TransformerConfigurationException;
 34  
 import javax.xml.transform.TransformerFactory;
 35  
 import javax.xml.transform.TransformerFactoryConfigurationError;
 36  
 import javax.xml.transform.dom.DOMResult;
 37  
 import javax.xml.transform.dom.DOMSource;
 38  
 import javax.xml.transform.sax.SAXSource;
 39  
 import javax.xml.transform.stream.StreamSource;
 40  
 
 41  
 import org.apache.commons.io.output.ByteArrayOutputStream;
 42  
 import org.apache.commons.lang.StringUtils;
 43  
 import org.dom4j.DocumentException;
 44  
 import org.dom4j.io.DOMReader;
 45  
 import org.dom4j.io.DocumentSource;
 46  
 import org.w3c.dom.Document;
 47  
 import org.xml.sax.InputSource;
 48  
 
 49  
 /**
 50  
  * General utility methods for working with XML.
 51  
  */
 52  0
 public class XMLUtils extends org.mule.util.XMLUtils
 53  
 {
 54  
     public static final String TRANSFORMER_FACTORY_JDK5 = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
 55  
 
 56  
     // xml parser feature names for optional XSD validation
 57  
     public static final String APACHE_XML_FEATURES_VALIDATION_SCHEMA = "http://apache.org/xml/features/validation/schema";
 58  
     public static final String APACHE_XML_FEATURES_VALIDATION_SCHEMA_FULL_CHECKING = "http://apache.org/xml/features/validation/schema-full-checking";
 59  
 
 60  
     // JAXP property for specifying external XSD location
 61  
     public static final String JAXP_PROPERTIES_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
 62  
 
 63  
     // JAXP properties for specifying external XSD language (as required by newer
 64  
     // JAXP implementation)
 65  
     public static final String JAXP_PROPERTIES_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
 66  
     public static final String JAXP_PROPERTIES_SCHEMA_LANGUAGE_VALUE = "http://www.w3.org/2001/XMLSchema";
 67  
 
 68  
     /**
 69  
      * Converts a DOM to an XML string.
 70  
      */
 71  
     public static String toXml(Document dom)
 72  
     {
 73  0
         return new DOMReader().read(dom).asXML();
 74  
     }
 75  
 
 76  
     /**
 77  
      * @return a new XSLT transformer
 78  
      * @throws TransformerConfigurationException if no TransformerFactory can be located in the
 79  
      * runtime environment.
 80  
      */
 81  
     public static Transformer getTransformer() throws TransformerConfigurationException
 82  
     {
 83  
         TransformerFactory tf;
 84  
         try
 85  
         {
 86  36
             tf = TransformerFactory.newInstance();
 87  
         }
 88  0
         catch (TransformerFactoryConfigurationError e)
 89  
         {
 90  0
             System.setProperty("javax.xml.transform.TransformerFactory", TRANSFORMER_FACTORY_JDK5);
 91  0
             tf = TransformerFactory.newInstance();
 92  36
         }
 93  36
         if (tf != null)
 94  
         {
 95  36
             return tf.newTransformer();
 96  
         }
 97  
         else
 98  
         {
 99  0
             throw new TransformerConfigurationException("Unable to instantiate a TransformerFactory");
 100  
         }
 101  
     }
 102  
 
 103  
     public static org.dom4j.Document toDocument(Object obj) throws Exception
 104  
     {
 105  76
         return toDocument(obj, null);
 106  
     }
 107  
     
 108  
     /**
 109  
      * Converts an object of unknown type to an org.dom4j.Document if possible.
 110  
      * @return null if object cannot be converted
 111  
      * @throws DocumentException if an error occurs while parsing
 112  
      */
 113  
     public static org.dom4j.Document toDocument(Object obj, String externalSchemaLocation) throws Exception
 114  
     {
 115  136
         org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
 116  136
         if (externalSchemaLocation != null)
 117  
         {
 118  60
             reader.setValidation(true);
 119  60
             reader.setFeature(APACHE_XML_FEATURES_VALIDATION_SCHEMA, true);
 120  60
             reader.setFeature(APACHE_XML_FEATURES_VALIDATION_SCHEMA_FULL_CHECKING, true);
 121  
             
 122  60
             InputStream xsdAsStream = IOUtils.getResourceAsStream(externalSchemaLocation, XMLUtils.class);
 123  60
             if (xsdAsStream == null)
 124  
             {
 125  4
                 throw new IllegalArgumentException("Couldn't find schema at " + externalSchemaLocation);
 126  
             }
 127  
     
 128  
             // Set schema language property (must be done before the schemaSource
 129  
             // is set)
 130  56
             reader.setProperty(JAXP_PROPERTIES_SCHEMA_LANGUAGE, JAXP_PROPERTIES_SCHEMA_LANGUAGE_VALUE);
 131  
     
 132  
             // Need this one to map schemaLocation to a physical location
 133  56
             reader.setProperty(JAXP_PROPERTIES_SCHEMA_SOURCE, xsdAsStream);
 134  
         }
 135  
         
 136  132
         if (obj instanceof org.dom4j.Document)
 137  
         {
 138  26
             return (org.dom4j.Document) obj;
 139  
         }
 140  106
         else if (obj instanceof org.w3c.dom.Document)
 141  
         {
 142  14
             org.dom4j.io.DOMReader domReader = new org.dom4j.io.DOMReader();
 143  14
             return domReader.read((org.w3c.dom.Document) obj);
 144  
         }
 145  92
         else if (obj instanceof org.xml.sax.InputSource)
 146  
         {                
 147  6
             return reader.read((org.xml.sax.InputSource) obj);
 148  
         }
 149  86
         else if (obj instanceof javax.xml.transform.Source || obj instanceof javax.xml.stream.XMLStreamReader)
 150  
         {                
 151  
             // TODO Find a more direct way to do this
 152  10
             XmlToDomDocument tr = new XmlToDomDocument();
 153  10
             tr.setReturnClass(org.dom4j.Document.class);
 154  10
             return (org.dom4j.Document) tr.transform(obj);
 155  
         }
 156  76
         else if (obj instanceof java.io.InputStream)
 157  
         {                
 158  6
             return reader.read((java.io.InputStream) obj);
 159  
         }
 160  70
         else if (obj instanceof String)
 161  
         {
 162  42
             return reader.read(new StringReader((String) obj));
 163  
         }
 164  28
         else if (obj instanceof byte[])
 165  
         {
 166  
             // TODO Handle encoding/charset somehow
 167  12
             return reader.read(new StringReader(new String((byte[]) obj)));
 168  
         }
 169  16
         else if (obj instanceof File)
 170  
         {                
 171  0
             return reader.read((File) obj);
 172  
         }
 173  
         else
 174  
         {
 175  16
             return null;
 176  
         }
 177  
     }
 178  
     /**
 179  
      * Returns an XMLStreamReader for an object of unknown type if possible.
 180  
      * @return null if no XMLStreamReader can be created for the object type
 181  
      * @throws XMLStreamException
 182  
      */
 183  
     public static javax.xml.stream.XMLStreamReader toXMLStreamReader(javax.xml.stream.XMLInputFactory factory, Object obj) throws XMLStreamException
 184  
     {
 185  44
         if (obj instanceof javax.xml.stream.XMLStreamReader)
 186  
         {
 187  2
             return (javax.xml.stream.XMLStreamReader) obj;
 188  
         }
 189  42
         else if (obj instanceof org.mule.module.xml.stax.StaxSource)
 190  
         {
 191  0
             return ((org.mule.module.xml.stax.StaxSource) obj).getXMLStreamReader();
 192  
         }
 193  42
         else if (obj instanceof javax.xml.transform.Source)
 194  
         {
 195  2
             return factory.createXMLStreamReader((javax.xml.transform.Source) obj);
 196  
         }
 197  40
         else if (obj instanceof org.xml.sax.InputSource)
 198  
         {
 199  2
             return factory.createXMLStreamReader(((org.xml.sax.InputSource) obj).getByteStream());
 200  
         }
 201  38
         else if (obj instanceof org.w3c.dom.Document)
 202  
         {
 203  2
             return factory.createXMLStreamReader(new javax.xml.transform.dom.DOMSource((org.w3c.dom.Document) obj));
 204  
         }
 205  36
         else if (obj instanceof org.dom4j.Document)
 206  
         {
 207  2
             return factory.createXMLStreamReader(new org.dom4j.io.DocumentSource((org.dom4j.Document) obj));
 208  
         }
 209  34
         else if (obj instanceof java.io.InputStream)
 210  
         {
 211  20
             final InputStream is = (java.io.InputStream) obj;
 212  
             
 213  20
             XMLStreamReader xsr = factory.createXMLStreamReader(is);
 214  20
             return new DelegateXMLStreamReader(xsr) {
 215  
 
 216  20
                 public void close() throws XMLStreamException
 217  
                 {
 218  4
                     super.close();
 219  
                     
 220  
                     try
 221  
                     {
 222  4
                         is.close();
 223  
                     }
 224  0
                     catch (IOException e)
 225  
                     {
 226  0
                         throw new XMLStreamException(e);
 227  4
                     }
 228  4
                 }
 229  
                 
 230  
             };
 231  
         }
 232  14
         else if (obj instanceof String)
 233  
         {
 234  10
             return factory.createXMLStreamReader(new StringReader((String) obj));
 235  
         }
 236  4
         else if (obj instanceof byte[])
 237  
         {
 238  
             // TODO Handle encoding/charset?
 239  2
             return factory.createXMLStreamReader(new ByteArrayInputStream((byte[]) obj));
 240  
         }
 241  
         else
 242  
         {
 243  2
             return null;
 244  
         }
 245  
     }
 246  
     
 247  
     /**
 248  
      * Convert our object to a Source type efficiently.
 249  
      */ 
 250  
     public static javax.xml.transform.Source toXmlSource(javax.xml.stream.XMLInputFactory xmlInputFactory, boolean useStaxSource, Object src) throws Exception
 251  
     {
 252  4102
         if (src instanceof javax.xml.transform.Source)
 253  
         {
 254  12
             return (Source) src;
 255  
         }
 256  4090
         else if (src instanceof byte[])
 257  
         {
 258  0
             ByteArrayInputStream stream = new ByteArrayInputStream((byte[]) src);
 259  0
             return toStreamSource(xmlInputFactory, useStaxSource, stream);
 260  
         }
 261  4090
         else if (src instanceof InputStream)
 262  
         {
 263  20
             return toStreamSource(xmlInputFactory, useStaxSource, (InputStream) src);
 264  
         }
 265  4070
         else if (src instanceof String)
 266  
         {
 267  4028
             if (useStaxSource)
 268  
             {
 269  0
                 return new StaxSource(xmlInputFactory.createXMLStreamReader(new StringReader((String) src)));
 270  
             }
 271  
             else
 272  
             {
 273  4028
                 return new StreamSource(new StringReader((String) src));
 274  
             }
 275  
         }
 276  42
         else if (src instanceof org.dom4j.Document)
 277  
         {
 278  6
             return new DocumentSource((org.dom4j.Document) src);
 279  
         }
 280  36
         else if (src instanceof org.xml.sax.InputSource)
 281  
         {
 282  6
             return new SAXSource((InputSource) src);
 283  
         }
 284  
         // TODO MULE-3555
 285  30
         else if (src instanceof XMLStreamReader)
 286  
         {
 287  12
             XMLStreamReader xsr = (XMLStreamReader) src;
 288  
             
 289  
             // StaxSource requires that we advance to a start element/document event
 290  12
             if (!xsr.isStartElement() && 
 291  
                             xsr.getEventType() != XMLStreamConstants.START_DOCUMENT) 
 292  
             {
 293  0
                 xsr.nextTag();
 294  
             }
 295  
             
 296  12
             return new StaxSource((XMLStreamReader) src);
 297  
         }
 298  18
         else if (src instanceof org.w3c.dom.Document || src instanceof org.w3c.dom.Element)
 299  
         {
 300  18
             return new DOMSource((org.w3c.dom.Node) src);
 301  
         }
 302  0
         else if (src instanceof DelayedResult) 
 303  
         {
 304  0
             DelayedResult result = ((DelayedResult) src);
 305  0
             DOMResult domResult = new DOMResult();
 306  0
             result.write(domResult);
 307  0
             return new DOMSource(domResult.getNode());
 308  
         }
 309  0
         else if (src instanceof OutputHandler) 
 310  
         {
 311  0
             OutputHandler handler = ((OutputHandler) src);
 312  0
             ByteArrayOutputStream output = new ByteArrayOutputStream();
 313  
             
 314  0
             handler.write(RequestContext.getEvent(), output);
 315  
             
 316  0
             return toStreamSource(xmlInputFactory, useStaxSource, new ByteArrayInputStream(output.toByteArray()));
 317  
         }
 318  
         else
 319  
         {
 320  0
             return null;
 321  
         }
 322  
     }
 323  
 
 324  
     public static javax.xml.transform.Source toStreamSource(javax.xml.stream.XMLInputFactory xmlInputFactory, boolean useStaxSource, InputStream stream) throws XMLStreamException
 325  
     {
 326  20
         if (useStaxSource)
 327  
         {
 328  0
             return new org.mule.module.xml.stax.StaxSource(xmlInputFactory.createXMLStreamReader(stream));
 329  
         }
 330  
         else 
 331  
         {
 332  20
             return new javax.xml.transform.stream.StreamSource(stream);
 333  
         }
 334  
     }
 335  
     
 336  
     /**
 337  
      * Copies the reader to the writer. The start and end document methods must
 338  
      * be handled on the writer manually. TODO: if the namespace on the reader
 339  
      * has been declared previously to where we are in the stream, this probably
 340  
      * won't work.
 341  
      * 
 342  
      * @param reader
 343  
      * @param writer
 344  
      * @throws XMLStreamException
 345  
      */
 346  
     public static void copy(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
 347  0
         copy(reader, writer, false);
 348  0
     }
 349  
     public static void copy(XMLStreamReader reader, XMLStreamWriter writer,
 350  
                             boolean fragment) throws XMLStreamException {
 351  
         // number of elements read in
 352  0
         int read = 0;
 353  0
         int event = reader.getEventType();
 354  
 
 355  0
         while (reader.hasNext()) {
 356  0
             switch (event) {
 357  
             case XMLStreamConstants.START_ELEMENT:
 358  0
                 read++;
 359  0
                 writeStartElement(reader, writer);
 360  0
                 break;
 361  
             case XMLStreamConstants.END_ELEMENT:
 362  0
                 writer.writeEndElement();
 363  0
                 read--;
 364  0
                 if (read <= 0 && !fragment) {
 365  0
                     return;
 366  
                 }
 367  
                 break;
 368  
             case XMLStreamConstants.CHARACTERS:
 369  0
                 writer.writeCharacters(reader.getText());
 370  0
                 break;
 371  
             case XMLStreamConstants.START_DOCUMENT:
 372  
             case XMLStreamConstants.END_DOCUMENT:
 373  
             case XMLStreamConstants.ATTRIBUTE:
 374  
             case XMLStreamConstants.NAMESPACE:
 375  0
                 break;
 376  
             default:
 377  
                 break;
 378  
             }
 379  0
             event = reader.next();
 380  
         }
 381  0
     }
 382  
 
 383  
     private static void writeStartElement(XMLStreamReader reader, XMLStreamWriter writer)
 384  
         throws XMLStreamException {
 385  0
         String local = reader.getLocalName();
 386  0
         String uri = reader.getNamespaceURI();
 387  0
         String prefix = reader.getPrefix();
 388  0
         if (prefix == null) {
 389  0
             prefix = "";
 390  
         }
 391  
 
 392  
         
 393  
 //        System.out.println("STAXUTILS:writeStartElement : node name : " + local +  " namespace URI" + uri);
 394  0
         boolean writeElementNS = false;
 395  0
         if (uri != null) {
 396  0
             String boundPrefix = writer.getPrefix(uri);
 397  0
             if (boundPrefix == null || !prefix.equals(boundPrefix)) {
 398  0
                 writeElementNS = true;
 399  
             }
 400  
         }
 401  
 
 402  
         // Write out the element name
 403  0
         if (uri != null) {
 404  0
             if (prefix.length() == 0 && StringUtils.isEmpty(uri)) {
 405  0
                 writer.writeStartElement(local);
 406  0
                 writer.setDefaultNamespace(uri);
 407  
 
 408  
             } else {
 409  0
                 writer.writeStartElement(prefix, local, uri);
 410  0
                 writer.setPrefix(prefix, uri);
 411  
             }
 412  
         } else {
 413  0
             writer.writeStartElement(local);
 414  
         }
 415  
 
 416  
         // Write out the namespaces
 417  0
         for (int i = 0; i < reader.getNamespaceCount(); i++) {
 418  0
             String nsURI = reader.getNamespaceURI(i);
 419  0
             String nsPrefix = reader.getNamespacePrefix(i);
 420  0
             if (nsPrefix == null) {
 421  0
                 nsPrefix = "";
 422  
             }
 423  
 
 424  0
             if (nsPrefix.length() == 0) {
 425  0
                 writer.writeDefaultNamespace(nsURI);
 426  
             } else {
 427  0
                 writer.writeNamespace(nsPrefix, nsURI);
 428  
             }
 429  
 
 430  0
             if (nsURI.equals(uri) && nsPrefix.equals(prefix)) {
 431  0
                 writeElementNS = false;
 432  
             }
 433  
         }
 434  
 
 435  
         // Check if the namespace still needs to be written.
 436  
         // We need this check because namespace writing works
 437  
         // different on Woodstox and the RI.
 438  0
         if (writeElementNS) {
 439  0
             if (prefix == null || prefix.length() == 0) {
 440  0
                 writer.writeDefaultNamespace(uri);
 441  
             } else {
 442  0
                 writer.writeNamespace(prefix, uri);
 443  
             }
 444  
         }        
 445  
         
 446  
         // Write out attributes
 447  0
         for (int i = 0; i < reader.getAttributeCount(); i++) {
 448  0
             String ns = reader.getAttributeNamespace(i);
 449  0
             String nsPrefix = reader.getAttributePrefix(i);
 450  0
             if (ns == null || ns.length() == 0) {
 451  0
                 writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
 452  0
             } else if (nsPrefix == null || nsPrefix.length() == 0) {
 453  0
                 writer.writeAttribute(reader.getAttributeNamespace(i), reader.getAttributeLocalName(i),
 454  
                                       reader.getAttributeValue(i));
 455  
             } else {
 456  0
                 writer.writeAttribute(reader.getAttributePrefix(i), reader.getAttributeNamespace(i), reader
 457  
                     .getAttributeLocalName(i), reader.getAttributeValue(i));
 458  
             }
 459  
 
 460  
         }
 461  0
     }
 462  
 }