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