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