001: /*
002: * The Apache Software License, Version 1.1
003: *
004: *
005: * Copyright (c) 1999 The Apache Software Foundation. All rights
006: * reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by the
023: * Apache Software Foundation (http://www.apache.org/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. The names "Xerces" and "Apache Software Foundation" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation and was
052: * originally based on software copyright (c) 1999, International
053: * Business Machines, Inc., http://www.apache.org. For more
054: * information on the Apache Software Foundation, please see
055: * <http://www.apache.org/>.
056: */
057:
058: // Sep 14, 2000:
059: // Fixed serializer to report IO exception directly, instead at
060: // the end of document processing.
061: // Reported by Patrick Higgins <phiggins@transzap.com>
062:
063: package org.apache.xml.serialize;
064:
065: import java.io.Writer;
066: import java.io.StringWriter;
067: import java.io.IOException;
068:
069: /**
070: * The printer is responsible for sending text to the output stream
071: * or writer. This class performs direct writing for efficiency.
072: * {@link IndentPrinter} supports indentation and line wrapping by
073: * extending this class.
074: *
075: * @version $Revision: 1.6 $ $Date: 2001/04/19 23:40:32 $
076: * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
077: */
078: public class Printer {
079:
080: /**
081: * The output format associated with this serializer. This will never
082: * be a null reference. If no format was passed to the constructor,
083: * the default one for this document type will be used. The format
084: * object is never changed by the serializer.
085: */
086: protected final OutputFormat _format;
087:
088: /**
089: * The writer to which the document is written.
090: */
091: protected Writer _writer;
092:
093: /**
094: * The DTD writer. When we switch to DTD mode, all output is
095: * accumulated in this DTD writer. When we switch out of it,
096: * the output is obtained as a string. Must not be reset to
097: * null until we're done with the document.
098: */
099: protected StringWriter _dtdWriter;
100:
101: /**
102: * Holds a reference to the document writer while we are
103: * in DTD mode.
104: */
105: protected Writer _docWriter;
106:
107: /**
108: * Holds the exception thrown by the serializer. Exceptions do not cause
109: * the serializer to quit, but are held and one is thrown at the end.
110: */
111: protected IOException _exception;
112:
113: /**
114: * The size of the output buffer.
115: */
116: private static final int BufferSize = 4096;
117:
118: /**
119: * Output buffer.
120: */
121: private final char[] _buffer = new char[BufferSize];
122:
123: /**
124: * Position within the output buffer.
125: */
126: private int _pos = 0;
127:
128: public Printer(Writer writer, OutputFormat format) {
129: _writer = writer;
130: _format = format;
131: _exception = null;
132: _dtdWriter = null;
133: _docWriter = null;
134: _pos = 0;
135: }
136:
137: public IOException getException() {
138: return _exception;
139: }
140:
141: /**
142: * Called by any of the DTD handlers to enter DTD mode.
143: * Once entered, all output will be accumulated in a string
144: * that can be printed as part of the document's DTD.
145: * This method may be called any number of time but will only
146: * have affect the first time it's called. To exist DTD state
147: * and get the accumulated DTD, call {@link #leaveDTD}.
148: */
149: public void enterDTD() throws IOException {
150: // Can only enter DTD state once. Once we're out of DTD
151: // state, can no longer re-enter it.
152: if (_dtdWriter == null) {
153: flushLine(false);
154:
155: _dtdWriter = new StringWriter();
156: _docWriter = _writer;
157: _writer = _dtdWriter;
158: }
159: }
160:
161: /**
162: * Called by the root element to leave DTD mode and if any
163: * DTD parts were printer, will return a string with their
164: * textual content.
165: */
166: public String leaveDTD() throws IOException {
167: // Only works if we're going out of DTD mode.
168: if (_writer == _dtdWriter) {
169: flushLine(false);
170:
171: _writer = _docWriter;
172: return _dtdWriter.toString();
173: } else
174: return null;
175: }
176:
177: public void printText(String text) throws IOException {
178: try {
179: int length = text.length();
180: for (int i = 0; i < length; ++i) {
181: if (_pos == BufferSize) {
182: _writer.write(_buffer);
183: _pos = 0;
184: }
185: _buffer[_pos] = text.charAt(i);
186: ++_pos;
187: }
188: } catch (IOException except) {
189: // We don't throw an exception, but hold it
190: // until the end of the document.
191: if (_exception == null)
192: _exception = except;
193: throw except;
194: }
195: }
196:
197: public void printText(StringBuffer text) throws IOException {
198: try {
199: int length = text.length();
200: for (int i = 0; i < length; ++i) {
201: if (_pos == BufferSize) {
202: _writer.write(_buffer);
203: _pos = 0;
204: }
205: _buffer[_pos] = text.charAt(i);
206: ++_pos;
207: }
208: } catch (IOException except) {
209: // We don't throw an exception, but hold it
210: // until the end of the document.
211: if (_exception == null)
212: _exception = except;
213: throw except;
214: }
215: }
216:
217: public void printText(char[] chars, int start, int length)
218: throws IOException {
219: try {
220: while (length-- > 0) {
221: if (_pos == BufferSize) {
222: _writer.write(_buffer);
223: _pos = 0;
224: }
225: _buffer[_pos] = chars[start];
226: ++start;
227: ++_pos;
228: }
229: } catch (IOException except) {
230: // We don't throw an exception, but hold it
231: // until the end of the document.
232: if (_exception == null)
233: _exception = except;
234: throw except;
235: }
236: }
237:
238: public void printText(char ch) throws IOException {
239: try {
240: if (_pos == BufferSize) {
241: _writer.write(_buffer);
242: _pos = 0;
243: }
244: _buffer[_pos] = ch;
245: ++_pos;
246: } catch (IOException except) {
247: // We don't throw an exception, but hold it
248: // until the end of the document.
249: if (_exception == null)
250: _exception = except;
251: throw except;
252: }
253: }
254:
255: public void printSpace() throws IOException {
256: try {
257: if (_pos == BufferSize) {
258: _writer.write(_buffer);
259: _pos = 0;
260: }
261: _buffer[_pos] = ' ';
262: ++_pos;
263: } catch (IOException except) {
264: // We don't throw an exception, but hold it
265: // until the end of the document.
266: if (_exception == null)
267: _exception = except;
268: throw except;
269: }
270: }
271:
272: public void breakLine() throws IOException {
273: try {
274: if (_pos == BufferSize) {
275: _writer.write(_buffer);
276: _pos = 0;
277: }
278: _buffer[_pos] = '\n';
279: ++_pos;
280: } catch (IOException except) {
281: // We don't throw an exception, but hold it
282: // until the end of the document.
283: if (_exception == null)
284: _exception = except;
285: throw except;
286: }
287: }
288:
289: public void breakLine(boolean preserveSpace) throws IOException {
290: breakLine();
291: }
292:
293: public void flushLine(boolean preserveSpace) throws IOException {
294: // Write anything left in the buffer into the writer.
295: try {
296: _writer.write(_buffer, 0, _pos);
297: } catch (IOException except) {
298: // We don't throw an exception, but hold it
299: // until the end of the document.
300: if (_exception == null)
301: _exception = except;
302: }
303: _pos = 0;
304: }
305:
306: /**
307: * Flush the output stream. Must be called when done printing
308: * the document, otherwise some text might be buffered.
309: */
310: public void flush() throws IOException {
311: try {
312: _writer.write(_buffer, 0, _pos);
313: _writer.flush();
314: } catch (IOException except) {
315: // We don't throw an exception, but hold it
316: // until the end of the document.
317: if (_exception == null)
318: _exception = except;
319: throw except;
320: }
321: _pos = 0;
322: }
323:
324: public void indent() {
325: // NOOP
326: }
327:
328: public void unindent() {
329: // NOOP
330: }
331:
332: public int getNextIndent() {
333: return 0;
334: }
335:
336: public void setNextIndent(int indent) {
337: }
338:
339: public void setThisIndent(int indent) {
340: }
341:
342: }
|