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    }