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