1 // ======================================================================== 2 // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd. 3 // ------------------------------------------------------------------------ 4 // All rights reserved. This program and the accompanying materials 5 // are made available under the terms of the Eclipse Public License v1.0 6 // and Apache License v2.0 which accompanies this distribution. 7 // The Eclipse Public License is available at 8 // http://www.eclipse.org/legal/epl-v10.html 9 // The Apache License v2.0 is available at 10 // http://www.opensource.org/licenses/apache2.0.php 11 // You may elect to redistribute this code under either of these licenses. 12 // ======================================================================== 13 14 15 package org.eclipse.jetty.io; 16 17 import java.io.BufferedWriter; 18 import java.io.InterruptedIOException; 19 import java.io.IOException; 20 import java.io.OutputStream; 21 import java.io.OutputStreamWriter; 22 import java.io.PrintWriter; 23 import java.io.Writer; 24 25 import org.eclipse.jetty.util.log.Log; 26 27 /* ------------------------------------------------------------ */ 28 /** 29 * A wrapper for the {@link java.io.PrintWriter} that re-throws the instances of 30 * {@link java.io.IOException} thrown by the underlying implementation of 31 * {@link java.io.Writer} as {@link RunimeIOException} instances. 32 */ 33 public class UncheckedPrintWriter extends PrintWriter 34 { 35 private boolean autoFlush = false; 36 37 /* ------------------------------------------------------------ */ 38 /** 39 * Line separator string. This is the value of the line.separator 40 * property at the moment that the stream was created. 41 */ 42 private String lineSeparator; 43 44 public UncheckedPrintWriter (Writer out) 45 { 46 this(out, false); 47 } 48 49 /* ------------------------------------------------------------ */ 50 /** 51 * Create a new PrintWriter. 52 * 53 * @param out A character-output stream 54 * @param autoFlush A boolean; if true, the println() methods will flush 55 * the output buffer 56 */ 57 public UncheckedPrintWriter(Writer out, boolean autoFlush) 58 { 59 super(out, autoFlush); 60 this.autoFlush = autoFlush; 61 this.lineSeparator = System.getProperty("line.separator"); 62 } 63 64 /* ------------------------------------------------------------ */ 65 /** 66 * Create a new PrintWriter, without automatic line flushing, from an 67 * existing OutputStream. This convenience constructor creates the 68 * necessary intermediate OutputStreamWriter, which will convert characters 69 * into bytes using the default character encoding. 70 * 71 * @param out An output stream 72 * 73 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 74 */ 75 public UncheckedPrintWriter(OutputStream out) 76 { 77 this(out, false); 78 } 79 80 /* ------------------------------------------------------------ */ 81 /** 82 * Create a new PrintWriter from an existing OutputStream. This 83 * convenience constructor creates the necessary intermediate 84 * OutputStreamWriter, which will convert characters into bytes using the 85 * default character encoding. 86 * 87 * @param out An output stream 88 * @param autoFlush A boolean; if true, the println() methods will flush 89 * the output buffer 90 * 91 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 92 */ 93 public UncheckedPrintWriter(OutputStream out, boolean autoFlush) 94 { 95 this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush); 96 } 97 98 /* ------------------------------------------------------------ */ 99 /** Check to make sure that the stream has not been closed */ 100 private void isOpen() throws IOException 101 { 102 if (super.out == null) 103 throw new IOException("Stream closed"); 104 } 105 106 /* ------------------------------------------------------------ */ 107 /** 108 * Flush the stream. 109 */ 110 public void flush() { 111 try { 112 synchronized (lock) { 113 isOpen(); 114 out.flush(); 115 } 116 } 117 catch (IOException ex) { 118 Log.debug(ex); 119 setError(); 120 throw new RuntimeIOException(ex); 121 } 122 } 123 124 /* ------------------------------------------------------------ */ 125 /** 126 * Close the stream. 127 */ 128 public void close() { 129 try { 130 synchronized (lock) { 131 out.close(); 132 } 133 } 134 catch (IOException ex) { 135 Log.debug(ex); 136 setError(); 137 throw new RuntimeIOException(ex); 138 } 139 } 140 141 /* ------------------------------------------------------------ */ 142 /** 143 * Write a single character. 144 * @param c int specifying a character to be written. 145 */ 146 public void write(int c) { 147 try { 148 synchronized (lock) { 149 isOpen(); 150 out.write(c); 151 } 152 } 153 catch (InterruptedIOException x) { 154 Thread.currentThread().interrupt(); 155 } 156 catch (IOException ex) { 157 Log.debug(ex); 158 setError(); 159 throw new RuntimeIOException(ex); 160 } 161 } 162 163 /* ------------------------------------------------------------ */ 164 /** 165 * Write a portion of an array of characters. 166 * @param buf Array of characters 167 * @param off Offset from which to start writing characters 168 * @param len Number of characters to write 169 */ 170 public void write(char buf[], int off, int len) { 171 try { 172 synchronized (lock) { 173 isOpen(); 174 out.write(buf, off, len); 175 } 176 } 177 catch (InterruptedIOException x) { 178 Thread.currentThread().interrupt(); 179 } 180 catch (IOException ex) { 181 Log.debug(ex); 182 setError(); 183 throw new RuntimeIOException(ex); 184 } 185 } 186 187 /* ------------------------------------------------------------ */ 188 /** 189 * Write an array of characters. This method cannot be inherited from the 190 * Writer class because it must suppress I/O exceptions. 191 * @param buf Array of characters to be written 192 */ 193 public void write(char buf[]) { 194 this.write(buf, 0, buf.length); 195 } 196 197 /* ------------------------------------------------------------ */ 198 /** 199 * Write a portion of a string. 200 * @param s A String 201 * @param off Offset from which to start writing characters 202 * @param len Number of characters to write 203 */ 204 public void write(String s, int off, int len) { 205 try { 206 synchronized (lock) { 207 isOpen(); 208 out.write(s, off, len); 209 } 210 } 211 catch (InterruptedIOException x) { 212 Thread.currentThread().interrupt(); 213 } 214 catch (IOException ex) { 215 Log.debug(ex); 216 setError(); 217 throw new RuntimeIOException(ex); 218 } 219 } 220 221 /* ------------------------------------------------------------ */ 222 /** 223 * Write a string. This method cannot be inherited from the Writer class 224 * because it must suppress I/O exceptions. 225 * @param s String to be written 226 */ 227 public void write(String s) { 228 this.write(s, 0, s.length()); 229 } 230 231 private void newLine() { 232 try { 233 synchronized (lock) { 234 isOpen(); 235 out.write(lineSeparator); 236 if (autoFlush) 237 out.flush(); 238 } 239 } 240 catch (InterruptedIOException x) { 241 Thread.currentThread().interrupt(); 242 } 243 catch (IOException ex) { 244 Log.debug(ex); 245 setError(); 246 throw new RuntimeIOException(ex); 247 } 248 } 249 250 251 /* Methods that do not terminate lines */ 252 253 /* ------------------------------------------------------------ */ 254 /** 255 * Print a boolean value. The string produced by <code>{@link 256 * java.lang.String#valueOf(boolean)}</code> is translated into bytes 257 * according to the platform's default character encoding, and these bytes 258 * are written in exactly the manner of the <code>{@link 259 * #write(int)}</code> method. 260 * 261 * @param b The <code>boolean</code> to be printed 262 */ 263 public void print(boolean b) { 264 this.write(b ? "true" : "false"); 265 } 266 267 /* ------------------------------------------------------------ */ 268 /** 269 * Print a character. The character is translated into one or more bytes 270 * according to the platform's default character encoding, and these bytes 271 * are written in exactly the manner of the <code>{@link 272 * #write(int)}</code> method. 273 * 274 * @param c The <code>char</code> to be printed 275 */ 276 public void print(char c) { 277 this.write(c); 278 } 279 280 /* ------------------------------------------------------------ */ 281 /** 282 * Print an integer. The string produced by <code>{@link 283 * java.lang.String#valueOf(int)}</code> is translated into bytes according 284 * to the platform's default character encoding, and these bytes are 285 * written in exactly the manner of the <code>{@link #write(int)}</code> 286 * method. 287 * 288 * @param i The <code>int</code> to be printed 289 * @see java.lang.Integer#toString(int) 290 */ 291 public void print(int i) { 292 this.write(String.valueOf(i)); 293 } 294 295 /* ------------------------------------------------------------ */ 296 /** 297 * Print a long integer. The string produced by <code>{@link 298 * java.lang.String#valueOf(long)}</code> is translated into bytes 299 * according to the platform's default character encoding, and these bytes 300 * are written in exactly the manner of the <code>{@link #write(int)}</code> 301 * method. 302 * 303 * @param l The <code>long</code> to be printed 304 * @see java.lang.Long#toString(long) 305 */ 306 public void print(long l) { 307 this.write(String.valueOf(l)); 308 } 309 310 /* ------------------------------------------------------------ */ 311 /** 312 * Print a floating-point number. The string produced by <code>{@link 313 * java.lang.String#valueOf(float)}</code> is translated into bytes 314 * according to the platform's default character encoding, and these bytes 315 * are written in exactly the manner of the <code>{@link #write(int)}</code> 316 * method. 317 * 318 * @param f The <code>float</code> to be printed 319 * @see java.lang.Float#toString(float) 320 */ 321 public void print(float f) { 322 this.write(String.valueOf(f)); 323 } 324 325 /* ------------------------------------------------------------ */ 326 /** 327 * Print a double-precision floating-point number. The string produced by 328 * <code>{@link java.lang.String#valueOf(double)}</code> is translated into 329 * bytes according to the platform's default character encoding, and these 330 * bytes are written in exactly the manner of the <code>{@link 331 * #write(int)}</code> method. 332 * 333 * @param d The <code>double</code> to be printed 334 * @see java.lang.Double#toString(double) 335 */ 336 public void print(double d) { 337 this.write(String.valueOf(d)); 338 } 339 340 /* ------------------------------------------------------------ */ 341 /** 342 * Print an array of characters. The characters are converted into bytes 343 * according to the platform's default character encoding, and these bytes 344 * are written in exactly the manner of the <code>{@link #write(int)}</code> 345 * method. 346 * 347 * @param s The array of chars to be printed 348 * 349 * @throws NullPointerException If <code>s</code> is <code>null</code> 350 */ 351 public void print(char s[]) { 352 this.write(s); 353 } 354 355 /* ------------------------------------------------------------ */ 356 /** 357 * Print a string. If the argument is <code>null</code> then the string 358 * <code>"null"</code> is printed. Otherwise, the string's characters are 359 * converted into bytes according to the platform's default character 360 * encoding, and these bytes are written in exactly the manner of the 361 * <code>{@link #write(int)}</code> method. 362 * 363 * @param s The <code>String</code> to be printed 364 */ 365 public void print(String s) { 366 if (s == null) { 367 s = "null"; 368 } 369 this.write(s); 370 } 371 372 /* ------------------------------------------------------------ */ 373 /** 374 * Print an object. The string produced by the <code>{@link 375 * java.lang.String#valueOf(Object)}</code> method is translated into bytes 376 * according to the platform's default character encoding, and these bytes 377 * are written in exactly the manner of the <code>{@link #write(int)}</code> 378 * method. 379 * 380 * @param obj The <code>Object</code> to be printed 381 * @see java.lang.Object#toString() 382 */ 383 public void print(Object obj) { 384 this.write(String.valueOf(obj)); 385 } 386 387 388 /* Methods that do terminate lines */ 389 390 /* ------------------------------------------------------------ */ 391 /** 392 * Terminate the current line by writing the line separator string. The 393 * line separator string is defined by the system property 394 * <code>line.separator</code>, and is not necessarily a single newline 395 * character (<code>'\n'</code>). 396 */ 397 public void println() { 398 this.newLine(); 399 } 400 401 /* ------------------------------------------------------------ */ 402 /** 403 * Print a boolean value and then terminate the line. This method behaves 404 * as though it invokes <code>{@link #print(boolean)}</code> and then 405 * <code>{@link #println()}</code>. 406 * 407 * @param x the <code>boolean</code> value to be printed 408 */ 409 public void println(boolean x) { 410 synchronized (lock) { 411 this.print(x); 412 this.println(); 413 } 414 } 415 416 /* ------------------------------------------------------------ */ 417 /** 418 * Print a character and then terminate the line. This method behaves as 419 * though it invokes <code>{@link #print(char)}</code> and then <code>{@link 420 * #println()}</code>. 421 * 422 * @param x the <code>char</code> value to be printed 423 */ 424 public void println(char x) { 425 synchronized (lock) { 426 this.print(x); 427 this.println(); 428 } 429 } 430 431 /* ------------------------------------------------------------ */ 432 /** 433 * Print an integer and then terminate the line. This method behaves as 434 * though it invokes <code>{@link #print(int)}</code> and then <code>{@link 435 * #println()}</code>. 436 * 437 * @param x the <code>int</code> value to be printed 438 */ 439 public void println(int x) { 440 synchronized (lock) { 441 this.print(x); 442 this.println(); 443 } 444 } 445 446 /* ------------------------------------------------------------ */ 447 /** 448 * Print a long integer and then terminate the line. This method behaves 449 * as though it invokes <code>{@link #print(long)}</code> and then 450 * <code>{@link #println()}</code>. 451 * 452 * @param x the <code>long</code> value to be printed 453 */ 454 public void println(long x) { 455 synchronized (lock) { 456 this.print(x); 457 this.println(); 458 } 459 } 460 461 /* ------------------------------------------------------------ */ 462 /** 463 * Print a floating-point number and then terminate the line. This method 464 * behaves as though it invokes <code>{@link #print(float)}</code> and then 465 * <code>{@link #println()}</code>. 466 * 467 * @param x the <code>float</code> value to be printed 468 */ 469 public void println(float x) { 470 synchronized (lock) { 471 this.print(x); 472 this.println(); 473 } 474 } 475 476 /* ------------------------------------------------------------ */ 477 /** 478 * Print a double-precision floating-point number and then terminate the 479 * line. This method behaves as though it invokes <code>{@link 480 * #print(double)}</code> and then <code>{@link #println()}</code>. 481 * 482 * @param x the <code>double</code> value to be printed 483 */ 484 /* ------------------------------------------------------------ */ 485 public void println(double x) { 486 synchronized (lock) { 487 this.print(x); 488 this.println(); 489 } 490 } 491 492 /* ------------------------------------------------------------ */ 493 /** 494 * Print an array of characters and then terminate the line. This method 495 * behaves as though it invokes <code>{@link #print(char[])}</code> and then 496 * <code>{@link #println()}</code>. 497 * 498 * @param x the array of <code>char</code> values to be printed 499 */ 500 public void println(char x[]) { 501 synchronized (lock) { 502 this.print(x); 503 this.println(); 504 } 505 } 506 507 /* ------------------------------------------------------------ */ 508 /** 509 * Print a String and then terminate the line. This method behaves as 510 * though it invokes <code>{@link #print(String)}</code> and then 511 * <code>{@link #println()}</code>. 512 * 513 * @param x the <code>String</code> value to be printed 514 */ 515 public void println(String x) { 516 synchronized (lock) { 517 this.print(x); 518 this.println(); 519 } 520 } 521 522 /* ------------------------------------------------------------ */ 523 /** 524 * Print an Object and then terminate the line. This method behaves as 525 * though it invokes <code>{@link #print(Object)}</code> and then 526 * <code>{@link #println()}</code>. 527 * 528 * @param x the <code>Object</code> value to be printed 529 */ 530 public void println(Object x) { 531 synchronized (lock) { 532 this.print(x); 533 this.println(); 534 } 535 } 536 }