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