Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/io/Console.java
38829 views
/*1* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;2627import java.util.*;28import java.nio.charset.Charset;29import sun.nio.cs.StreamDecoder;30import sun.nio.cs.StreamEncoder;3132/**33* Methods to access the character-based console device, if any, associated34* with the current Java virtual machine.35*36* <p> Whether a virtual machine has a console is dependent upon the37* underlying platform and also upon the manner in which the virtual38* machine is invoked. If the virtual machine is started from an39* interactive command line without redirecting the standard input and40* output streams then its console will exist and will typically be41* connected to the keyboard and display from which the virtual machine42* was launched. If the virtual machine is started automatically, for43* example by a background job scheduler, then it will typically not44* have a console.45* <p>46* If this virtual machine has a console then it is represented by a47* unique instance of this class which can be obtained by invoking the48* {@link java.lang.System#console()} method. If no console device is49* available then an invocation of that method will return <tt>null</tt>.50* <p>51* Read and write operations are synchronized to guarantee the atomic52* completion of critical operations; therefore invoking methods53* {@link #readLine()}, {@link #readPassword()}, {@link #format format()},54* {@link #printf printf()} as well as the read, format and write operations55* on the objects returned by {@link #reader()} and {@link #writer()} may56* block in multithreaded scenarios.57* <p>58* Invoking <tt>close()</tt> on the objects returned by the {@link #reader()}59* and the {@link #writer()} will not close the underlying stream of those60* objects.61* <p>62* The console-read methods return <tt>null</tt> when the end of the63* console input stream is reached, for example by typing control-D on64* Unix or control-Z on Windows. Subsequent read operations will succeed65* if additional characters are later entered on the console's input66* device.67* <p>68* Unless otherwise specified, passing a <tt>null</tt> argument to any method69* in this class will cause a {@link NullPointerException} to be thrown.70* <p>71* <b>Security note:</b>72* If an application needs to read a password or other secure data, it should73* use {@link #readPassword()} or {@link #readPassword(String, Object...)} and74* manually zero the returned character array after processing to minimize the75* lifetime of sensitive data in memory.76*77* <blockquote><pre>{@code78* Console cons;79* char[] passwd;80* if ((cons = System.console()) != null &&81* (passwd = cons.readPassword("[%s]", "Password:")) != null) {82* ...83* java.util.Arrays.fill(passwd, ' ');84* }85* }</pre></blockquote>86*87* @author Xueming Shen88* @since 1.689*/9091public final class Console implements Flushable92{93/**94* Retrieves the unique {@link java.io.PrintWriter PrintWriter} object95* associated with this console.96*97* @return The printwriter associated with this console98*/99public PrintWriter writer() {100return pw;101}102103/**104* Retrieves the unique {@link java.io.Reader Reader} object associated105* with this console.106* <p>107* This method is intended to be used by sophisticated applications, for108* example, a {@link java.util.Scanner} object which utilizes the rich109* parsing/scanning functionality provided by the <tt>Scanner</tt>:110* <blockquote><pre>111* Console con = System.console();112* if (con != null) {113* Scanner sc = new Scanner(con.reader());114* ...115* }116* </pre></blockquote>117* <p>118* For simple applications requiring only line-oriented reading, use119* <tt>{@link #readLine}</tt>.120* <p>121* The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) },122* {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and123* {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)}124* on the returned object will not read in characters beyond the line125* bound for each invocation, even if the destination buffer has space for126* more characters. The {@code Reader}'s {@code read} methods may block if a127* line bound has not been entered or reached on the console's input device.128* A line bound is considered to be any one of a line feed (<tt>'\n'</tt>),129* a carriage return (<tt>'\r'</tt>), a carriage return followed immediately130* by a linefeed, or an end of stream.131*132* @return The reader associated with this console133*/134public Reader reader() {135return reader;136}137138/**139* Writes a formatted string to this console's output stream using140* the specified format string and arguments.141*142* @param fmt143* A format string as described in <a144* href="../util/Formatter.html#syntax">Format string syntax</a>145*146* @param args147* Arguments referenced by the format specifiers in the format148* string. If there are more arguments than format specifiers, the149* extra arguments are ignored. The number of arguments is150* variable and may be zero. The maximum number of arguments is151* limited by the maximum dimension of a Java array as defined by152* <cite>The Java™ Virtual Machine Specification</cite>.153* The behaviour on a154* <tt>null</tt> argument depends on the <a155* href="../util/Formatter.html#syntax">conversion</a>.156*157* @throws IllegalFormatException158* If a format string contains an illegal syntax, a format159* specifier that is incompatible with the given arguments,160* insufficient arguments given the format string, or other161* illegal conditions. For specification of all possible162* formatting errors, see the <a163* href="../util/Formatter.html#detail">Details</a> section164* of the formatter class specification.165*166* @return This console167*/168public Console format(String fmt, Object ...args) {169formatter.format(fmt, args).flush();170return this;171}172173/**174* A convenience method to write a formatted string to this console's175* output stream using the specified format string and arguments.176*177* <p> An invocation of this method of the form <tt>con.printf(format,178* args)</tt> behaves in exactly the same way as the invocation of179* <pre>con.format(format, args)</pre>.180*181* @param format182* A format string as described in <a183* href="../util/Formatter.html#syntax">Format string syntax</a>.184*185* @param args186* Arguments referenced by the format specifiers in the format187* string. If there are more arguments than format specifiers, the188* extra arguments are ignored. The number of arguments is189* variable and may be zero. The maximum number of arguments is190* limited by the maximum dimension of a Java array as defined by191* <cite>The Java™ Virtual Machine Specification</cite>.192* The behaviour on a193* <tt>null</tt> argument depends on the <a194* href="../util/Formatter.html#syntax">conversion</a>.195*196* @throws IllegalFormatException197* If a format string contains an illegal syntax, a format198* specifier that is incompatible with the given arguments,199* insufficient arguments given the format string, or other200* illegal conditions. For specification of all possible201* formatting errors, see the <a202* href="../util/Formatter.html#detail">Details</a> section of the203* formatter class specification.204*205* @return This console206*/207public Console printf(String format, Object ... args) {208return format(format, args);209}210211/**212* Provides a formatted prompt, then reads a single line of text from the213* console.214*215* @param fmt216* A format string as described in <a217* href="../util/Formatter.html#syntax">Format string syntax</a>.218*219* @param args220* Arguments referenced by the format specifiers in the format221* string. If there are more arguments than format specifiers, the222* extra arguments are ignored. The maximum number of arguments is223* limited by the maximum dimension of a Java array as defined by224* <cite>The Java™ Virtual Machine Specification</cite>.225*226* @throws IllegalFormatException227* If a format string contains an illegal syntax, a format228* specifier that is incompatible with the given arguments,229* insufficient arguments given the format string, or other230* illegal conditions. For specification of all possible231* formatting errors, see the <a232* href="../util/Formatter.html#detail">Details</a> section233* of the formatter class specification.234*235* @throws IOError236* If an I/O error occurs.237*238* @return A string containing the line read from the console, not239* including any line-termination characters, or <tt>null</tt>240* if an end of stream has been reached.241*/242public String readLine(String fmt, Object ... args) {243String line = null;244synchronized (writeLock) {245synchronized(readLock) {246if (fmt.length() != 0)247pw.format(fmt, args);248try {249char[] ca = readline(false);250if (ca != null)251line = new String(ca);252} catch (IOException x) {253throw new IOError(x);254}255}256}257return line;258}259260/**261* Reads a single line of text from the console.262*263* @throws IOError264* If an I/O error occurs.265*266* @return A string containing the line read from the console, not267* including any line-termination characters, or <tt>null</tt>268* if an end of stream has been reached.269*/270public String readLine() {271return readLine("");272}273274/**275* Provides a formatted prompt, then reads a password or passphrase from276* the console with echoing disabled.277*278* @param fmt279* A format string as described in <a280* href="../util/Formatter.html#syntax">Format string syntax</a>281* for the prompt text.282*283* @param args284* Arguments referenced by the format specifiers in the format285* string. If there are more arguments than format specifiers, the286* extra arguments are ignored. The maximum number of arguments is287* limited by the maximum dimension of a Java array as defined by288* <cite>The Java™ Virtual Machine Specification</cite>.289*290* @throws IllegalFormatException291* If a format string contains an illegal syntax, a format292* specifier that is incompatible with the given arguments,293* insufficient arguments given the format string, or other294* illegal conditions. For specification of all possible295* formatting errors, see the <a296* href="../util/Formatter.html#detail">Details</a>297* section of the formatter class specification.298*299* @throws IOError300* If an I/O error occurs.301*302* @return A character array containing the password or passphrase read303* from the console, not including any line-termination characters,304* or <tt>null</tt> if an end of stream has been reached.305*/306public char[] readPassword(String fmt, Object ... args) {307char[] passwd = null;308synchronized (writeLock) {309synchronized(readLock) {310try {311echoOff = echo(false);312} catch (IOException x) {313throw new IOError(x);314}315IOError ioe = null;316try {317if (fmt.length() != 0)318pw.format(fmt, args);319passwd = readline(true);320} catch (IOException x) {321ioe = new IOError(x);322} finally {323try {324echoOff = echo(true);325} catch (IOException x) {326if (ioe == null)327ioe = new IOError(x);328else329ioe.addSuppressed(x);330}331if (ioe != null)332throw ioe;333}334pw.println();335}336}337return passwd;338}339340/**341* Reads a password or passphrase from the console with echoing disabled342*343* @throws IOError344* If an I/O error occurs.345*346* @return A character array containing the password or passphrase read347* from the console, not including any line-termination characters,348* or <tt>null</tt> if an end of stream has been reached.349*/350public char[] readPassword() {351return readPassword("");352}353354/**355* Flushes the console and forces any buffered output to be written356* immediately .357*/358public void flush() {359pw.flush();360}361362private Object readLock;363private Object writeLock;364private Reader reader;365private Writer out;366private PrintWriter pw;367private Formatter formatter;368private Charset cs;369private char[] rcb;370private static native String encoding();371private static native boolean echo(boolean on) throws IOException;372private static boolean echoOff;373374private char[] readline(boolean zeroOut) throws IOException {375int len = reader.read(rcb, 0, rcb.length);376if (len < 0)377return null; //EOL378if (rcb[len-1] == '\r')379len--; //remove CR at end;380else if (rcb[len-1] == '\n') {381len--; //remove LF at end;382if (len > 0 && rcb[len-1] == '\r')383len--; //remove the CR, if there is one384}385char[] b = new char[len];386if (len > 0) {387System.arraycopy(rcb, 0, b, 0, len);388if (zeroOut) {389Arrays.fill(rcb, 0, len, ' ');390}391}392return b;393}394395private char[] grow() {396assert Thread.holdsLock(readLock);397char[] t = new char[rcb.length * 2];398System.arraycopy(rcb, 0, t, 0, rcb.length);399rcb = t;400return rcb;401}402403class LineReader extends Reader {404private Reader in;405private char[] cb;406private int nChars, nextChar;407boolean leftoverLF;408LineReader(Reader in) {409this.in = in;410cb = new char[1024];411nextChar = nChars = 0;412leftoverLF = false;413}414public void close () {}415public boolean ready() throws IOException {416//in.ready synchronizes on readLock already417return in.ready();418}419420public int read(char cbuf[], int offset, int length)421throws IOException422{423int off = offset;424int end = offset + length;425if (offset < 0 || offset > cbuf.length || length < 0 ||426end < 0 || end > cbuf.length) {427throw new IndexOutOfBoundsException();428}429synchronized(readLock) {430boolean eof = false;431char c = 0;432for (;;) {433if (nextChar >= nChars) { //fill434int n = 0;435do {436n = in.read(cb, 0, cb.length);437} while (n == 0);438if (n > 0) {439nChars = n;440nextChar = 0;441if (n < cb.length &&442cb[n-1] != '\n' && cb[n-1] != '\r') {443/*444* we're in canonical mode so each "fill" should445* come back with an eol. if there no lf or nl at446* the end of returned bytes we reached an eof.447*/448eof = true;449}450} else { /*EOF*/451if (off - offset == 0)452return -1;453return off - offset;454}455}456if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') {457/*458* if invoked by our readline, skip the leftover, otherwise459* return the LF.460*/461nextChar++;462}463leftoverLF = false;464while (nextChar < nChars) {465c = cbuf[off++] = cb[nextChar];466cb[nextChar++] = 0;467if (c == '\n') {468return off - offset;469} else if (c == '\r') {470if (off == end) {471/* no space left even the next is LF, so return472* whatever we have if the invoker is not our473* readLine()474*/475if (cbuf == rcb) {476cbuf = grow();477end = cbuf.length;478} else {479leftoverLF = true;480return off - offset;481}482}483if (nextChar == nChars && in.ready()) {484/*485* we have a CR and we reached the end of486* the read in buffer, fill to make sure we487* don't miss a LF, if there is one, it's possible488* that it got cut off during last round reading489* simply because the read in buffer was full.490*/491nChars = in.read(cb, 0, cb.length);492nextChar = 0;493}494if (nextChar < nChars && cb[nextChar] == '\n') {495cbuf[off++] = '\n';496nextChar++;497}498return off - offset;499} else if (off == end) {500if (cbuf == rcb) {501cbuf = grow();502end = cbuf.length;503} else {504return off - offset;505}506}507}508if (eof)509return off - offset;510}511}512}513}514515// Set up JavaIOAccess in SharedSecrets516static {517try {518// Add a shutdown hook to restore console's echo state should519// it be necessary.520sun.misc.SharedSecrets.getJavaLangAccess()521.registerShutdownHook(0 /* shutdown hook invocation order */,522false /* only register if shutdown is not in progress */,523new Runnable() {524public void run() {525try {526if (echoOff) {527echo(true);528}529} catch (IOException x) { }530}531});532} catch (IllegalStateException e) {533// shutdown is already in progress and console is first used534// by a shutdown hook535}536537sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {538public Console console() {539if (istty()) {540if (cons == null)541cons = new Console();542return cons;543}544return null;545}546547public Charset charset() {548// This method is called in sun.security.util.Password,549// cons already exists when this method is called550return cons.cs;551}552});553}554private static Console cons;555private native static boolean istty();556private Console() {557readLock = new Object();558writeLock = new Object();559String csname = encoding();560if (csname != null) {561try {562cs = Charset.forName(csname);563} catch (Exception x) {}564}565if (cs == null)566cs = Charset.defaultCharset();567out = StreamEncoder.forOutputStreamWriter(568new FileOutputStream(FileDescriptor.out),569writeLock,570cs);571pw = new PrintWriter(out, true) { public void close() {} };572formatter = new Formatter(out);573reader = new LineReader(StreamDecoder.forInputStreamReader(574new FileInputStream(FileDescriptor.in),575readLock,576cs));577rcb = new char[1024];578}579}580581582