/*
* utils - XML.java - Copyright © 2006-2009 David Roden
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.pterodactylus.util.xml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import net.pterodactylus.util.io.Closer;
import net.pterodactylus.util.logging.Logging;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Contains method to transform DOM XML trees to byte arrays and vice versa.
*
* @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
*/
public class XML {
/** The logger. */
private static final Logger logger = Logging.getLogger(XML.class.getName());
/** Cached document builder factory. */
private static DocumentBuilderFactory documentBuilderFactory = null;
/** Cached document builder. */
private static DocumentBuilder documentBuilder = null;
/** Cached transformer factory. */
private static TransformerFactory transformerFactory = null;
/**
* Returns a document builder factory. If possible the cached instance will
* be returned.
*
* @return A document builder factory
*/
private static DocumentBuilderFactory getDocumentBuilderFactory() {
if (documentBuilderFactory != null) {
return documentBuilderFactory;
}
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setXIncludeAware(true);
documentBuilderFactory.setNamespaceAware(true);
return documentBuilderFactory;
}
/**
* Returns a document builder. If possible the cached instance will be
* returned.
*
* @return A document builder
*/
private static DocumentBuilder getDocumentBuilder() {
if (documentBuilder != null) {
return documentBuilder;
}
try {
documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
} catch (ParserConfigurationException pce1) {
logger.log(Level.WARNING, "Could not create DocumentBuilder.", pce1);
}
return documentBuilder;
}
/**
* Returns a transformer factory. If possible the cached instance will be
* returned.
*
* @return A transformer factory
*/
private static TransformerFactory getTransformerFactory() {
if (transformerFactory != null) {
return transformerFactory;
}
transformerFactory = TransformerFactory.newInstance();
return transformerFactory;
}
/**
* Creates a new XML document.
*
* @return A new XML document
*/
public static Document createDocument() {
return getDocumentBuilder().newDocument();
}
/**
* Transforms the DOM XML document into a byte array.
*
* @param document
* The document to transform
* @return The byte array containing the XML representation
*/
public static byte[] transformToByteArray(Document document) {
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
OutputStreamWriter converter = new OutputStreamWriter(byteOutput, Charset.forName("UTF-8"));
writeToOutputStream(document, converter);
try {
converter.flush();
byteOutput.flush();
byte[] result = byteOutput.toByteArray();
return result;
} catch (IOException ioe1) {
return null;
} finally {
Closer.close(converter);
Closer.close(byteOutput);
}
}
/**
* Writes the given document to the given writer.
*
* @param document
* The document to write
* @param writer
* The writer to write the document to
*/
public static void writeToOutputStream(Document document, Writer writer) {
writeToOutputStream(document, writer, true);
}
/**
* Writes the given document to the given writer.
*
* @param document
* The document to write
* @param writer
* The writer to write the document to
* @param preamble
* <code>true</code> to include the XML header,
* <code>false</code> to not include it
*/
public static void writeToOutputStream(Document document, Writer writer, boolean preamble) {
Result transformResult = new StreamResult(writer);
Source documentSource = new DOMSource(document);
try {
Transformer transformer = getTransformerFactory().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, preamble ? "no" : "yes");
transformer.transform(documentSource, transformResult);
} catch (TransformerConfigurationException tce1) {
logger.log(Level.WARNING, "Could create Transformer.", tce1);
} catch (TransformerException te1) {
logger.log(Level.WARNING, "Could not transform Document.", te1);
}
}
/**
* Transforms the byte array into a DOM XML document.
*
* @param data
* The byte array to parse
* @return The DOM XML document
*/
public static Document transformToDocument(byte[] data) {
return transformToDocument(new ByteArrayInputStream(data));
}
/**
* Transforms the input stream into a DOM XML document.
*
* @param inputStream
* The input stream to parse
* @return The DOM XML document
*/
public static Document transformToDocument(InputStream inputStream) {
return transformToDocument(new InputSource(inputStream));
}
/**
* Transforms the reader into a DOM XML document.
*
* @param inputReader
* The reader to read the XML from
* @return The DOM XML document
*/
public static Document transformToDocument(Reader inputReader) {
return transformToDocument(new InputSource(inputReader));
}
/**
* Transforms the inout source into a DOM XML document.
*
* @param inputSource
* The source to read the XML from
* @return The DOM XML document
*/
public static Document transformToDocument(InputSource inputSource) {
try {
DocumentBuilder documentBuilder = getDocumentBuilder();
return documentBuilder.parse(inputSource);
} catch (SAXException saxe1) {
logger.log(Level.WARNING, "Could not parse InputSource.", saxe1);
} catch (IOException ioe1) {
logger.log(Level.WARNING, "Could not read InputSource.", ioe1);
}
return null;
}
}