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