001: /*
002: * Copyright 1999-2002,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: // Sep 14, 2000:
018: // Fixed serializer to report IO exception directly, instead at
019: // the end of document processing.
020: // Reported by Patrick Higgins <phiggins@transzap.com>
021:
022: package org.jasig.portal.serialize;
023:
024: import java.io.Writer;
025: import java.io.StringWriter;
026: import java.io.IOException;
027:
028: /**
029: * The printer is responsible for sending text to the output stream
030: * or writer. This class performs direct writing for efficiency.
031: * {@link IndentPrinter} supports indentation and line wrapping by
032: * extending this class.
033: *
034: * @version $Revision: 36559 $ $Date: 2006-04-28 11:38:13 -0700 (Fri, 28 Apr 2006) $
035: * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
036: */
037: public class Printer {
038:
039: /**
040: * The output format associated with this serializer. This will never
041: * be a null reference. If no format was passed to the constructor,
042: * the default one for this document type will be used. The format
043: * object is never changed by the serializer.
044: */
045: protected final OutputFormat _format;
046:
047: /**
048: * The writer to which the document is written.
049: */
050: protected Writer _writer;
051:
052: /**
053: * The DTD writer. When we switch to DTD mode, all output is
054: * accumulated in this DTD writer. When we switch out of it,
055: * the output is obtained as a string. Must not be reset to
056: * null until we're done with the document.
057: */
058: protected StringWriter _dtdWriter;
059:
060: /**
061: * Holds a reference to the document writer while we are
062: * in DTD mode.
063: */
064: protected Writer _docWriter;
065:
066: /**
067: * Holds the exception thrown by the serializer. Exceptions do not cause
068: * the serializer to quit, but are held and one is thrown at the end.
069: */
070: protected IOException _exception;
071:
072: /**
073: * The size of the output buffer.
074: */
075: private static final int BufferSize = 4096;
076:
077: /**
078: * Output buffer.
079: */
080: private final char[] _buffer = new char[BufferSize];
081:
082: /**
083: * Position within the output buffer.
084: */
085: private int _pos = 0;
086:
087: public Printer(Writer writer, OutputFormat format) {
088: _writer = writer;
089: _format = format;
090: _exception = null;
091: _dtdWriter = null;
092: _docWriter = null;
093: _pos = 0;
094: }
095:
096: public IOException getException() {
097: return _exception;
098: }
099:
100: /**
101: * Called by any of the DTD handlers to enter DTD mode.
102: * Once entered, all output will be accumulated in a string
103: * that can be printed as part of the document's DTD.
104: * This method may be called any number of time but will only
105: * have affect the first time it's called. To exist DTD state
106: * and get the accumulated DTD, call {@link #leaveDTD}.
107: */
108: public void enterDTD() throws IOException {
109: // Can only enter DTD state once. Once we're out of DTD
110: // state, can no longer re-enter it.
111: if (_dtdWriter == null) {
112: flushLine(false);
113:
114: _dtdWriter = new StringWriter();
115: _docWriter = _writer;
116: _writer = _dtdWriter;
117: }
118: }
119:
120: /**
121: * Called by the root element to leave DTD mode and if any
122: * DTD parts were printer, will return a string with their
123: * textual content.
124: */
125: public String leaveDTD() throws IOException {
126: // Only works if we're going out of DTD mode.
127: if (_writer == _dtdWriter) {
128: flushLine(false);
129:
130: _writer = _docWriter;
131: return _dtdWriter.toString();
132: } else
133: return null;
134: }
135:
136: public void printText(String text) throws IOException {
137: try {
138: int length = text.length();
139: for (int i = 0; i < length; ++i) {
140: if (_pos == BufferSize) {
141: _writer.write(_buffer);
142: _pos = 0;
143: }
144: _buffer[_pos] = text.charAt(i);
145: ++_pos;
146: }
147: } catch (IOException except) {
148: // We don't throw an exception, but hold it
149: // until the end of the document.
150: if (_exception == null)
151: _exception = except;
152: throw except;
153: }
154: }
155:
156: public void printText(StringBuffer text) throws IOException {
157: try {
158: int length = text.length();
159: for (int i = 0; i < length; ++i) {
160: if (_pos == BufferSize) {
161: _writer.write(_buffer);
162: _pos = 0;
163: }
164: _buffer[_pos] = text.charAt(i);
165: ++_pos;
166: }
167: } catch (IOException except) {
168: // We don't throw an exception, but hold it
169: // until the end of the document.
170: if (_exception == null)
171: _exception = except;
172: throw except;
173: }
174: }
175:
176: public void printText(char[] chars, int start, int length)
177: throws IOException {
178: try {
179: while (length-- > 0) {
180: if (_pos == BufferSize) {
181: _writer.write(_buffer);
182: _pos = 0;
183: }
184: _buffer[_pos] = chars[start];
185: ++start;
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(char ch) throws IOException {
198: try {
199: if (_pos == BufferSize) {
200: _writer.write(_buffer);
201: _pos = 0;
202: }
203: _buffer[_pos] = ch;
204: ++_pos;
205: } catch (IOException except) {
206: // We don't throw an exception, but hold it
207: // until the end of the document.
208: if (_exception == null)
209: _exception = except;
210: throw except;
211: }
212: }
213:
214: public void printSpace() throws IOException {
215: try {
216: if (_pos == BufferSize) {
217: _writer.write(_buffer);
218: _pos = 0;
219: }
220: _buffer[_pos] = ' ';
221: ++_pos;
222: } catch (IOException except) {
223: // We don't throw an exception, but hold it
224: // until the end of the document.
225: if (_exception == null)
226: _exception = except;
227: throw except;
228: }
229: }
230:
231: public void breakLine() throws IOException {
232: try {
233: if (_pos == BufferSize) {
234: _writer.write(_buffer);
235: _pos = 0;
236: }
237: _buffer[_pos] = '\n';
238: ++_pos;
239: } catch (IOException except) {
240: // We don't throw an exception, but hold it
241: // until the end of the document.
242: if (_exception == null)
243: _exception = except;
244: throw except;
245: }
246: }
247:
248: public void breakLine(boolean preserveSpace) throws IOException {
249: breakLine();
250: }
251:
252: public void flushLine(boolean preserveSpace) throws IOException {
253: // Write anything left in the buffer into the writer.
254: try {
255: _writer.write(_buffer, 0, _pos);
256: } catch (IOException except) {
257: // We don't throw an exception, but hold it
258: // until the end of the document.
259: if (_exception == null)
260: _exception = except;
261: }
262: _pos = 0;
263: }
264:
265: /**
266: * Flush the output stream. Must be called when done printing
267: * the document, otherwise some text might be buffered.
268: */
269: public void flush() throws IOException {
270: try {
271: _writer.write(_buffer, 0, _pos);
272: _writer.flush();
273: } catch (IOException except) {
274: // We don't throw an exception, but hold it
275: // until the end of the document.
276: if (_exception == null)
277: _exception = except;
278: throw except;
279: }
280: _pos = 0;
281: }
282:
283: public void indent() {
284: // NOOP
285: }
286:
287: public void unindent() {
288: // NOOP
289: }
290:
291: public int getNextIndent() {
292: return 0;
293: }
294:
295: public void setNextIndent(int indent) {
296: }
297:
298: public void setThisIndent(int indent) {
299: }
300:
301: }
|