Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/io/Console.java
41152 views
1
/*
2
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.io;
27
28
import java.util.*;
29
import java.nio.charset.Charset;
30
import jdk.internal.access.JavaIOAccess;
31
import jdk.internal.access.SharedSecrets;
32
import sun.nio.cs.StreamDecoder;
33
import sun.nio.cs.StreamEncoder;
34
import sun.security.action.GetPropertyAction;
35
36
/**
37
* Methods to access the character-based console device, if any, associated
38
* with the current Java virtual machine.
39
*
40
* <p> Whether a virtual machine has a console is dependent upon the
41
* underlying platform and also upon the manner in which the virtual
42
* machine is invoked. If the virtual machine is started from an
43
* interactive command line without redirecting the standard input and
44
* output streams then its console will exist and will typically be
45
* connected to the keyboard and display from which the virtual machine
46
* was launched. If the virtual machine is started automatically, for
47
* example by a background job scheduler, then it will typically not
48
* have a console.
49
* <p>
50
* If this virtual machine has a console then it is represented by a
51
* unique instance of this class which can be obtained by invoking the
52
* {@link java.lang.System#console()} method. If no console device is
53
* available then an invocation of that method will return {@code null}.
54
* <p>
55
* Read and write operations are synchronized to guarantee the atomic
56
* completion of critical operations; therefore invoking methods
57
* {@link #readLine()}, {@link #readPassword()}, {@link #format format()},
58
* {@link #printf printf()} as well as the read, format and write operations
59
* on the objects returned by {@link #reader()} and {@link #writer()} may
60
* block in multithreaded scenarios.
61
* <p>
62
* Invoking {@code close()} on the objects returned by the {@link #reader()}
63
* and the {@link #writer()} will not close the underlying stream of those
64
* objects.
65
* <p>
66
* The console-read methods return {@code null} when the end of the
67
* console input stream is reached, for example by typing control-D on
68
* Unix or control-Z on Windows. Subsequent read operations will succeed
69
* if additional characters are later entered on the console's input
70
* device.
71
* <p>
72
* Unless otherwise specified, passing a {@code null} argument to any method
73
* in this class will cause a {@link NullPointerException} to be thrown.
74
* <p>
75
* <b>Security note:</b>
76
* If an application needs to read a password or other secure data, it should
77
* use {@link #readPassword()} or {@link #readPassword(String, Object...)} and
78
* manually zero the returned character array after processing to minimize the
79
* lifetime of sensitive data in memory.
80
*
81
* <blockquote><pre>{@code
82
* Console cons;
83
* char[] passwd;
84
* if ((cons = System.console()) != null &&
85
* (passwd = cons.readPassword("[%s]", "Password:")) != null) {
86
* ...
87
* java.util.Arrays.fill(passwd, ' ');
88
* }
89
* }</pre></blockquote>
90
*
91
* @author Xueming Shen
92
* @since 1.6
93
*/
94
95
public final class Console implements Flushable
96
{
97
/**
98
* Retrieves the unique {@link java.io.PrintWriter PrintWriter} object
99
* associated with this console.
100
*
101
* @return The printwriter associated with this console
102
*/
103
public PrintWriter writer() {
104
return pw;
105
}
106
107
/**
108
* Retrieves the unique {@link java.io.Reader Reader} object associated
109
* with this console.
110
* <p>
111
* This method is intended to be used by sophisticated applications, for
112
* example, a {@link java.util.Scanner} object which utilizes the rich
113
* parsing/scanning functionality provided by the {@code Scanner}:
114
* <blockquote><pre>
115
* Console con = System.console();
116
* if (con != null) {
117
* Scanner sc = new Scanner(con.reader());
118
* ...
119
* }
120
* </pre></blockquote>
121
* <p>
122
* For simple applications requiring only line-oriented reading, use
123
* {@link #readLine}.
124
* <p>
125
* The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) },
126
* {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and
127
* {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)}
128
* on the returned object will not read in characters beyond the line
129
* bound for each invocation, even if the destination buffer has space for
130
* more characters. The {@code Reader}'s {@code read} methods may block if a
131
* line bound has not been entered or reached on the console's input device.
132
* A line bound is considered to be any one of a line feed ({@code '\n'}),
133
* a carriage return ({@code '\r'}), a carriage return followed immediately
134
* by a linefeed, or an end of stream.
135
*
136
* @return The reader associated with this console
137
*/
138
public Reader reader() {
139
return reader;
140
}
141
142
/**
143
* Writes a formatted string to this console's output stream using
144
* the specified format string and arguments.
145
*
146
* @param fmt
147
* A format string as described in <a
148
* href="../util/Formatter.html#syntax">Format string syntax</a>
149
*
150
* @param args
151
* Arguments referenced by the format specifiers in the format
152
* string. If there are more arguments than format specifiers, the
153
* extra arguments are ignored. The number of arguments is
154
* variable and may be zero. The maximum number of arguments is
155
* limited by the maximum dimension of a Java array as defined by
156
* <cite>The Java Virtual Machine Specification</cite>.
157
* The behaviour on a
158
* {@code null} argument depends on the <a
159
* href="../util/Formatter.html#syntax">conversion</a>.
160
*
161
* @throws IllegalFormatException
162
* If a format string contains an illegal syntax, a format
163
* specifier that is incompatible with the given arguments,
164
* insufficient arguments given the format string, or other
165
* illegal conditions. For specification of all possible
166
* formatting errors, see the <a
167
* href="../util/Formatter.html#detail">Details</a> section
168
* of the formatter class specification.
169
*
170
* @return This console
171
*/
172
public Console format(String fmt, Object ...args) {
173
formatter.format(fmt, args).flush();
174
return this;
175
}
176
177
/**
178
* A convenience method to write a formatted string to this console's
179
* output stream using the specified format string and arguments.
180
*
181
* <p> An invocation of this method of the form
182
* {@code con.printf(format, args)} behaves in exactly the same way
183
* as the invocation of
184
* <pre>con.format(format, args)</pre>.
185
*
186
* @param format
187
* A format string as described in <a
188
* href="../util/Formatter.html#syntax">Format string syntax</a>.
189
*
190
* @param args
191
* Arguments referenced by the format specifiers in the format
192
* string. If there are more arguments than format specifiers, the
193
* extra arguments are ignored. The number of arguments is
194
* variable and may be zero. The maximum number of arguments is
195
* limited by the maximum dimension of a Java array as defined by
196
* <cite>The Java Virtual Machine Specification</cite>.
197
* The behaviour on a
198
* {@code null} argument depends on the <a
199
* href="../util/Formatter.html#syntax">conversion</a>.
200
*
201
* @throws IllegalFormatException
202
* If a format string contains an illegal syntax, a format
203
* specifier that is incompatible with the given arguments,
204
* insufficient arguments given the format string, or other
205
* illegal conditions. For specification of all possible
206
* formatting errors, see the <a
207
* href="../util/Formatter.html#detail">Details</a> section of the
208
* formatter class specification.
209
*
210
* @return This console
211
*/
212
public Console printf(String format, Object ... args) {
213
return format(format, args);
214
}
215
216
/**
217
* Provides a formatted prompt, then reads a single line of text from the
218
* console.
219
*
220
* @param fmt
221
* A format string as described in <a
222
* href="../util/Formatter.html#syntax">Format string syntax</a>.
223
*
224
* @param args
225
* Arguments referenced by the format specifiers in the format
226
* string. If there are more arguments than format specifiers, the
227
* extra arguments are ignored. The maximum number of arguments is
228
* limited by the maximum dimension of a Java array as defined by
229
* <cite>The Java Virtual Machine Specification</cite>.
230
*
231
* @throws IllegalFormatException
232
* If a format string contains an illegal syntax, a format
233
* specifier that is incompatible with the given arguments,
234
* insufficient arguments given the format string, or other
235
* illegal conditions. For specification of all possible
236
* formatting errors, see the <a
237
* href="../util/Formatter.html#detail">Details</a> section
238
* of the formatter class specification.
239
*
240
* @throws IOError
241
* If an I/O error occurs.
242
*
243
* @return A string containing the line read from the console, not
244
* including any line-termination characters, or {@code null}
245
* if an end of stream has been reached.
246
*/
247
public String readLine(String fmt, Object ... args) {
248
String line = null;
249
synchronized (writeLock) {
250
synchronized(readLock) {
251
if (!fmt.isEmpty())
252
pw.format(fmt, args);
253
try {
254
char[] ca = readline(false);
255
if (ca != null)
256
line = new String(ca);
257
} catch (IOException x) {
258
throw new IOError(x);
259
}
260
}
261
}
262
return line;
263
}
264
265
/**
266
* Reads a single line of text from the console.
267
*
268
* @throws IOError
269
* If an I/O error occurs.
270
*
271
* @return A string containing the line read from the console, not
272
* including any line-termination characters, or {@code null}
273
* if an end of stream has been reached.
274
*/
275
public String readLine() {
276
return readLine("");
277
}
278
279
/**
280
* Provides a formatted prompt, then reads a password or passphrase from
281
* the console with echoing disabled.
282
*
283
* @param fmt
284
* A format string as described in <a
285
* href="../util/Formatter.html#syntax">Format string syntax</a>
286
* for the prompt text.
287
*
288
* @param args
289
* Arguments referenced by the format specifiers in the format
290
* string. If there are more arguments than format specifiers, the
291
* extra arguments are ignored. The maximum number of arguments is
292
* limited by the maximum dimension of a Java array as defined by
293
* <cite>The Java Virtual Machine Specification</cite>.
294
*
295
* @throws IllegalFormatException
296
* If a format string contains an illegal syntax, a format
297
* specifier that is incompatible with the given arguments,
298
* insufficient arguments given the format string, or other
299
* illegal conditions. For specification of all possible
300
* formatting errors, see the <a
301
* href="../util/Formatter.html#detail">Details</a>
302
* section of the formatter class specification.
303
*
304
* @throws IOError
305
* If an I/O error occurs.
306
*
307
* @return A character array containing the password or passphrase read
308
* from the console, not including any line-termination characters,
309
* or {@code null} if an end of stream has been reached.
310
*/
311
public char[] readPassword(String fmt, Object ... args) {
312
char[] passwd = null;
313
synchronized (writeLock) {
314
synchronized(readLock) {
315
installShutdownHook();
316
try {
317
restoreEcho = echo(false);
318
} catch (IOException x) {
319
throw new IOError(x);
320
}
321
IOError ioe = null;
322
try {
323
if (!fmt.isEmpty())
324
pw.format(fmt, args);
325
passwd = readline(true);
326
} catch (IOException x) {
327
ioe = new IOError(x);
328
} finally {
329
try {
330
if (restoreEcho)
331
restoreEcho = echo(true);
332
} catch (IOException x) {
333
if (ioe == null)
334
ioe = new IOError(x);
335
else
336
ioe.addSuppressed(x);
337
}
338
if (ioe != null)
339
throw ioe;
340
}
341
pw.println();
342
}
343
}
344
return passwd;
345
}
346
347
private void installShutdownHook() {
348
if (shutdownHookInstalled)
349
return;
350
try {
351
// Add a shutdown hook to restore console's echo state should
352
// it be necessary.
353
SharedSecrets.getJavaLangAccess()
354
.registerShutdownHook(0 /* shutdown hook invocation order */,
355
false /* only register if shutdown is not in progress */,
356
new Runnable() {
357
public void run() {
358
try {
359
if (restoreEcho) {
360
echo(true);
361
}
362
} catch (IOException x) { }
363
}
364
});
365
} catch (IllegalStateException e) {
366
// shutdown is already in progress and readPassword is first used
367
// by a shutdown hook
368
}
369
shutdownHookInstalled = true;
370
}
371
372
/**
373
* Reads a password or passphrase from the console with echoing disabled
374
*
375
* @throws IOError
376
* If an I/O error occurs.
377
*
378
* @return A character array containing the password or passphrase read
379
* from the console, not including any line-termination characters,
380
* or {@code null} if an end of stream has been reached.
381
*/
382
public char[] readPassword() {
383
return readPassword("");
384
}
385
386
/**
387
* Flushes the console and forces any buffered output to be written
388
* immediately .
389
*/
390
public void flush() {
391
pw.flush();
392
}
393
394
395
/**
396
* Returns the {@link java.nio.charset.Charset Charset} object used for
397
* the {@code Console}.
398
* <p>
399
* The returned charset corresponds to the input and output source
400
* (e.g., keyboard and/or display) specified by the host environment or user.
401
* It may not necessarily be the same as the default charset returned from
402
* {@link java.nio.charset.Charset#defaultCharset() Charset.defaultCharset()}.
403
*
404
* @return a {@link java.nio.charset.Charset Charset} object used for the
405
* {@code Console}
406
* @since 17
407
*/
408
public Charset charset() {
409
assert CHARSET != null : "charset() should not return null";
410
return CHARSET;
411
}
412
413
private Object readLock;
414
private Object writeLock;
415
private Reader reader;
416
private Writer out;
417
private PrintWriter pw;
418
private Formatter formatter;
419
private char[] rcb;
420
private boolean restoreEcho;
421
private boolean shutdownHookInstalled;
422
private static native String encoding();
423
/*
424
* Sets the console echo status to {@code on} and returns the previous
425
* console on/off status.
426
* @param on the echo status to set to. {@code true} for echo on and
427
* {@code false} for echo off
428
* @return true if the previous console echo status is on
429
*/
430
private static native boolean echo(boolean on) throws IOException;
431
432
private char[] readline(boolean zeroOut) throws IOException {
433
int len = reader.read(rcb, 0, rcb.length);
434
if (len < 0)
435
return null; //EOL
436
if (rcb[len-1] == '\r')
437
len--; //remove CR at end;
438
else if (rcb[len-1] == '\n') {
439
len--; //remove LF at end;
440
if (len > 0 && rcb[len-1] == '\r')
441
len--; //remove the CR, if there is one
442
}
443
char[] b = new char[len];
444
if (len > 0) {
445
System.arraycopy(rcb, 0, b, 0, len);
446
if (zeroOut) {
447
Arrays.fill(rcb, 0, len, ' ');
448
}
449
}
450
return b;
451
}
452
453
private char[] grow() {
454
assert Thread.holdsLock(readLock);
455
char[] t = new char[rcb.length * 2];
456
System.arraycopy(rcb, 0, t, 0, rcb.length);
457
rcb = t;
458
return rcb;
459
}
460
461
class LineReader extends Reader {
462
private Reader in;
463
private char[] cb;
464
private int nChars, nextChar;
465
boolean leftoverLF;
466
LineReader(Reader in) {
467
this.in = in;
468
cb = new char[1024];
469
nextChar = nChars = 0;
470
leftoverLF = false;
471
}
472
public void close () {}
473
public boolean ready() throws IOException {
474
//in.ready synchronizes on readLock already
475
return in.ready();
476
}
477
478
public int read(char cbuf[], int offset, int length)
479
throws IOException
480
{
481
int off = offset;
482
int end = offset + length;
483
if (offset < 0 || offset > cbuf.length || length < 0 ||
484
end < 0 || end > cbuf.length) {
485
throw new IndexOutOfBoundsException();
486
}
487
synchronized(readLock) {
488
boolean eof = false;
489
char c = 0;
490
for (;;) {
491
if (nextChar >= nChars) { //fill
492
int n = 0;
493
do {
494
n = in.read(cb, 0, cb.length);
495
} while (n == 0);
496
if (n > 0) {
497
nChars = n;
498
nextChar = 0;
499
if (n < cb.length &&
500
cb[n-1] != '\n' && cb[n-1] != '\r') {
501
/*
502
* we're in canonical mode so each "fill" should
503
* come back with an eol. if there no lf or nl at
504
* the end of returned bytes we reached an eof.
505
*/
506
eof = true;
507
}
508
} else { /*EOF*/
509
if (off - offset == 0)
510
return -1;
511
return off - offset;
512
}
513
}
514
if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') {
515
/*
516
* if invoked by our readline, skip the leftover, otherwise
517
* return the LF.
518
*/
519
nextChar++;
520
}
521
leftoverLF = false;
522
while (nextChar < nChars) {
523
c = cbuf[off++] = cb[nextChar];
524
cb[nextChar++] = 0;
525
if (c == '\n') {
526
return off - offset;
527
} else if (c == '\r') {
528
if (off == end) {
529
/* no space left even the next is LF, so return
530
* whatever we have if the invoker is not our
531
* readLine()
532
*/
533
if (cbuf == rcb) {
534
cbuf = grow();
535
end = cbuf.length;
536
} else {
537
leftoverLF = true;
538
return off - offset;
539
}
540
}
541
if (nextChar == nChars && in.ready()) {
542
/*
543
* we have a CR and we reached the end of
544
* the read in buffer, fill to make sure we
545
* don't miss a LF, if there is one, it's possible
546
* that it got cut off during last round reading
547
* simply because the read in buffer was full.
548
*/
549
nChars = in.read(cb, 0, cb.length);
550
nextChar = 0;
551
}
552
if (nextChar < nChars && cb[nextChar] == '\n') {
553
cbuf[off++] = '\n';
554
nextChar++;
555
}
556
return off - offset;
557
} else if (off == end) {
558
if (cbuf == rcb) {
559
cbuf = grow();
560
end = cbuf.length;
561
} else {
562
return off - offset;
563
}
564
}
565
}
566
if (eof)
567
return off - offset;
568
}
569
}
570
}
571
}
572
573
private static final Charset CHARSET;
574
static {
575
String csname = encoding();
576
Charset cs = null;
577
if (csname == null) {
578
csname = GetPropertyAction.privilegedGetProperty("sun.stdout.encoding");
579
}
580
if (csname != null) {
581
try {
582
cs = Charset.forName(csname);
583
} catch (Exception ignored) { }
584
}
585
CHARSET = cs == null ? Charset.defaultCharset() : cs;
586
587
// Set up JavaIOAccess in SharedSecrets
588
SharedSecrets.setJavaIOAccess(new JavaIOAccess() {
589
public Console console() {
590
if (istty()) {
591
if (cons == null)
592
cons = new Console();
593
return cons;
594
}
595
return null;
596
}
597
598
public Charset charset() {
599
return CHARSET;
600
}
601
});
602
}
603
private static Console cons;
604
private static native boolean istty();
605
private Console() {
606
readLock = new Object();
607
writeLock = new Object();
608
out = StreamEncoder.forOutputStreamWriter(
609
new FileOutputStream(FileDescriptor.out),
610
writeLock,
611
CHARSET);
612
pw = new PrintWriter(out, true) { public void close() {} };
613
formatter = new Formatter(out);
614
reader = new LineReader(StreamDecoder.forInputStreamReader(
615
new FileInputStream(FileDescriptor.in),
616
readLock,
617
CHARSET));
618
rcb = new char[1024];
619
}
620
}
621
622