1/*
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3 */
4/*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements.  See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21
22// Sep 14, 2000:
23//  Fixed serializer to report IO exception directly, instead at
24//  the end of document processing.
25//  Reported by Patrick Higgins <phiggins@transzap.com>
26
27
28package com.sun.org.apache.xml.internal.serialize;
29
30
31import java.io.Writer;
32import java.io.StringWriter;
33import java.io.IOException;
34
35
36/**
37 * The printer is responsible for sending text to the output stream
38 * or writer. This class performs direct writing for efficiency.
39 * {@link IndentPrinter} supports indentation and line wrapping by
40 * extending this class.
41 *
42 * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
43 *
44 * @deprecated As of JDK 9, Xerces 2.9.0, Xerces DOM L3 Serializer implementation
45 * is replaced by that of Xalan. Main class
46 * {@link com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl} is replaced
47 * by {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}.
48 */
49@Deprecated
50public class Printer
51{
52
53
54    /**
55     * The output format associated with this serializer. This will never
56     * be a null reference. If no format was passed to the constructor,
57     * the default one for this document type will be used. The format
58     * object is never changed by the serializer.
59     */
60    protected final OutputFormat _format;
61
62
63    /**
64     * The writer to which the document is written.
65     */
66    protected Writer             _writer;
67
68
69    /**
70     * The DTD writer. When we switch to DTD mode, all output is
71     * accumulated in this DTD writer. When we switch out of it,
72     * the output is obtained as a string. Must not be reset to
73     * null until we're done with the document.
74     */
75    protected StringWriter       _dtdWriter;
76
77
78    /**
79     * Holds a reference to the document writer while we are
80     * in DTD mode.
81     */
82    protected Writer          _docWriter;
83
84
85    /**
86     * Holds the exception thrown by the serializer.  Exceptions do not cause
87     * the serializer to quit, but are held and one is thrown at the end.
88     */
89    protected IOException     _exception;
90
91
92    /**
93     * The size of the output buffer.
94     */
95    private static final int BufferSize = 4096;
96
97
98    /**
99     * Output buffer.
100     */
101    private final char[]  _buffer = new char[ BufferSize ];
102
103
104    /**
105     * Position within the output buffer.
106     */
107    private int           _pos = 0;
108
109
110    public Printer( Writer writer, OutputFormat format)
111    {
112        _writer = writer;
113        _format = format;
114        _exception = null;
115        _dtdWriter = null;
116        _docWriter = null;
117        _pos = 0;
118    }
119
120
121    public IOException getException()
122    {
123        return _exception;
124    }
125
126
127    /**
128     * Called by any of the DTD handlers to enter DTD mode.
129     * Once entered, all output will be accumulated in a string
130     * that can be printed as part of the document's DTD.
131     * This method may be called any number of time but will only
132     * have affect the first time it's called. To exist DTD state
133     * and get the accumulated DTD, call {@link #leaveDTD}.
134     */
135    public void enterDTD()
136        throws IOException
137    {
138        // Can only enter DTD state once. Once we're out of DTD
139        // state, can no longer re-enter it.
140        if ( _dtdWriter == null ) {
141            flushLine( false );
142
143                        _dtdWriter = new StringWriter();
144            _docWriter = _writer;
145            _writer = _dtdWriter;
146        }
147    }
148
149
150    /**
151     * Called by the root element to leave DTD mode and if any
152     * DTD parts were printer, will return a string with their
153     * textual content.
154     */
155    public String leaveDTD()
156        throws IOException
157    {
158        // Only works if we're going out of DTD mode.
159        if ( _writer == _dtdWriter ) {
160            flushLine( false );
161
162                        _writer = _docWriter;
163            return _dtdWriter.toString();
164        } else
165            return null;
166    }
167
168
169    public void printText( String text )
170        throws IOException
171    {
172        try {
173            int length = text.length();
174            for ( int i = 0 ; i < length ; ++i ) {
175                if ( _pos == BufferSize ) {
176                    _writer.write( _buffer );
177                    _pos = 0;
178                }
179                _buffer[ _pos ] = text.charAt( i );
180                ++_pos;
181            }
182        } catch ( IOException except ) {
183            // We don't throw an exception, but hold it
184            // until the end of the document.
185            if ( _exception == null )
186                _exception = except;
187            throw except;
188        }
189    }
190
191
192    public void printText( StringBuffer text )
193        throws IOException
194    {
195        try {
196            int length = text.length();
197            for ( int i = 0 ; i < length ; ++i ) {
198                if ( _pos == BufferSize ) {
199                    _writer.write( _buffer );
200                    _pos = 0;
201                }
202                _buffer[ _pos ] = text.charAt( i );
203                ++_pos;
204            }
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
215    public void printText( char[] chars, int start, int length )
216        throws IOException
217    {
218        try {
219            while ( length-- > 0 ) {
220                if ( _pos == BufferSize ) {
221                    _writer.write( _buffer );
222                    _pos = 0;
223                }
224                _buffer[ _pos ] = chars[ start ];
225                ++start;
226                ++_pos;
227            }
228        } catch ( IOException except ) {
229            // We don't throw an exception, but hold it
230            // until the end of the document.
231            if ( _exception == null )
232                _exception = except;
233            throw except;
234        }
235    }
236
237
238    public void printText( char ch )
239        throws IOException
240    {
241        try {
242            if ( _pos == BufferSize ) {
243                _writer.write( _buffer );
244                _pos = 0;
245            }
246            _buffer[ _pos ] = ch;
247            ++_pos;
248        } catch ( IOException except ) {
249            // We don't throw an exception, but hold it
250            // until the end of the document.
251            if ( _exception == null )
252                _exception = except;
253            throw except;
254        }
255    }
256
257
258    public void printSpace()
259        throws IOException
260    {
261        try {
262            if ( _pos == BufferSize ) {
263                _writer.write( _buffer );
264                _pos = 0;
265            }
266            _buffer[ _pos ] = ' ';
267            ++_pos;
268        } catch ( IOException except ) {
269            // We don't throw an exception, but hold it
270            // until the end of the document.
271            if ( _exception == null )
272                _exception = except;
273            throw except;
274        }
275    }
276
277
278    public void breakLine()
279        throws IOException
280    {
281        try {
282            if ( _pos == BufferSize ) {
283                _writer.write( _buffer );
284                _pos = 0;
285            }
286            _buffer[ _pos ] = '\n';
287            ++_pos;
288        } catch ( IOException except ) {
289            // We don't throw an exception, but hold it
290            // until the end of the document.
291            if ( _exception == null )
292                _exception = except;
293            throw except;
294        }
295    }
296
297
298    public void breakLine( boolean preserveSpace )
299        throws IOException
300    {
301        breakLine();
302    }
303
304
305    public void flushLine( boolean preserveSpace )
306        throws IOException
307    {
308        // Write anything left in the buffer into the writer.
309        try {
310            _writer.write( _buffer, 0, _pos );
311        } catch ( IOException except ) {
312            // We don't throw an exception, but hold it
313            // until the end of the document.
314            if ( _exception == null )
315                _exception = except;
316        }
317        _pos = 0;
318    }
319
320
321    /**
322     * Flush the output stream. Must be called when done printing
323     * the document, otherwise some text might be buffered.
324     */
325    public void flush()
326        throws IOException
327    {
328        try {
329            _writer.write( _buffer, 0, _pos );
330            _writer.flush();
331        } catch ( IOException except ) {
332            // We don't throw an exception, but hold it
333            // until the end of the document.
334            if ( _exception == null )
335                _exception = except;
336            throw except;
337        }
338        _pos = 0;
339    }
340
341
342    public void indent()
343    {
344        // NOOP
345    }
346
347
348    public void unindent()
349    {
350        // NOOP
351    }
352
353
354    public int getNextIndent()
355    {
356        return 0;
357    }
358
359
360    public void setNextIndent( int indent )
361    {
362    }
363
364
365    public void setThisIndent( int indent )
366    {
367    }
368
369
370}
371