Skip to content

Commit bae2247

Browse files
committed
8308591: JLine as the default Console provider
Reviewed-by: alanb
1 parent b772e67 commit bae2247

File tree

5 files changed

+62
-15
lines changed

5 files changed

+62
-15
lines changed

src/java.base/share/classes/java/io/Console.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,16 +344,33 @@ public Charset charset() {
344344
throw newUnsupportedOperationException();
345345
}
346346

347+
/**
348+
* {@return {@code true} if the {@code Console} instance is a terminal}
349+
* <p>
350+
* This method returns {@code true} if the console device, associated with the current
351+
* Java virtual machine, is a terminal, typically an interactive command line
352+
* connected to a keyboard and display.
353+
*
354+
* @implNote The default implementation returns the value equivalent to calling
355+
* {@code isatty(stdin/stdout)} on POSIX platforms, or whether standard in/out file
356+
* descriptors are character devices or not on Windows.
357+
*
358+
* @since 22
359+
*/
360+
public boolean isTerminal() {
361+
return istty;
362+
}
363+
347364
private static UnsupportedOperationException newUnsupportedOperationException() {
348365
return new UnsupportedOperationException(
349366
"Console class itself does not provide implementation");
350367
}
351368

352369
private static native String encoding();
370+
private static final boolean istty = istty();
353371
static final Charset CHARSET;
354372
static {
355373
Charset cs = null;
356-
boolean istty = istty();
357374

358375
if (istty) {
359376
String csname = encoding();

src/java.base/share/classes/java/io/ProxyingConsole.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -34,24 +34,30 @@
3434
*/
3535
final class ProxyingConsole extends Console {
3636
private final JdkConsole delegate;
37-
private final Object readLock;
38-
private final Object writeLock;
39-
private final Reader reader;
40-
private final PrintWriter printWriter;
37+
private final Object readLock = new Object();
38+
private final Object writeLock = new Object();
39+
private volatile Reader reader;
40+
private volatile PrintWriter printWriter;
4141

4242
ProxyingConsole(JdkConsole delegate) {
4343
this.delegate = delegate;
44-
readLock = new Object();
45-
writeLock = new Object();
46-
reader = new WrappingReader(delegate.reader(), readLock);
47-
printWriter = new WrappingWriter(delegate.writer(), writeLock);
4844
}
4945

5046
/**
5147
* {@inheritDoc}
5248
*/
5349
@Override
5450
public PrintWriter writer() {
51+
PrintWriter printWriter = this.printWriter;
52+
if (printWriter == null) {
53+
synchronized (this) {
54+
printWriter = this.printWriter;
55+
if (printWriter == null) {
56+
printWriter = new WrappingWriter(delegate.writer(), writeLock);
57+
this.printWriter = printWriter;
58+
}
59+
}
60+
}
5561
return printWriter;
5662
}
5763

@@ -60,6 +66,16 @@ public PrintWriter writer() {
6066
*/
6167
@Override
6268
public Reader reader() {
69+
Reader reader = this.reader;
70+
if (reader == null) {
71+
synchronized (this) {
72+
reader = this.reader;
73+
if (reader == null) {
74+
reader = new WrappingReader(delegate.reader(), readLock);
75+
this.reader = reader;
76+
}
77+
}
78+
}
6379
return reader;
6480
}
6581

src/java.base/share/classes/jdk/internal/io/JdkConsoleProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public interface JdkConsoleProvider {
3333
/**
3434
* The module name of the JdkConsole default provider.
3535
*/
36-
String DEFAULT_PROVIDER_MODULE_NAME = "java.base";
36+
String DEFAULT_PROVIDER_MODULE_NAME = "jdk.internal.le";
3737

3838
/**
3939
* {@return the Console instance, or {@code null} if not available}

src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,7 @@ public JdkConsole printf(String format, Object ... args) {
9191
@Override
9292
public String readLine(String fmt, Object ... args) {
9393
try {
94+
initJLineIfNeeded();
9495
return jline.readLine(fmt.formatted(args));
9596
} catch (EndOfFileException eofe) {
9697
return null;
@@ -105,6 +106,7 @@ public String readLine() {
105106
@Override
106107
public char[] readPassword(String fmt, Object ... args) {
107108
try {
109+
initJLineIfNeeded();
108110
return jline.readLine(fmt.formatted(args), '\0').toCharArray();
109111
} catch (EndOfFileException eofe) {
110112
return null;
@@ -126,12 +128,24 @@ public Charset charset() {
126128
return terminal.encoding();
127129
}
128130

129-
private final LineReader jline;
130131
private final Terminal terminal;
132+
private volatile LineReader jline;
131133

132134
public JdkConsoleImpl(Terminal terminal) {
133135
this.terminal = terminal;
134-
this.jline = LineReaderBuilder.builder().terminal(terminal).build();
136+
}
137+
138+
private void initJLineIfNeeded() {
139+
LineReader jline = this.jline;
140+
if (jline == null) {
141+
synchronized (this) {
142+
jline = this.jline;
143+
if (jline == null) {
144+
jline = LineReaderBuilder.builder().terminal(terminal).build();
145+
this.jline = jline;
146+
}
147+
}
148+
}
135149
}
136150
}
137151
}

test/jdk/java/io/Console/ModuleSelectionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* @summary Tests System.console() returns correct Console (or null) from the expected
2828
* module.
2929
* @modules java.base/java.io:+open
30-
* @run main/othervm ModuleSelectionTest java.base
30+
* @run main/othervm ModuleSelectionTest jdk.internal.le
3131
* @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le
3232
* @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base
3333
* @run main/othervm --limit-modules java.base ModuleSelectionTest java.base

0 commit comments

Comments
 (0)