001: /*
002: ******************************************************************
003: Copyright (c) 2001-2007, Jeff Martin, Tim Bacon
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: * Redistributions of source code must retain the above copyright
011: notice, this list of conditions and the following disclaimer.
012: * Redistributions in binary form must reproduce the above
013: copyright notice, this list of conditions and the following
014: disclaimer in the documentation and/or other materials provided
015: with the distribution.
016: * Neither the name of the xmlunit.sourceforge.net nor the names
017: of its contributors may be used to endorse or promote products
018: derived from this software without specific prior written
019: permission.
020:
021: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
022: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
023: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
024: FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
025: COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
026: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
027: BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
028: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
029: CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
030: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
031: ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
032: POSSIBILITY OF SUCH DAMAGE.
033:
034: ******************************************************************
035: */
036:
037: package org.custommonkey.xmlunit;
038:
039: import java.io.ByteArrayOutputStream;
040: import java.io.InputStream;
041: import java.io.IOException;
042: import java.util.Properties;
043: import javax.xml.transform.stream.StreamResult;
044: import org.w3c.dom.Node;
045:
046: /**
047: * Adapter class to present the content of a DOM Node (e.g. a Document) as an
048: * InputStream using a DOM to Stream transformation.
049: * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a>
050: */
051: public class NodeInputStream extends InputStream {
052: private final Node rootNode;
053: private final ByteArrayOutputStream nodeContentBytes;
054: private final Properties outputProperties;
055: private int atPos = 0;
056:
057: /**
058: * Simple constructor
059: * @param rootNode the node to be presented as an input stream
060: */
061: public NodeInputStream(Node rootNode) {
062: this (rootNode, null);
063: }
064:
065: /**
066: * Simple constructor
067: * @param rootNode the node to be presented as an input stream
068: */
069: public NodeInputStream(Node rootNode, Properties outputProperties) {
070: this .rootNode = rootNode;
071: nodeContentBytes = new ByteArrayOutputStream();
072: this .outputProperties = outputProperties;
073: }
074:
075: /**
076: * Do the actual work of serializing the node to bytes
077: * @throws IOException if serialization goes awry
078: */
079: private void ensureContentAvailable() throws IOException {
080: if (nodeContentBytes.size() > 0) {
081: return;
082: }
083: try {
084: Transform serializeTransform = new Transform(rootNode);
085: if (outputProperties != null) {
086: serializeTransform
087: .setOutputProperties(outputProperties);
088: }
089: StreamResult byteResult = new StreamResult(nodeContentBytes);
090: serializeTransform.transformTo(byteResult);
091: } catch (Exception e) {
092: throw new IOException(
093: "Unable to serialize document to outputstream: "
094: + e.toString());
095: }
096: }
097:
098: /**
099: * InputStream method
100: * @return byte as read
101: * @throws IOException
102: */
103: public int read() throws IOException {
104: ensureContentAvailable();
105: if (reallyAvailable() == 0) {
106: return -1;
107: }
108: int contentByte = nodeContentBytes.toByteArray()[atPos];
109: atPos++;
110: return contentByte;
111: }
112:
113: /**
114: * InputStream method
115: * Note that calling close allows a repeated read of the content
116: * @throws IOException
117: */
118: public void close() throws IOException {
119: atPos = 0;
120: }
121:
122: /**
123: * InputStream method
124: * @return number of bytes available
125: */
126: public int available() throws IOException {
127: ensureContentAvailable();
128: return reallyAvailable();
129: }
130:
131: /**
132: * @return really available
133: */
134: private int reallyAvailable() {
135: return nodeContentBytes.size() - atPos;
136: }
137: }
|