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 RuntimeIOException} 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 }