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 package org.eclipse.jetty.io; 15 16 import java.io.BufferedWriter; 17 import java.io.IOException; 18 import java.io.InterruptedIOException; 19 import java.io.OutputStream; 20 import java.io.OutputStreamWriter; 21 import java.io.PrintWriter; 22 import java.io.Writer; 23 24 import org.eclipse.jetty.util.log.Log; 25 import org.eclipse.jetty.util.log.Logger; 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 RuntimeIOException} instances. 32 */ 33 public class UncheckedPrintWriter extends PrintWriter 34 { 35 private static final Logger LOG = Log.getLogger(UncheckedPrintWriter.class); 36 37 private boolean _autoFlush = false; 38 private boolean _throwUnchecked=true; 39 40 /* ------------------------------------------------------------ */ 41 /** 42 * Line separator string. This is the value of the line.separator property 43 * at the moment that the stream was created. 44 */ 45 private String _lineSeparator; 46 47 public UncheckedPrintWriter(Writer out) 48 { 49 this(out,false); 50 } 51 52 /* ------------------------------------------------------------ */ 53 /** 54 * Create a new PrintWriter. 55 * 56 * @param out 57 * A character-output stream 58 * @param autoFlush 59 * A boolean; if true, the println() methods will flush the 60 * output buffer 61 */ 62 public UncheckedPrintWriter(Writer out, boolean autoFlush) 63 { 64 super(out,autoFlush); 65 this._autoFlush = autoFlush; 66 this._lineSeparator = System.getProperty("line.separator"); 67 } 68 69 /* ------------------------------------------------------------ */ 70 /** 71 * Create a new PrintWriter, without automatic line flushing, from an 72 * existing OutputStream. This convenience constructor creates the necessary 73 * intermediate OutputStreamWriter, which will convert characters into bytes 74 * using the default character encoding. 75 * 76 * @param out 77 * An output stream 78 * 79 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 80 */ 81 public UncheckedPrintWriter(OutputStream out) 82 { 83 this(out,false); 84 } 85 86 /* ------------------------------------------------------------ */ 87 /** 88 * Create a new PrintWriter from an existing OutputStream. This convenience 89 * constructor creates the necessary intermediate OutputStreamWriter, which 90 * will convert characters into bytes using the default character encoding. 91 * 92 * @param out 93 * An output stream 94 * @param autoFlush 95 * A boolean; if true, the println() methods will flush the 96 * output buffer 97 * 98 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 99 */ 100 public UncheckedPrintWriter(OutputStream out, boolean autoFlush) 101 { 102 this(new BufferedWriter(new OutputStreamWriter(out)),autoFlush); 103 } 104 105 /* ------------------------------------------------------------ */ 106 private void setError(Throwable th) 107 { 108 setError(); 109 if (_throwUnchecked) 110 throw new UncheckedIOException(th); 111 LOG.debug(th); 112 } 113 114 /* ------------------------------------------------------------ */ 115 /** Are unchecked exceptions thrown. 116 * @return True if {@link RuntimeIOException}s are thrown 117 */ 118 public boolean isUncheckedPrintWriter() 119 { 120 return _throwUnchecked; 121 } 122 123 /* ------------------------------------------------------------ */ 124 /** Set if unchecked exceptions are thrown 125 * @param uncheckedPrintWriter True if {@link RuntimeIOException}s are to be thrown 126 */ 127 public void setUncheckedPrintWriter(boolean uncheckedPrintWriter) 128 { 129 _throwUnchecked = uncheckedPrintWriter; 130 } 131 132 /* ------------------------------------------------------------ */ 133 /** Check to make sure that the stream has not been closed */ 134 private void isOpen() throws IOException 135 { 136 if (super.out == null) 137 throw new IOException("Stream closed"); 138 } 139 140 /* ------------------------------------------------------------ */ 141 /** 142 * Flush the stream. 143 */ 144 @Override 145 public void flush() 146 { 147 try 148 { 149 synchronized (lock) 150 { 151 isOpen(); 152 out.flush(); 153 } 154 } 155 catch (IOException ex) 156 { 157 setError(ex); 158 } 159 } 160 161 /* ------------------------------------------------------------ */ 162 /** 163 * Close the stream. 164 */ 165 @Override 166 public void close() 167 { 168 try 169 { 170 synchronized (lock) 171 { 172 out.close(); 173 } 174 } 175 catch (IOException ex) 176 { 177 setError(ex); 178 } 179 } 180 181 /* ------------------------------------------------------------ */ 182 /** 183 * Write a single character. 184 * 185 * @param c 186 * int specifying a character to be written. 187 */ 188 @Override 189 public void write(int c) 190 { 191 try 192 { 193 synchronized (lock) 194 { 195 isOpen(); 196 out.write(c); 197 } 198 } 199 catch (InterruptedIOException x) 200 { 201 Thread.currentThread().interrupt(); 202 } 203 catch (IOException ex) 204 { 205 setError(ex); 206 } 207 } 208 209 /* ------------------------------------------------------------ */ 210 /** 211 * Write a portion of an array of characters. 212 * 213 * @param buf 214 * Array of characters 215 * @param off 216 * Offset from which to start writing characters 217 * @param len 218 * Number of characters to write 219 */ 220 @Override 221 public void write(char buf[], int off, int len) 222 { 223 try 224 { 225 synchronized (lock) 226 { 227 isOpen(); 228 out.write(buf,off,len); 229 } 230 } 231 catch (InterruptedIOException x) 232 { 233 Thread.currentThread().interrupt(); 234 } 235 catch (IOException ex) 236 { 237 setError(ex); 238 } 239 } 240 241 /* ------------------------------------------------------------ */ 242 /** 243 * Write an array of characters. This method cannot be inherited from the 244 * Writer class because it must suppress I/O exceptions. 245 * 246 * @param buf 247 * Array of characters to be written 248 */ 249 @Override 250 public void write(char buf[]) 251 { 252 this.write(buf,0,buf.length); 253 } 254 255 /* ------------------------------------------------------------ */ 256 /** 257 * Write a portion of a string. 258 * 259 * @param s 260 * A String 261 * @param off 262 * Offset from which to start writing characters 263 * @param len 264 * Number of characters to write 265 */ 266 @Override 267 public void write(String s, int off, int len) 268 { 269 try 270 { 271 synchronized (lock) 272 { 273 isOpen(); 274 out.write(s,off,len); 275 } 276 } 277 catch (InterruptedIOException x) 278 { 279 Thread.currentThread().interrupt(); 280 } 281 catch (IOException ex) 282 { 283 setError(ex); 284 } 285 } 286 287 /* ------------------------------------------------------------ */ 288 /** 289 * Write a string. This method cannot be inherited from the Writer class 290 * because it must suppress I/O exceptions. 291 * 292 * @param s 293 * String to be written 294 */ 295 @Override 296 public void write(String s) 297 { 298 this.write(s,0,s.length()); 299 } 300 301 private void newLine() 302 { 303 try 304 { 305 synchronized (lock) 306 { 307 isOpen(); 308 out.write(_lineSeparator); 309 if (_autoFlush) 310 out.flush(); 311 } 312 } 313 catch (InterruptedIOException x) 314 { 315 Thread.currentThread().interrupt(); 316 } 317 catch (IOException ex) 318 { 319 setError(ex); 320 } 321 } 322 323 /* ------------------------------------------------------------ */ 324 /** 325 * Print a boolean value. The string produced by <code>{@link 326 * java.lang.String#valueOf(boolean)}</code> is translated into bytes 327 * according to the platform's default character encoding, and these bytes 328 * are written in exactly the manner of the <code>{@link 329 * #write(int)}</code> method. 330 * 331 * @param b 332 * The <code>boolean</code> to be printed 333 */ 334 @Override 335 public void print(boolean b) 336 { 337 this.write(b?"true":"false"); 338 } 339 340 /* ------------------------------------------------------------ */ 341 /** 342 * Print a character. The character is translated into one or more bytes 343 * according to the platform's default character encoding, and these bytes 344 * are written in exactly the manner of the <code>{@link 345 * #write(int)}</code> method. 346 * 347 * @param c 348 * The <code>char</code> to be printed 349 */ 350 @Override 351 public void print(char c) 352 { 353 this.write(c); 354 } 355 356 /* ------------------------------------------------------------ */ 357 /** 358 * Print an integer. The string produced by <code>{@link 359 * java.lang.String#valueOf(int)}</code> is translated into bytes according 360 * to the platform's default character encoding, and these bytes are written 361 * in exactly the manner of the <code>{@link #write(int)}</code> method. 362 * 363 * @param i 364 * The <code>int</code> to be printed 365 * @see java.lang.Integer#toString(int) 366 */ 367 @Override 368 public void print(int i) 369 { 370 this.write(String.valueOf(i)); 371 } 372 373 /* ------------------------------------------------------------ */ 374 /** 375 * Print a long integer. The string produced by <code>{@link 376 * java.lang.String#valueOf(long)}</code> is translated into bytes according 377 * to the platform's default character encoding, and these bytes are written 378 * in exactly the manner of the <code>{@link #write(int)}</code> method. 379 * 380 * @param l 381 * The <code>long</code> to be printed 382 * @see java.lang.Long#toString(long) 383 */ 384 @Override 385 public void print(long l) 386 { 387 this.write(String.valueOf(l)); 388 } 389 390 /* ------------------------------------------------------------ */ 391 /** 392 * Print a floating-point number. The string produced by <code>{@link 393 * java.lang.String#valueOf(float)}</code> is translated into bytes 394 * according to the platform's default character encoding, and these bytes 395 * are written in exactly the manner of the <code>{@link #write(int)}</code> 396 * method. 397 * 398 * @param f 399 * The <code>float</code> to be printed 400 * @see java.lang.Float#toString(float) 401 */ 402 @Override 403 public void print(float f) 404 { 405 this.write(String.valueOf(f)); 406 } 407 408 /* ------------------------------------------------------------ */ 409 /** 410 * Print a double-precision floating-point number. The string produced by 411 * <code>{@link java.lang.String#valueOf(double)}</code> is translated into 412 * bytes according to the platform's default character encoding, and these 413 * bytes are written in exactly the manner of the <code>{@link 414 * #write(int)}</code> method. 415 * 416 * @param d 417 * The <code>double</code> to be printed 418 * @see java.lang.Double#toString(double) 419 */ 420 @Override 421 public void print(double d) 422 { 423 this.write(String.valueOf(d)); 424 } 425 426 /* ------------------------------------------------------------ */ 427 /** 428 * Print an array of characters. The characters are converted into bytes 429 * according to the platform's default character encoding, and these bytes 430 * are written in exactly the manner of the <code>{@link #write(int)}</code> 431 * method. 432 * 433 * @param s 434 * The array of chars to be printed 435 * 436 * @throws NullPointerException 437 * If <code>s</code> is <code>null</code> 438 */ 439 @Override 440 public void print(char s[]) 441 { 442 this.write(s); 443 } 444 445 /* ------------------------------------------------------------ */ 446 /** 447 * Print a string. If the argument is <code>null</code> then the string 448 * <code>"null"</code> is printed. Otherwise, the string's characters are 449 * converted into bytes according to the platform's default character 450 * encoding, and these bytes are written in exactly the manner of the 451 * <code>{@link #write(int)}</code> method. 452 * 453 * @param s 454 * The <code>String</code> to be printed 455 */ 456 @Override 457 public void print(String s) 458 { 459 if (s == null) 460 { 461 s = "null"; 462 } 463 this.write(s); 464 } 465 466 /* ------------------------------------------------------------ */ 467 /** 468 * Print an object. The string produced by the <code>{@link 469 * java.lang.String#valueOf(Object)}</code> method is translated into bytes 470 * according to the platform's default character encoding, and these bytes 471 * are written in exactly the manner of the <code>{@link #write(int)}</code> 472 * method. 473 * 474 * @param obj 475 * The <code>Object</code> to be printed 476 * @see java.lang.Object#toString() 477 */ 478 @Override 479 public void print(Object obj) 480 { 481 this.write(String.valueOf(obj)); 482 } 483 484 /* ------------------------------------------------------------ */ 485 /** 486 * Terminate the current line by writing the line separator string. The line 487 * separator string is defined by the system property 488 * <code>line.separator</code>, and is not necessarily a single newline 489 * character (<code>'\n'</code>). 490 */ 491 @Override 492 public void println() 493 { 494 this.newLine(); 495 } 496 497 /* ------------------------------------------------------------ */ 498 /** 499 * Print a boolean value and then terminate the line. This method behaves as 500 * though it invokes <code>{@link #print(boolean)}</code> and then 501 * <code>{@link #println()}</code>. 502 * 503 * @param x 504 * the <code>boolean</code> value to be printed 505 */ 506 @Override 507 public void println(boolean x) 508 { 509 synchronized (lock) 510 { 511 this.print(x); 512 this.println(); 513 } 514 } 515 516 /* ------------------------------------------------------------ */ 517 /** 518 * Print a character and then terminate the line. This method behaves as 519 * though it invokes <code>{@link #print(char)}</code> and then <code>{@link 520 * #println()}</code>. 521 * 522 * @param x 523 * the <code>char</code> value to be printed 524 */ 525 @Override 526 public void println(char x) 527 { 528 synchronized (lock) 529 { 530 this.print(x); 531 this.println(); 532 } 533 } 534 535 /* ------------------------------------------------------------ */ 536 /** 537 * Print an integer and then terminate the line. This method behaves as 538 * though it invokes <code>{@link #print(int)}</code> and then <code>{@link 539 * #println()}</code>. 540 * 541 * @param x 542 * the <code>int</code> value to be printed 543 */ 544 @Override 545 public void println(int x) 546 { 547 synchronized (lock) 548 { 549 this.print(x); 550 this.println(); 551 } 552 } 553 554 /* ------------------------------------------------------------ */ 555 /** 556 * Print a long integer and then terminate the line. This method behaves as 557 * though it invokes <code>{@link #print(long)}</code> and then 558 * <code>{@link #println()}</code>. 559 * 560 * @param x 561 * the <code>long</code> value to be printed 562 */ 563 @Override 564 public void println(long x) 565 { 566 synchronized (lock) 567 { 568 this.print(x); 569 this.println(); 570 } 571 } 572 573 /* ------------------------------------------------------------ */ 574 /** 575 * Print a floating-point number and then terminate the line. This method 576 * behaves as though it invokes <code>{@link #print(float)}</code> and then 577 * <code>{@link #println()}</code>. 578 * 579 * @param x 580 * the <code>float</code> value to be printed 581 */ 582 @Override 583 public void println(float x) 584 { 585 synchronized (lock) 586 { 587 this.print(x); 588 this.println(); 589 } 590 } 591 592 /* ------------------------------------------------------------ */ 593 /** 594 * Print a double-precision floating-point number and then terminate the 595 * line. This method behaves as though it invokes <code>{@link 596 * #print(double)}</code> and then <code>{@link #println()}</code>. 597 * 598 * @param x 599 * the <code>double</code> value to be printed 600 */ 601 /* ------------------------------------------------------------ */ 602 @Override 603 public void println(double x) 604 { 605 synchronized (lock) 606 { 607 this.print(x); 608 this.println(); 609 } 610 } 611 612 /* ------------------------------------------------------------ */ 613 /** 614 * Print an array of characters and then terminate the line. This method 615 * behaves as though it invokes <code>{@link #print(char[])}</code> and then 616 * <code>{@link #println()}</code>. 617 * 618 * @param x 619 * the array of <code>char</code> values to be printed 620 */ 621 @Override 622 public void println(char x[]) 623 { 624 synchronized (lock) 625 { 626 this.print(x); 627 this.println(); 628 } 629 } 630 631 /* ------------------------------------------------------------ */ 632 /** 633 * Print a String and then terminate the line. This method behaves as though 634 * it invokes <code>{@link #print(String)}</code> and then 635 * <code>{@link #println()}</code>. 636 * 637 * @param x 638 * the <code>String</code> value to be printed 639 */ 640 @Override 641 public void println(String x) 642 { 643 synchronized (lock) 644 { 645 this.print(x); 646 this.println(); 647 } 648 } 649 650 /* ------------------------------------------------------------ */ 651 /** 652 * Print an Object and then terminate the line. This method behaves as 653 * though it invokes <code>{@link #print(Object)}</code> and then 654 * <code>{@link #println()}</code>. 655 * 656 * @param x 657 * the <code>Object</code> value to be printed 658 */ 659 @Override 660 public void println(Object x) 661 { 662 synchronized (lock) 663 { 664 this.print(x); 665 this.println(); 666 } 667 } 668 }