001: /*
002: ******************************************************************
003: Copyright (c) 2001, 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.BufferedInputStream;
040: import java.io.ByteArrayOutputStream;
041: import java.io.InputStream;
042: import java.io.IOException;
043:
044: /**
045: * Adapts the marked-up content in a source InputStream to specify that it
046: * conforms to a different DTD.
047: * Combines InputStream semantics with the ability to specify a target doctype
048: * for a byte stream containing XML markup.
049: * Used by Validator class to wrap an InputStrea, when performing validation of a
050: * document against a DTD.
051: * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a>
052: */
053: public class DoctypeInputStream extends InputStream {
054:
055: private final ByteArrayOutputStream baos = new ByteArrayOutputStream(
056: 1024);
057: private final InputStream wrappedStream;
058: private final DoctypeSupport support;
059:
060: /**
061: * Create an InputStream whose XML content is provided by the
062: * originalSource with the exception of the DOCTYPE which is
063: * provided by the doctypeName and systemID.
064: * @param originalSource
065: * @param doctypeName
066: * @param systemID
067: */
068: public DoctypeInputStream(InputStream originalSource,
069: String encoding, String doctypeName, String systemID) {
070: wrappedStream = originalSource instanceof BufferedInputStream ? originalSource
071: : new BufferedInputStream(originalSource);
072: support = new DoctypeSupport(doctypeName, systemID,
073: new DoctypeSupport.Readable() {
074: public int read() throws IOException {
075: return wrappedStream.read();
076: }
077: }, false, encoding);
078: }
079:
080: /**
081: * @return the content of the original source, without amendments or
082: * substitutions. Safe to call multiple times.
083: * @throws IOException if thrown while reading from the original source
084: */
085: protected String getContent(String encoding) throws IOException {
086: if (baos.size() == 0) {
087: byte[] buffer = new byte[8192];
088: int bytesRead = -1;
089: while ((bytesRead = wrappedStream.read(buffer)) > -1) {
090: baos.write(buffer, 0, bytesRead);
091: }
092: }
093: return encoding == null ? baos.toString() : baos
094: .toString(encoding);
095: }
096:
097: /**
098: * Read DOCTYPE-replaced content from the wrapped InputStream
099: */
100: public int read() throws IOException {
101: return support.read();
102: }
103:
104: public void close() throws IOException {
105: wrappedStream.close();
106: }
107: }
|