2828import java .io .IOException ;
2929import java .io .PrintWriter ;
3030import java .io .Reader ;
31- import java .io .UncheckedIOException ;
3231import java .nio .charset .Charset ;
3332import java .util .Locale ;
3433
@@ -51,18 +50,134 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
5150 */
5251 @ Override
5352 public JdkConsole console (boolean isTTY , Charset charset ) {
54- try {
55- Terminal terminal = TerminalBuilder .builder ().encoding (charset )
56- .exec (false )
57- .systemOutput (SystemOutput .SysOut )
58- .build ();
59- return new JdkConsoleImpl (terminal );
60- } catch (IllegalStateException ise ) {
61- //cannot create a non-dumb, non-exec terminal,
62- //use the standard Console:
63- return null ;
64- } catch (IOException ioe ) {
65- throw new UncheckedIOException (ioe );
53+ return new LazyDelegatingJdkConsoleImpl (charset );
54+ }
55+
56+ private static class LazyDelegatingJdkConsoleImpl implements JdkConsole {
57+ private final Charset charset ;
58+ private volatile boolean jlineInitialized ;
59+ private volatile JdkConsole delegate ;
60+
61+ public LazyDelegatingJdkConsoleImpl (Charset charset ) {
62+ this .charset = charset ;
63+ this .delegate = new jdk .internal .io .JdkConsoleImpl (charset );
64+ }
65+
66+ @ Override
67+ public PrintWriter writer () {
68+ return getDelegate (true ).writer ();
69+ }
70+
71+ @ Override
72+ public Reader reader () {
73+ return getDelegate (true ).reader ();
74+ }
75+
76+ @ Override
77+ public JdkConsole println (Object obj ) {
78+ JdkConsole delegate = getDelegate (false );
79+
80+ delegate .println (obj );
81+ flushOldDelegateIfNeeded (delegate );
82+
83+ return this ;
84+ }
85+
86+ @ Override
87+ public JdkConsole print (Object obj ) {
88+ JdkConsole delegate = getDelegate (false );
89+
90+ delegate .print (obj );
91+ flushOldDelegateIfNeeded (delegate );
92+
93+ return this ;
94+ }
95+
96+ @ Override
97+ public String readln (String prompt ) {
98+ return getDelegate (true ).readln (prompt );
99+ }
100+
101+ @ Override
102+ public JdkConsole format (Locale locale , String format , Object ... args ) {
103+ JdkConsole delegate = getDelegate (false );
104+
105+ delegate .format (locale , format , args );
106+ flushOldDelegateIfNeeded (delegate );
107+
108+ return this ;
109+ }
110+
111+ @ Override
112+ public String readLine (Locale locale , String format , Object ... args ) {
113+ return getDelegate (true ).readLine (locale , format , args );
114+ }
115+
116+ @ Override
117+ public String readLine () {
118+ return getDelegate (true ).readLine ();
119+ }
120+
121+ @ Override
122+ public char [] readPassword (Locale locale , String format , Object ... args ) {
123+ return getDelegate (true ).readPassword (locale , format , args );
124+ }
125+
126+ @ Override
127+ public char [] readPassword () {
128+ return getDelegate (true ).readPassword ();
129+ }
130+
131+ @ Override
132+ public void flush () {
133+ getDelegate (false ).flush ();
134+ }
135+
136+ @ Override
137+ public Charset charset () {
138+ return charset ;
139+ }
140+
141+ private void flushOldDelegateIfNeeded (JdkConsole oldDelegate ) {
142+ if (oldDelegate != getDelegate (false )) {
143+ //if the delegate changed in the mean time, make sure the original
144+ //delegate is flushed:
145+ oldDelegate .flush ();
146+ }
147+ }
148+
149+ private JdkConsole getDelegate (boolean needsJLine ) {
150+ if (!needsJLine || jlineInitialized ) {
151+ return delegate ;
152+ }
153+
154+ return initializeJLineDelegate ();
155+ }
156+
157+ private synchronized JdkConsole initializeJLineDelegate () {
158+ JdkConsole newDelegate = delegate ;
159+
160+ if (jlineInitialized ) {
161+ return newDelegate ;
162+ }
163+
164+ try {
165+ Terminal terminal = TerminalBuilder .builder ().encoding (charset )
166+ .exec (false )
167+ .systemOutput (SystemOutput .SysOut )
168+ .build ();
169+ newDelegate = new JdkConsoleImpl (terminal );
170+ } catch (IllegalStateException ise ) {
171+ //cannot create a non-dumb, non-exec terminal,
172+ //use the standard Console:
173+ } catch (IOException ioe ) {
174+ //something went wrong, keep the existing delegate
175+ }
176+
177+ delegate = newDelegate ;
178+ jlineInitialized = true ;
179+
180+ return newDelegate ;
66181 }
67182 }
68183
0 commit comments