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.Libcore; 20 21 /** 22 * Provides access to the console, if available. The system-wide instance can 23 * be accessed via {@link java.lang.System#console}. 24 * @since 1.6 25 */ 26 public final class Console implements Flushable { 27 private static final Object CONSOLE_LOCK = new Object(); 28 29 private static final Console console = makeConsole(); 30 31 private final ConsoleReader reader; 32 private final PrintWriter writer; 33 34 /** 35 * Secret accessor for {@code System.console}. 36 * @hide 37 */ getConsole()38 public static Console getConsole() { 39 return console; 40 } 41 makeConsole()42 private static Console makeConsole() { 43 // We don't care about stderr, because this class only uses stdin and stdout. 44 if (!Libcore.os.isatty(FileDescriptor.in) || !Libcore.os.isatty(FileDescriptor.out)) { 45 return null; 46 } 47 try { 48 return new Console(System.in, System.out); 49 } catch (UnsupportedEncodingException ex) { 50 throw new AssertionError(ex); 51 } 52 } 53 Console(InputStream in, OutputStream out)54 private Console(InputStream in, OutputStream out) throws UnsupportedEncodingException { 55 this.reader = new ConsoleReader(in); 56 this.writer = new ConsoleWriter(out); 57 } 58 flush()59 public void flush() { 60 writer.flush(); 61 } 62 63 /** 64 * Writes a formatted string to the console using 65 * the specified format string and arguments. 66 * 67 * @param format the format string (see {@link java.util.Formatter#format}) 68 * @param args 69 * the list of arguments passed to the formatter. If there are 70 * more arguments than required by {@code format}, 71 * additional arguments are ignored. 72 * @return the console instance. 73 */ format(String format, Object... args)74 public Console format(String format, Object... args) { 75 Formatter f = new Formatter(writer); 76 f.format(format, args); 77 f.flush(); 78 return this; 79 } 80 81 /** 82 * Equivalent to {@code format(format, args)}. 83 */ printf(String format, Object... args)84 public Console printf(String format, Object... args) { 85 return format(format, args); 86 } 87 88 /** 89 * Returns the {@link Reader} associated with this console. 90 */ reader()91 public Reader reader() { 92 return reader; 93 } 94 95 /** 96 * Reads a line from the console. 97 * 98 * @return the line, or null at EOF. 99 */ readLine()100 public String readLine() { 101 try { 102 return reader.readLine(); 103 } catch (IOException e) { 104 throw new IOError(e); 105 } 106 } 107 108 /** 109 * Reads a line from this console, using the specified prompt. 110 * The prompt is given as a format string and optional arguments. 111 * Note that this can be a source of errors: if it is possible that your 112 * prompt contains {@code %} characters, you must use the format string {@code "%s"} 113 * and pass the actual prompt as a parameter. 114 * 115 * @param format the format string (see {@link java.util.Formatter#format}) 116 * @param args 117 * the list of arguments passed to the formatter. If there are 118 * more arguments than required by {@code format}, 119 * additional arguments are ignored. 120 * @return the line, or null at EOF. 121 */ readLine(String format, Object... args)122 public String readLine(String format, Object... args) { 123 synchronized (CONSOLE_LOCK) { 124 format(format, args); 125 return readLine(); 126 } 127 } 128 129 /** 130 * This method is unimplemented on Android. 131 */ readPassword()132 public char[] readPassword() { 133 throw new UnsupportedOperationException(); 134 } 135 136 /** 137 * This method is unimplemented on Android. 138 */ readPassword(String format, Object... args)139 public char[] readPassword(String format, Object... args) { 140 throw new UnsupportedOperationException(); 141 } 142 143 /** 144 * Returns the {@link Writer} associated with this console. 145 */ writer()146 public PrintWriter writer() { 147 return writer; 148 } 149 150 private static class ConsoleReader extends BufferedReader { ConsoleReader(InputStream in)151 public ConsoleReader(InputStream in) throws UnsupportedEncodingException { 152 super(new InputStreamReader(in, System.getProperty("file.encoding")), 256); 153 lock = CONSOLE_LOCK; 154 } 155 156 @Override close()157 public void close() { 158 // Console.reader cannot be closed. 159 } 160 } 161 162 private static class ConsoleWriter extends PrintWriter { ConsoleWriter(OutputStream out)163 public ConsoleWriter(OutputStream out) { 164 super(out, true); 165 lock = CONSOLE_LOCK; 166 } 167 168 @Override close()169 public void close() { 170 // Console.writer cannot be closed. 171 flush(); 172 } 173 } 174 } 175