KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > io > Console


1 /*
2  * @(#)Console.java 1.11 06/06/12
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.io;
9
10 import java.util.*;
11 import java.nio.charset.Charset JavaDoc;
12 import sun.nio.cs.StreamDecoder;
13 import sun.nio.cs.StreamEncoder;
14
15 /**
16  * Methods to access the character-based console device, if any, associated
17  * with the current Java virtual machine.
18  *
19  * <p> Whether a virtual machine has a console is dependent upon the
20  * underlying platform and also upon the manner in which the virtual
21  * machine is invoked. If the virtual machine is started from an
22  * interactive command line without redirecting the standard input and
23  * output streams then its console will exist and will typically be
24  * connected to the keyboard and display from which the virtual machine
25  * was launched. If the virtual machine is started automatically, for
26  * example by a background job scheduler, then it will typically not
27  * have a console.
28  * <p>
29  * If this virtual machine has a console then it is represented by a
30  * unique instance of this class which can be obtained by invoking the
31  * {@link java.lang.System#console()} method. If no console device is
32  * available then an invocation of that method will return <tt>null</tt>.
33  * <p>
34  * Read and write operations are synchronized to guarantee the atomic
35  * completion of critical operations; therefore invoking methods
36  * {@link #readLine()}, {@link #readPassword()}, {@link #format format()},
37  * {@link #printf printf()} as well as the read, format and write operations
38  * on the objects returned by {@link #reader()} and {@link #writer()} may
39  * block in multithreaded scenarios.
40  * <p>
41  * Invoking <tt>close()</tt> on the objects returned by the {@link #reader()}
42  * and the {@link #writer()} will not close the underlying stream of those
43  * objects.
44  * <p>
45  * The console-read methods return <tt>null</tt> when the end of the
46  * console input stream is reached, for example by typing control-D on
47  * Unix or control-Z on Windows. Subsequent read operations will succeed
48  * if additional characters are later entered on the console's input
49  * device.
50  * <p>
51  * Unless otherwise specified, passing a <tt>null</tt> argument to any method
52  * in this class will cause a {@link NullPointerException} to be thrown.
53  * <p>
54  * <b>Security note:</b>
55  * If an application needs to read a password or other secure data, it should
56  * use {@link #readPassword()} or {@link #readPassword(String, Object...)} and
57  * manually zero the returned character array after processing to minimize the
58  * lifetime of sensitive data in memory.
59  *
60  * <blockquote><pre>
61  * Console cons;
62  * char[] passwd;
63  * if ((cons = System.console()) != null &&
64  * (passwd = cons.readPassword("[%s]", "Password:")) != null) {
65  * ...
66  * java.util.Arrays.fill(passwd, ' ');
67  * }
68  * </pre></blockquote>
69  *
70  * @author Xueming Shen
71  * @version 1.11, 06/12/06
72  * @since 1.6
73  */

74
75 public final class Console implements Flushable JavaDoc
76 {
77    /**
78     * Retrieves the unique {@link java.io.PrintWriter PrintWriter} object
79     * associated with this console.
80     *
81     * @return The printwriter associated with this console
82     */

83     public PrintWriter JavaDoc writer() {
84         return pw;
85     }
86
87    /**
88     * Retrieves the unique {@link java.io.Reader Reader} object associated
89     * with this console.
90     * <p>
91     * This method is intended to be used by sophisticated applications, for
92     * example, a {@link java.util.Scanner} object which utilizes the rich
93     * parsing/scanning functionality provided by the <tt>Scanner</tt>:
94     * <blockquote><pre>
95     * Console con = System.console();
96     * if (con != null) {
97     * Scanner sc = new Scanner(con.reader());
98     * ...
99     * }
100     * </pre></blockquote>
101     * <p>
102     * For simple applications requiring only line-oriented reading, use
103     * <tt>{@link #readLine}</tt>.
104     * <p>
105     * The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) },
106     * {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and
107     * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)}
108     * on the returned object will not read in characters beyond the line
109     * bound for each invocation, even if the destination buffer has space for
110     * more characters. A line bound is considered to be any one of a line feed
111     * (<tt>'\n'</tt>), a carriage return (<tt>'\r'</tt>), a carriage return
112     * followed immediately by a linefeed, or an end of stream.
113     *
114     * @return The reader associated with this console
115     */

116     public Reader JavaDoc reader() {
117         return reader;
118     }
119
120    /**
121     * Writes a formatted string to this console's output stream using
122     * the specified format string and arguments.
123     *
124     * @param fmt
125     * A format string as described in <a
126     * HREF="../util/Formatter.html#syntax">Format string syntax</a>
127     *
128     * @param args
129     * Arguments referenced by the format specifiers in the format
130     * string. If there are more arguments than format specifiers, the
131     * extra arguments are ignored. The number of arguments is
132     * variable and may be zero. The maximum number of arguments is
133     * limited by the maximum dimension of a Java array as defined by
134     * the <a HREF="http://java.sun.com/docs/books/vmspec/">Java
135     * Virtual Machine Specification</a>. The behaviour on a
136     * <tt>null</tt> argument depends on the <a
137     * HREF="../util/Formatter.html#syntax">conversion</a>.
138     *
139     * @throws IllegalFormatException
140     * If a format string contains an illegal syntax, a format
141     * specifier that is incompatible with the given arguments,
142     * insufficient arguments given the format string, or other
143     * illegal conditions. For specification of all possible
144     * formatting errors, see the <a
145     * HREF="../util/Formatter.html#detail">Details</a> section
146     * of the formatter class specification.
147     *
148     * @return This console
149     */

150     public Console JavaDoc format(String JavaDoc fmt, Object JavaDoc ...args) {
151         formatter.format(fmt, args).flush();
152         return this;
153     }
154
155    /**
156     * A convenience method to write a formatted string to this console's
157     * output stream using the specified format string and arguments.
158     *
159     * <p> An invocation of this method of the form <tt>con.printf(format,
160     * args)</tt> behaves in exactly the same way as the invocation of
161     * <pre>con.format(format, args)</pre>.
162     *
163     * @param format
164     * A format string as described in <a
165     * HREF="../util/Formatter.html#syntax">Format string syntax</a>.
166     *
167     * @param args
168     * Arguments referenced by the format specifiers in the format
169     * string. If there are more arguments than format specifiers, the
170     * extra arguments are ignored. The number of arguments is
171     * variable and may be zero. The maximum number of arguments is
172     * limited by the maximum dimension of a Java array as defined by
173     * the <a HREF="http://java.sun.com/docs/books/vmspec/">Java
174     * Virtual Machine Specification</a>. The behaviour on a
175     * <tt>null</tt> argument depends on the <a
176     * HREF="../util/Formatter.html#syntax">conversion</a>.
177     *
178     * @throws IllegalFormatException
179     * If a format string contains an illegal syntax, a format
180     * specifier that is incompatible with the given arguments,
181     * insufficient arguments given the format string, or other
182     * illegal conditions. For specification of all possible
183     * formatting errors, see the <a
184     * HREF="../util/Formatter.html#detail">Details</a> section of the
185     * formatter class specification.
186     *
187     * @return This console
188     */

189     public Console JavaDoc printf(String JavaDoc format, Object JavaDoc ... args) {
190     return format(format, args);
191     }
192
193    /**
194     * Provides a formatted prompt, then reads a single line of text from the
195     * console.
196     *
197     * @param fmt
198     * A format string as described in <a
199     * HREF="../util/Formatter.html#syntax">Format string syntax</a>.
200     *
201     * @param args
202     * Arguments referenced by the format specifiers in the format
203     * string. If there are more arguments than format specifiers, the
204     * extra arguments are ignored. The maximum number of arguments is
205     * limited by the maximum dimension of a Java array as defined by
206     * the <a HREF="http://java.sun.com/docs/books/vmspec/">Java
207     * Virtual Machine Specification</a>.
208     *
209     * @throws IllegalFormatException
210     * If a format string contains an illegal syntax, a format
211     * specifier that is incompatible with the given arguments,
212     * insufficient arguments given the format string, or other
213     * illegal conditions. For specification of all possible
214     * formatting errors, see the <a
215     * HREF="../util/Formatter.html#detail">Details</a> section
216     * of the formatter class specification.
217     *
218     * @throws IOError
219     * If an I/O error occurs.
220     *
221     * @return A string containing the line read from the console, not
222     * including any line-termination characters, or <tt>null</tt>
223     * if an end of stream has been reached.
224     */

225     public String JavaDoc readLine(String JavaDoc fmt, Object JavaDoc ... args) {
226         String JavaDoc line = null;
227         synchronized (writeLock) {
228             synchronized(readLock) {
229                 if (fmt.length() != 0)
230                     pw.format(fmt, args);
231                 try {
232                     char[] ca = readline(false);
233                     if (ca != null)
234                         line = new String JavaDoc(ca);
235                 } catch (IOException JavaDoc x) {
236                     throw new IOError JavaDoc(x);
237                 }
238             }
239         }
240         return line;
241     }
242
243    /**
244     * Reads a single line of text from the console.
245     *
246     * @throws IOError
247     * If an I/O error occurs.
248     *
249     * @return A string containing the line read from the console, not
250     * including any line-termination characters, or <tt>null</tt>
251     * if an end of stream has been reached.
252     */

253     public String JavaDoc readLine() {
254         return readLine("");
255     }
256
257    /**
258     * Provides a formatted prompt, then reads a password or passphrase from
259     * the console with echoing disabled.
260     *
261     * @param fmt
262     * A format string as described in <a
263     * HREF="../util/Formatter.html#syntax">Format string syntax</a>
264     * for the prompt text.
265     *
266     * @param args
267     * Arguments referenced by the format specifiers in the format
268     * string. If there are more arguments than format specifiers, the
269     * extra arguments are ignored. The maximum number of arguments is
270     * limited by the maximum dimension of a Java array as defined by
271     * the <a HREF="http://java.sun.com/docs/books/vmspec/">Java
272     * Virtual Machine Specification</a>.
273     *
274     * @throws IllegalFormatException
275     * If a format string contains an illegal syntax, a format
276     * specifier that is incompatible with the given arguments,
277     * insufficient arguments given the format string, or other
278     * illegal conditions. For specification of all possible
279     * formatting errors, see the <a
280     * HREF="../util/Formatter.html#detail">Details</a>
281     * section of the formatter class specification.
282     *
283     * @throws IOError
284     * If an I/O error occurs.
285     *
286     * @return A character array containing the password or passphrase read
287     * from the console, not including any line-termination characters,
288     * or <tt>null</tt> if an end of stream has been reached.
289     */

290     public char[] readPassword(String JavaDoc fmt, Object JavaDoc ... args) {
291         char[] passwd = null;
292         synchronized (writeLock) {
293             synchronized(readLock) {
294                 if (fmt.length() != 0)
295                     pw.format(fmt, args);
296                 try {
297                     echoOff = echo(false);
298                     passwd = readline(true);
299                 } catch (IOException JavaDoc x) {
300                     throw new IOError JavaDoc(x);
301                 } finally {
302             try {
303                         echoOff = echo(true);
304                     } catch (IOException JavaDoc xx) {}
305                 }
306                 pw.println();
307         }
308     }
309         return passwd;
310     }
311
312    /**
313     * Reads a password or passphrase from the console with echoing disabled
314     *
315     * @throws IOError
316     * If an I/O error occurs.
317     *
318     * @return A character array containing the password or passphrase read
319     * from the console, not including any line-termination characters,
320     * or <tt>null</tt> if an end of stream has been reached.
321     */

322     public char[] readPassword() {
323         return readPassword("");
324     }
325
326     /**
327      * Flushes the console and forces any buffered output to be written
328      * immediately .
329      */

330     public void flush() {
331         pw.flush();
332     }
333
334     private Object JavaDoc readLock;
335     private Object JavaDoc writeLock;
336     private Reader JavaDoc reader;
337     private Writer JavaDoc out;
338     private PrintWriter JavaDoc pw;
339     private Formatter formatter;
340     private Charset JavaDoc cs;
341     private char[] rcb;
342     private static native String JavaDoc encoding();
343     private static native boolean echo(boolean on) throws IOException JavaDoc;
344     private static boolean echoOff;
345
346     private char[] readline(boolean zeroOut) throws IOException JavaDoc {
347         int len = reader.read(rcb, 0, rcb.length);
348         if (len < 0)
349             return null; //EOL
350
if (rcb[len-1] == '\r')
351             len--; //remove CR at end;
352
else if (rcb[len-1] == '\n') {
353             len--; //remove LF at end;
354
if (len > 0 && rcb[len-1] == '\r')
355                 len--; //remove the CR, if there is one
356
}
357     char[] b = new char[len];
358         if (len > 0) {
359         System.arraycopy(rcb, 0, b, 0, len);
360             if (zeroOut) {
361                 Arrays.fill(rcb, 0, len, ' ');
362             }
363     }
364     return b;
365     }
366
367     private char[] grow() {
368         assert Thread.holdsLock(readLock);
369         char[] t = new char[rcb.length * 2];
370         System.arraycopy(rcb, 0, t, 0, rcb.length);
371         rcb = t;
372         return rcb;
373     }
374
375     class LineReader extends Reader JavaDoc {
376         private Reader JavaDoc in;
377         private char[] cb;
378         private int nChars, nextChar;
379         boolean leftoverLF;
380         LineReader(Reader JavaDoc in) {
381             this.in = in;
382             cb = new char[1024];
383             nextChar = nChars = 0;
384             leftoverLF = false;
385         }
386         public void close () {}
387         public boolean ready() throws IOException JavaDoc {
388         //in.ready synchronizes on readLock already
389
return in.ready();
390         }
391
392         public int read(char cbuf[], int offset, int length)
393             throws IOException JavaDoc
394         {
395             int off = offset;
396             int end = offset + length;
397             if (offset < 0 || offset > cbuf.length || length < 0 ||
398                 end < 0 || end > cbuf.length) {
399                 throw new IndexOutOfBoundsException JavaDoc();
400             }
401         synchronized(readLock) {
402                 boolean eof = false;
403         char c = 0;
404         for (;;) {
405                     if (nextChar >= nChars) { //fill
406
int n = 0;
407                     do {
408                         n = in.read(cb, 0, cb.length);
409                     } while (n == 0);
410                     if (n > 0) {
411                             nChars = n;
412                             nextChar = 0;
413                             if (n < cb.length &&
414                 cb[n-1] != '\n' && cb[n-1] != '\r') {
415                     /*
416                      * we're in canonical mode so each "fill" should
417                      * come back with an eol. if there no lf or nl at
418                      * the end of returned bytes we reached an eof.
419                                  */

420                                 eof = true;
421                 }
422                     } else { /*EOF*/
423                             if (off - offset == 0)
424                                 return -1;
425                             return off - offset;
426                         }
427                     }
428                     if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') {
429                 /*
430              * if invoked by our readline, skip the leftover, otherwise
431                  * return the LF.
432                          */

433                         nextChar++;
434                     }
435                     leftoverLF = false;
436             while (nextChar < nChars) {
437                         c = cbuf[off++] = cb[nextChar];
438                         cb[nextChar++] = 0;
439             if (c == '\n') {
440                             return off - offset;
441                         } else if (c == '\r') {
442                             if (off == end) {
443                     /* no space left even the next is LF, so return
444                      * whatever we have if the invoker is not our
445                      * readLine()
446                                  */

447                     if (cbuf == rcb) {
448                                     cbuf = grow();
449                                     end = cbuf.length;
450                                 } else {
451                                     leftoverLF = true;
452                             return off - offset;
453                                 }
454                             }
455                 if (nextChar == nChars && in.ready()) {
456                     /*
457                                  * we have a CR and we reached the end of
458                                  * the read in buffer, fill to make sure we
459                                  * don't miss a LF, if there is one, it's possible
460                                  * that it got cut off during last round reading
461                                  * simply because the read in buffer was full.
462                                  */

463                             nChars = in.read(cb, 0, cb.length);
464                                 nextChar = 0;
465                 }
466                             if (nextChar < nChars && cb[nextChar] == '\n') {
467                                 cbuf[off++] = '\n';
468                                 nextChar++;
469                             }
470                 return off - offset;
471             } else if (off == end) {
472                if (cbuf == rcb) {
473                                 cbuf = grow();
474                                 end = cbuf.length;
475                } else {
476                                return off - offset;
477                            }
478             }
479             }
480                     if (eof)
481                         return off - offset;
482         }
483         }
484     }
485     }
486
487     // Set up JavaIOAccess in SharedSecrets
488
static {
489         sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {
490             public Console JavaDoc console() {
491                 if (istty()) {
492                     if (cons == null)
493                         cons = new Console JavaDoc();
494                     return cons;
495         }
496         return null;
497             }
498
499             // Add a shutdown hook to restore console's echo state should
500
// it be necessary.
501
public Runnable JavaDoc consoleRestoreHook() {
502                 return new Runnable JavaDoc() {
503                 public void run() {
504                     try {
505                     if (echoOff) {
506                                 echo(true);
507                 }
508             } catch (IOException JavaDoc x) {}
509             }
510                 };
511         }
512             
513             public Charset JavaDoc charset() {
514                 // This method is called in sun.security.util.Password,
515
// cons already exists when this method is called
516
return cons.cs;
517             }
518         });
519     }
520     private static Console JavaDoc cons;
521     private native static boolean istty();
522     private Console() {
523         readLock = new Object JavaDoc();
524         writeLock = new Object JavaDoc();
525         String JavaDoc csname = encoding();
526         if (csname != null) {
527             try {
528                 cs = Charset.forName(csname);
529             } catch (Exception JavaDoc x) {}
530         }
531         if (cs == null)
532             cs = Charset.defaultCharset();
533         out = StreamEncoder.forOutputStreamWriter(
534                   new FileOutputStream JavaDoc(FileDescriptor.out),
535           writeLock,
536           cs);
537         pw = new PrintWriter JavaDoc(out, true) { public void close() {} };
538         formatter = new Formatter(out);
539         reader = new LineReader(StreamDecoder.forInputStreamReader(
540              new FileInputStream JavaDoc(FileDescriptor.in),
541              readLock,
542              cs));
543     rcb = new char[1024];
544     }
545 }
546
547
Popular Tags