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 */ 40 public static Console getConsole() { 41 return console; 42 } 43 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 56 private Console(InputStream in, OutputStream out) throws IOException { 57 this.reader = new ConsoleReader(in); 58 this.writer = new ConsoleWriter(out); 59 } 60 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 } 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 */ 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 */ 179 public PrintWriter writer() { 180 return writer; 181 } 182 183 private static class ConsoleReader extends BufferedReader { 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 190 public void close() { 191 // Console.reader cannot be closed. 192 } 193 } 194 195 private static class ConsoleWriter extends PrintWriter { 196 public ConsoleWriter(OutputStream out) { 197 super(out, true); 198 lock = CONSOLE_LOCK; 199 } 200 201 @Override 202 public void close() { 203 // Console.writer cannot be closed. 204 flush(); 205 } 206 } 207 } 208