• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package java.io;
17 
18 import java.util.Formatter;
19 import libcore.io.ErrnoException;
20 import libcore.io.Libcore;
21 import static libcore.io.OsConstants.*;
22 
23 /**
24  * Provides access to the console, if available. The system-wide instance can
25  * be accessed via {@link java.lang.System#console}.
26  * @since 1.6
27  */
28 public final class Console implements Flushable {
29     private static final Object CONSOLE_LOCK = new Object();
30 
31     private static final Console console = makeConsole();
32 
33     private final ConsoleReader reader;
34     private final PrintWriter writer;
35 
36     /**
37      * Secret accessor for {@code System.console}.
38      * @hide
39      */
getConsole()40     public static Console getConsole() {
41         return console;
42     }
43 
makeConsole()44     private static Console makeConsole() {
45         // We don't care about stderr, because this class only uses stdin and stdout.
46         if (!Libcore.os.isatty(FileDescriptor.in) || !Libcore.os.isatty(FileDescriptor.out)) {
47             return null;
48         }
49         try {
50             return new Console(System.in, System.out);
51         } catch (IOException ex) {
52             throw new AssertionError(ex);
53         }
54     }
55 
Console(InputStream in, OutputStream out)56     private Console(InputStream in, OutputStream out) throws IOException {
57         this.reader = new ConsoleReader(in);
58         this.writer = new ConsoleWriter(out);
59     }
60 
flush()61     public void flush() {
62         writer.flush();
63     }
64 
65     /**
66      * Writes a formatted string to the console using
67      * the specified format string and arguments.
68      *
69      * @param format the format string (see {@link java.util.Formatter#format})
70      * @param args
71      *            the list of arguments passed to the formatter. If there are
72      *            more arguments than required by {@code format},
73      *            additional arguments are ignored.
74      * @return the console instance.
75      */
format(String format, Object... args)76     public Console format(String format, Object... args) {
77         Formatter f = new Formatter(writer);
78         f.format(format, args);
79         f.flush();
80         return this;
81     }
82 
83     /**
84      * Equivalent to {@code format(format, args)}.
85      */
printf(String format, Object... args)86     public Console printf(String format, Object... args) {
87         return format(format, args);
88     }
89 
90     /**
91      * Returns the {@link Reader} associated with this console.
92      */
reader()93     public Reader reader() {
94         return reader;
95     }
96 
97     /**
98      * Reads a line from the console.
99      *
100      * @return the line, or null at EOF.
101      */
readLine()102     public String readLine() {
103         try {
104             return reader.readLine();
105         } catch (IOException e) {
106             throw new IOError(e);
107         }
108     }
109 
110     /**
111      * Reads a line from this console, using the specified prompt.
112      * The prompt is given as a format string and optional arguments.
113      * Note that this can be a source of errors: if it is possible that your
114      * prompt contains {@code %} characters, you must use the format string {@code "%s"}
115      * and pass the actual prompt as a parameter.
116      *
117      * @param format the format string (see {@link java.util.Formatter#format})
118      * @param args
119      *            the list of arguments passed to the formatter. If there are
120      *            more arguments than required by {@code format},
121      *            additional arguments are ignored.
122      * @return the line, or null at EOF.
123      */
readLine(String format, Object... args)124     public String readLine(String format, Object... args) {
125         synchronized (CONSOLE_LOCK) {
126             format(format, args);
127             return readLine();
128         }
129     }
130 
131     /**
132      * Reads a password from the console. The password will not be echoed to the display.
133      *
134      * @return a character array containing the password, or null at EOF.
135      */
readPassword()136     public char[] readPassword() {
137         synchronized (CONSOLE_LOCK) {
138             int previousState = setEcho(false, 0);
139             try {
140                 String password = readLine();
141                 writer.println(); // We won't have echoed the user's newline.
142                 return (password == null) ? null : password.toCharArray();
143             } finally {
144                 setEcho(true, previousState);
145             }
146         }
147     }
148 
setEcho(boolean on, int previousState)149     private static int setEcho(boolean on, int previousState) {
150         try {
151             return setEchoImpl(on, previousState);
152         } catch (IOException ex) {
153             throw new IOError(ex);
154         }
155     }
setEchoImpl(boolean on, int previousState)156     private static native int setEchoImpl(boolean on, int previousState) throws IOException;
157 
158     /**
159      * Reads a password from the console. The password will not be echoed to the display.
160      * A formatted prompt is also displayed.
161      *
162      * @param format the format string (see {@link java.util.Formatter#format})
163      * @param args
164      *            the list of arguments passed to the formatter. If there are
165      *            more arguments than required by {@code format},
166      *            additional arguments are ignored.
167      * @return a character array containing the password, or null at EOF.
168      */
readPassword(String format, Object... args)169     public char[] readPassword(String format, Object... args) {
170         synchronized (CONSOLE_LOCK) {
171             format(format, args);
172             return readPassword();
173         }
174     }
175 
176     /**
177      * Returns the {@link Writer} associated with this console.
178      */
writer()179     public PrintWriter writer() {
180         return writer;
181     }
182 
183     private static class ConsoleReader extends BufferedReader {
ConsoleReader(InputStream in)184         public ConsoleReader(InputStream in) throws IOException {
185             super(new InputStreamReader(in, System.getProperty("file.encoding")), 256);
186             lock = CONSOLE_LOCK;
187         }
188 
189         @Override
close()190         public void close() {
191             // Console.reader cannot be closed.
192         }
193     }
194 
195     private static class ConsoleWriter extends PrintWriter {
ConsoleWriter(OutputStream out)196         public ConsoleWriter(OutputStream out) {
197             super(out, true);
198             lock = CONSOLE_LOCK;
199         }
200 
201         @Override
close()202         public void close() {
203             // Console.writer cannot be closed.
204             flush();
205         }
206     }
207 }
208