001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 /*
019 * This code has been borrowed from the Apache Xerces project. We're copying the code to
020 * keep from adding a dependency on Xerces in the Geronimo kernel.
021 */
022
023 package org.apache.geronimo.system.configuration;
024
025 import java.io.Writer;
026 import java.io.StringWriter;
027 import java.io.IOException;
028
029
030 /**
031 * The printer is responsible for sending text to the output stream
032 * or writer. This class performs direct writing for efficiency.
033 * {@link IndentPrinter} supports indentation and line wrapping by
034 * extending this class.
035 *
036 * @version $Revision: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
037 * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
038 */
039 public class Printer
040 {
041
042
043 /**
044 * The output format associated with this serializer. This will never
045 * be a null reference. If no format was passed to the constructor,
046 * the default one for this document type will be used. The format
047 * object is never changed by the serializer.
048 */
049 protected final OutputFormat format;
050
051
052 /**
053 * The writer to which the document is written.
054 */
055 protected Writer writer;
056
057
058 /**
059 * The DTD writer. When we switch to DTD mode, all output is
060 * accumulated in this DTD writer. When we switch out of it,
061 * the output is obtained as a string. Must not be reset to
062 * null until we're done with the document.
063 */
064 protected StringWriter dtdWriter;
065
066
067 /**
068 * Holds a reference to the document writer while we are
069 * in DTD mode.
070 */
071 protected Writer docWriter;
072
073
074 /**
075 * Holds the exception thrown by the serializer. Exceptions do not cause
076 * the serializer to quit, but are held and one is thrown at the end.
077 */
078 protected IOException exception;
079
080
081 /**
082 * The size of the output buffer.
083 */
084 private static final int BufferSize = 4096;
085
086
087 /**
088 * Output buffer.
089 */
090 private final char[] buffer = new char[ BufferSize ];
091
092
093 /**
094 * Position within the output buffer.
095 */
096 private int pos = 0;
097
098
099 public Printer( Writer writer, OutputFormat format)
100 {
101 this.writer = writer;
102 this.format = format;
103 exception = null;
104 dtdWriter = null;
105 docWriter = null;
106 pos = 0;
107 }
108
109
110 public IOException getException()
111 {
112 return exception;
113 }
114
115
116 /**
117 * Called by any of the DTD handlers to enter DTD mode.
118 * Once entered, all output will be accumulated in a string
119 * that can be printed as part of the document's DTD.
120 * This method may be called any number of time but will only
121 * have affect the first time it's called. To exist DTD state
122 * and get the accumulated DTD, call {@link #leaveDTD}.
123 */
124 public void enterDTD()
125 throws IOException
126 {
127 // Can only enter DTD state once. Once we're out of DTD
128 // state, can no longer re-enter it.
129 if ( dtdWriter == null ) {
130 flushLine( false );
131
132 dtdWriter = new StringWriter();
133 docWriter = writer;
134 writer = dtdWriter;
135 }
136 }
137
138
139 /**
140 * Called by the root element to leave DTD mode and if any
141 * DTD parts were printer, will return a string with their
142 * textual content.
143 */
144 public String leaveDTD()
145 throws IOException
146 {
147 // Only works if we're going out of DTD mode.
148 if ( writer == dtdWriter ) {
149 flushLine( false );
150
151 writer = docWriter;
152 return dtdWriter.toString();
153 } else
154 return null;
155 }
156
157
158 public void printText( String text )
159 throws IOException
160 {
161 try {
162 int length = text.length();
163 for ( int i = 0 ; i < length ; ++i ) {
164 if ( pos == BufferSize ) {
165 writer.write( buffer );
166 pos = 0;
167 }
168 buffer[ pos ] = text.charAt( i );
169 ++pos;
170 }
171 } catch ( IOException except ) {
172 // We don't throw an exception, but hold it
173 // until the end of the document.
174 if ( exception == null )
175 exception = except;
176 throw except;
177 }
178 }
179
180
181 public void printText( StringBuffer text )
182 throws IOException
183 {
184 try {
185 int length = text.length();
186 for ( int i = 0 ; i < length ; ++i ) {
187 if ( pos == BufferSize ) {
188 writer.write( buffer );
189 pos = 0;
190 }
191 buffer[ pos ] = text.charAt( i );
192 ++pos;
193 }
194 } catch ( IOException except ) {
195 // We don't throw an exception, but hold it
196 // until the end of the document.
197 if ( exception == null )
198 exception = except;
199 throw except;
200 }
201 }
202
203
204 public void printText( char[] chars, int start, int length )
205 throws IOException
206 {
207 try {
208 while ( length-- > 0 ) {
209 if ( pos == BufferSize ) {
210 writer.write( buffer );
211 pos = 0;
212 }
213 buffer[ pos ] = chars[ start ];
214 ++start;
215 ++pos;
216 }
217 } catch ( IOException except ) {
218 // We don't throw an exception, but hold it
219 // until the end of the document.
220 if ( exception == null )
221 exception = except;
222 throw except;
223 }
224 }
225
226
227 public void printText( char ch )
228 throws IOException
229 {
230 try {
231 if ( pos == BufferSize ) {
232 writer.write( buffer );
233 pos = 0;
234 }
235 buffer[ pos ] = ch;
236 ++pos;
237 } catch ( IOException except ) {
238 // We don't throw an exception, but hold it
239 // until the end of the document.
240 if ( exception == null )
241 exception = except;
242 throw except;
243 }
244 }
245
246
247 public void printSpace()
248 throws IOException
249 {
250 try {
251 if ( pos == BufferSize ) {
252 writer.write( buffer );
253 pos = 0;
254 }
255 buffer[ pos ] = ' ';
256 ++pos;
257 } catch ( IOException except ) {
258 // We don't throw an exception, but hold it
259 // until the end of the document.
260 if ( exception == null )
261 exception = except;
262 throw except;
263 }
264 }
265
266
267 public void breakLine()
268 throws IOException
269 {
270 try {
271 if ( pos == BufferSize ) {
272 writer.write( buffer );
273 pos = 0;
274 }
275 buffer[ pos ] = '\n';
276 ++pos;
277 } catch ( IOException except ) {
278 // We don't throw an exception, but hold it
279 // until the end of the document.
280 if ( exception == null )
281 exception = except;
282 throw except;
283 }
284 }
285
286
287 public void breakLine( boolean preserveSpace )
288 throws IOException
289 {
290 breakLine();
291 }
292
293
294 public void flushLine( boolean preserveSpace )
295 throws IOException
296 {
297 // Write anything left in the buffer into the writer.
298 try {
299 writer.write( buffer, 0, pos );
300 } catch ( IOException except ) {
301 // We don't throw an exception, but hold it
302 // until the end of the document.
303 if ( exception == null )
304 exception = except;
305 }
306 pos = 0;
307 }
308
309
310 /**
311 * Flush the output stream. Must be called when done printing
312 * the document, otherwise some text might be buffered.
313 */
314 public void flush()
315 throws IOException
316 {
317 try {
318 writer.write( buffer, 0, pos );
319 writer.flush();
320 } catch ( IOException except ) {
321 // We don't throw an exception, but hold it
322 // until the end of the document.
323 if ( exception == null )
324 exception = except;
325 throw except;
326 }
327 pos = 0;
328 }
329
330
331 public void indent()
332 {
333 // NOOP
334 }
335
336
337 public void unindent()
338 {
339 // NOOP
340 }
341
342
343 public int getNextIndent()
344 {
345 return 0;
346 }
347
348
349 public void setNextIndent( int indent )
350 {
351 }
352
353
354 public void setThisIndent( int indent )
355 {
356 }
357
358
359 }