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 }