8330276: Console methods with explicit Locale

Reviewed-by: joehw, rriggs, jlahoda
This commit is contained in:
Naoto Sato 2024-05-15 19:28:24 +00:00
parent 8a4315f833
commit 7cff04fc8a
8 changed files with 417 additions and 104 deletions
src
java.base/share/classes
jdk.internal.le/share/classes/jdk/internal/org/jline
jdk.jshell/share/classes/jdk/jshell/execution/impl
test/jdk/java/io/Console

@ -62,6 +62,11 @@ import sun.security.action.GetPropertyAction;
* on the objects returned by {@link #reader()} and {@link #writer()} may
* block in multithreaded scenarios.
* <p>
* Operations that format strings are locale sensitive, using either the
* specified {@code Locale}, or the
* {@link Locale##default_locale default format Locale} to produce localized
* formatted strings.
* <p>
* Invoking {@code close()} on the objects returned by the {@link #reader()}
* and the {@link #writer()} will not close the underlying stream of those
* objects.
@ -147,11 +152,12 @@ public sealed class Console implements Flushable permits ProxyingConsole {
/**
* Writes a formatted string to this console's output stream using
* the specified format string and arguments.
* the specified format string and arguments with the
* {@link Locale##default_locale default format locale}.
*
* @param fmt
* A format string as described in <a
* href="../util/Formatter.html#syntax">Format string syntax</a>.
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
@ -160,39 +166,75 @@ public sealed class Console implements Flushable permits ProxyingConsole {
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behaviour on a
* {@code null} argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the <a
* href="../util/Formatter.html#detail">Details</a> section
* formatting errors, see the {@link
* Formatter##detail Details} section
* of the formatter class specification.
*
* @return This console
*/
public Console format(String fmt, Object ...args) {
public Console format(String format, Object ... args) {
throw newUnsupportedOperationException();
}
/**
* Writes a formatted string to this console's output stream using
* the specified format string and arguments with the specified
* {@code locale}.
*
* @param locale The {@linkplain Locale locale} to apply during
* formatting. If {@code locale} is {@code null} then no localization
* is applied.
*
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the {@link
* Formatter##detail Details} section
* of the formatter class specification.
*
* @return This console
* @since 23
*/
public Console format(Locale locale, String format, Object ... args) {
throw newUnsupportedOperationException();
}
/**
* A convenience method to write a formatted string to this console's
* output stream using the specified format string and arguments.
* output stream using the specified format string and arguments with
* the {@link Locale##default_locale default format locale}.
*
* <p> An invocation of this method of the form
* {@code con.printf(format, args)} behaves in exactly the same way
* as the invocation of
* {@snippet lang=java :
* con.format(format, args)
* }
* @implSpec This is the same as calling {@code format(format, args)}.
*
* @param format
* A format string as described in <a
* href="../util/Formatter.html#syntax">Format string syntax</a>.
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
@ -201,17 +243,17 @@ public sealed class Console implements Flushable permits ProxyingConsole {
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behaviour on a
* {@code null} argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the <a
* href="../util/Formatter.html#detail">Details</a> section of the
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @return This console
@ -221,28 +263,76 @@ public sealed class Console implements Flushable permits ProxyingConsole {
}
/**
* Provides a formatted prompt, then reads a single line of text from the
* console.
* A convenience method to write a formatted string to this console's
* output stream using the specified format string and arguments with
* the specified {@code locale}.
*
* @param fmt
* A format string as described in <a
* href="../util/Formatter.html#syntax">Format string syntax</a>.
* @implSpec This is the same as calling
* {@code format(locale, format, args)}.
*
* @param locale The {@linkplain Locale locale} to apply during
* formatting. If {@code locale} is {@code null} then no localization
* is applied.
*
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The maximum number of arguments is
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the <a
* href="../util/Formatter.html#detail">Details</a> section
* of the formatter class specification.
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @return This console
* @since 23
*/
public Console printf(Locale locale, String format, Object ... args) {
throw newUnsupportedOperationException();
}
/**
* Provides a formatted prompt using the
* {@link Locale##default_locale default format locale}, then reads a
* single line of text from the console.
*
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @throws IOError
* If an I/O error occurs.
@ -251,7 +341,51 @@ public sealed class Console implements Flushable permits ProxyingConsole {
* including any line-termination characters, or {@code null}
* if an end of stream has been reached.
*/
public String readLine(String fmt, Object ... args) {
public String readLine(String format, Object ... args) {
throw newUnsupportedOperationException();
}
/**
* Provides a formatted prompt using the specified {@code locale}, then
* reads a single line of text from the console.
*
* @param locale The {@linkplain Locale locale} to apply during
* formatting. If {@code locale} is {@code null} then no localization
* is applied.
*
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @throws IOError
* If an I/O error occurs.
*
* @return A string containing the line read from the console, not
* including any line-termination characters, or {@code null}
* if an end of stream has been reached.
* @since 23
*/
public String readLine(Locale locale, String format, Object ... args) {
throw newUnsupportedOperationException();
}
@ -270,29 +404,34 @@ public sealed class Console implements Flushable permits ProxyingConsole {
}
/**
* Provides a formatted prompt, then reads a password or passphrase from
* the console with echoing disabled.
* Provides a formatted prompt using the
* {@link Locale##default_locale default format locale}, then reads a
* password or passphrase from the console with echoing disabled.
*
* @param fmt
* A format string as described in <a
* href="../util/Formatter.html#syntax">Format string syntax</a>
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}
* for the prompt text.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The maximum number of arguments is
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the <a
* href="../util/Formatter.html#detail">Details</a>
* section of the formatter class specification.
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @throws IOError
* If an I/O error occurs.
@ -301,7 +440,52 @@ public sealed class Console implements Flushable permits ProxyingConsole {
* from the console, not including any line-termination characters,
* or {@code null} if an end of stream has been reached.
*/
public char[] readPassword(String fmt, Object ... args) {
public char[] readPassword(String format, Object ... args) {
throw newUnsupportedOperationException();
}
/**
* Provides a formatted prompt using the specified {@code locale}, then
* reads a password or passphrase from the console with echoing disabled.
*
* @param locale The {@linkplain Locale locale} to apply during
* formatting. If {@code locale} is {@code null} then no localization
* is applied.
*
* @param format
* A format string as described in {@link
* Formatter##syntax Format string syntax}
* for the prompt text.
*
* @param args
* Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers, the
* extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java Virtual Machine Specification</cite>.
* The behavior on a
* {@code null} argument depends on the {@link
* Formatter##syntax conversion}.
*
* @throws IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
* illegal conditions. For specification of all possible
* formatting errors, see the {@link
* Formatter##detail Details} section of the
* formatter class specification.
*
* @throws IOError
* If an I/O error occurs.
*
* @return A character array containing the password or passphrase read
* from the console, not including any line-termination characters,
* or {@code null} if an end of stream has been reached.
* @since 23
*/
public char[] readPassword(Locale locale, String format, Object ... args) {
throw newUnsupportedOperationException();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,8 @@
package java.io;
import java.nio.charset.Charset;
import java.util.Locale;
import jdk.internal.io.JdkConsole;
/**
@ -83,9 +85,17 @@ final class ProxyingConsole extends Console {
* {@inheritDoc}
*/
@Override
public Console format(String fmt, Object ... args) {
public Console format(String format, Object ... args) {
return format(Locale.getDefault(Locale.Category.FORMAT), format, args);
}
/**
* {@inheritDoc}
*/
@Override
public Console format(Locale locale, String format, Object ... args) {
synchronized (writeLock) {
delegate.format(fmt, args);
delegate.format(locale, format, args);
}
return this;
}
@ -95,8 +105,16 @@ final class ProxyingConsole extends Console {
*/
@Override
public Console printf(String format, Object ... args) {
return printf(Locale.getDefault(Locale.Category.FORMAT), format, args);
}
/**
* {@inheritDoc}
*/
@Override
public Console printf(Locale locale, String format, Object ... args) {
synchronized (writeLock) {
delegate.printf(format, args);
delegate.format(locale, format, args);
}
return this;
}
@ -105,10 +123,18 @@ final class ProxyingConsole extends Console {
* {@inheritDoc}
*/
@Override
public String readLine(String fmt, Object ... args) {
public String readLine(String format, Object ... args) {
return readLine(Locale.getDefault(Locale.Category.FORMAT), format, args);
}
/**
* {@inheritDoc}
*/
@Override
public String readLine(Locale locale, String format, Object ... args) {
synchronized (writeLock) {
synchronized (readLock) {
return delegate.readLine(fmt, args);
return delegate.readLine(locale, format, args);
}
}
}
@ -127,10 +153,18 @@ final class ProxyingConsole extends Console {
* {@inheritDoc}
*/
@Override
public char[] readPassword(String fmt, Object ... args) {
public char[] readPassword(String format, Object ... args) {
return readPassword(Locale.getDefault(Locale.Category.FORMAT), format, args);
}
/**
* {@inheritDoc}
*/
@Override
public char[] readPassword(Locale locale, String format, Object ... args) {
synchronized (writeLock) {
synchronized (readLock) {
return delegate.readPassword(fmt, args);
return delegate.readPassword(locale, format, args);
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@ package jdk.internal.io;
import java.io.PrintWriter;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Locale;
/**
* Delegate interface for custom Console implementations.
@ -37,11 +38,10 @@ import java.nio.charset.Charset;
public interface JdkConsole {
PrintWriter writer();
Reader reader();
JdkConsole format(String fmt, Object ... args);
JdkConsole printf(String format, Object ... args);
String readLine(String fmt, Object ... args);
JdkConsole format(Locale locale, String format, Object ... args);
String readLine(Locale locale, String format, Object ... args);
String readLine();
char[] readPassword(String fmt, Object ... args);
char[] readPassword(Locale locale, String format, Object ... args);
char[] readPassword();
void flush();
Charset charset();

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,6 +36,7 @@ import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
import jdk.internal.access.SharedSecrets;
@ -57,23 +58,18 @@ public final class JdkConsoleImpl implements JdkConsole {
}
@Override
public JdkConsole format(String fmt, Object ... args) {
formatter.format(fmt, args).flush();
public JdkConsole format(Locale locale, String format, Object ... args) {
formatter.format(locale, format, args).flush();
return this;
}
@Override
public JdkConsole printf(String format, Object ... args) {
return format(format, args);
}
@Override
public String readLine(String fmt, Object ... args) {
public String readLine(Locale locale, String format, Object ... args) {
String line = null;
synchronized (writeLock) {
synchronized(readLock) {
if (!fmt.isEmpty())
pw.format(fmt, args);
if (!format.isEmpty())
pw.format(locale, format, args);
try {
char[] ca = readline(false);
if (ca != null)
@ -88,11 +84,11 @@ public final class JdkConsoleImpl implements JdkConsole {
@Override
public String readLine() {
return readLine("");
return readLine(Locale.getDefault(Locale.Category.FORMAT), "");
}
@Override
public char[] readPassword(String fmt, Object ... args) {
public char[] readPassword(Locale locale, String format, Object ... args) {
char[] passwd = null;
synchronized (writeLock) {
synchronized(readLock) {
@ -104,8 +100,8 @@ public final class JdkConsoleImpl implements JdkConsole {
}
IOError ioe = null;
try {
if (!fmt.isEmpty())
pw.format(fmt, args);
if (!format.isEmpty())
pw.format(locale, format, args);
passwd = readline(true);
} catch (IOException x) {
ioe = new IOError(x);
@ -164,7 +160,7 @@ public final class JdkConsoleImpl implements JdkConsole {
@Override
public char[] readPassword() {
return readPassword("");
return readPassword(Locale.getDefault(Locale.Category.FORMAT), "");
}
@Override

@ -30,6 +30,7 @@ import java.io.PrintWriter;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
import java.util.Locale;
import jdk.internal.io.JdkConsole;
import jdk.internal.io.JdkConsoleProvider;
@ -84,21 +85,16 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
}
@Override
public JdkConsole format(String fmt, Object ... args) {
writer().format(fmt, args).flush();
public JdkConsole format(Locale locale, String format, Object ... args) {
writer().format(locale, format, args).flush();
return this;
}
@Override
public JdkConsole printf(String format, Object ... args) {
return format(format, args);
}
@Override
public String readLine(String fmt, Object ... args) {
public String readLine(Locale locale, String format, Object ... args) {
try {
initJLineIfNeeded();
return jline.readLine(fmt.formatted(args).replace("%", "%%"));
return jline.readLine(String.format(locale, format, args).replace("%", "%%"));
} catch (EndOfFileException eofe) {
return null;
}
@ -106,14 +102,14 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
@Override
public String readLine() {
return readLine("");
return readLine(Locale.getDefault(Locale.Category.FORMAT), "");
}
@Override
public char[] readPassword(String fmt, Object ... args) {
public char[] readPassword(Locale locale, String format, Object ... args) {
try {
initJLineIfNeeded();
return jline.readLine(fmt.formatted(args).replace("%", "%%"), '\0')
return jline.readLine(String.format(locale, format, args).replace("%", "%%"), '\0')
.toCharArray();
} catch (EndOfFileException eofe) {
return null;
@ -124,7 +120,7 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
@Override
public char[] readPassword() {
return readPassword("");
return readPassword(Locale.getDefault(Locale.Category.FORMAT), "");
}
@Override

@ -76,7 +76,9 @@ public class Display {
public void resize(int rows, int columns) {
if (rows == 0 || columns == 0) {
columns = 1;
// OpenJDK patch. Original code assigned 1 to columns, which ended up
// appending " \b" to the prompt in certain cases.
columns = Integer.MAX_VALUE - 1;
rows = 1;
}
if (this.rows != rows || this.columns != columns) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,8 @@ import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
import jdk.internal.io.JdkConsole;
import jdk.internal.io.JdkConsoleProvider;
import jdk.jshell.JShellConsole;
@ -193,8 +195,8 @@ public class ConsoleImpl {
* {@inheritDoc}
*/
@Override
public JdkConsole format(String fmt, Object... args) {
writer().format(fmt, args).flush();
public JdkConsole format(Locale locale, String format, Object... args) {
writer().format(locale, format, args).flush();
return this;
}
@ -202,19 +204,11 @@ public class ConsoleImpl {
* {@inheritDoc}
*/
@Override
public JdkConsole printf(String format, Object... args) {
return format(format, args);
}
/**
* {@inheritDoc}
*/
@Override
public String readLine(String fmt, Object... args) {
public String readLine(Locale locale, String format, Object... args) {
try {
return sendAndReceive(() -> {
remoteInput.write(Task.READ_LINE.ordinal());
String prompt = fmt.formatted(args);
String prompt = String.format(locale, format, args);
char[] chars = prompt.toCharArray();
sendChars(chars, 0, chars.length);
char[] line = readChars();
@ -230,18 +224,18 @@ public class ConsoleImpl {
*/
@Override
public String readLine() {
return readLine("");
return readLine(Locale.getDefault(Locale.Category.FORMAT), "");
}
/**
* {@inheritDoc}
*/
@Override
public char[] readPassword(String fmt, Object... args) {
public char[] readPassword(Locale locale, String format, Object... args) {
try {
return sendAndReceive(() -> {
remoteInput.write(Task.READ_PASSWORD.ordinal());
String prompt = fmt.formatted(args);
String prompt = String.format(locale, format, args);
char[] chars = prompt.toCharArray();
sendChars(chars, 0, chars.length);
return readChars();
@ -256,7 +250,7 @@ public class ConsoleImpl {
*/
@Override
public char[] readPassword() {
return readPassword("");
return readPassword(Locale.getDefault(Locale.Category.FORMAT), "");
}
/**

@ -0,0 +1,107 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import jdk.test.lib.process.ProcessTools;
/**
* @test
* @bug 8330276
* @summary Tests Console methods that have Locale as an argument
* @library /test/lib
* @modules jdk.internal.le jdk.localedata
*/
public class LocaleTest {
private static Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
private static String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
// We want to limit the expected strings within US-ASCII charset, as
// the native encoding is determined as such, which is used by
// the `Process` class under jtreg environment.
private static List<String> EXPECTED = List.of(
String.format(Locale.UK, FORMAT, TODAY),
String.format(Locale.FRANCE, FORMAT, TODAY),
String.format(Locale.GERMANY, FORMAT, TODAY),
String.format(Locale.of("es"), FORMAT, TODAY),
String.format((Locale)null, FORMAT, TODAY),
String.format((Locale)null, FORMAT, TODAY),
String.format((Locale)null, FORMAT, TODAY),
String.format((Locale)null, FORMAT, TODAY)
);
public static void main(String... args) throws Throwable {
if (args.length == 0) {
// no arg will launch the child process that actually perform tests
var pb = ProcessTools.createTestJavaProcessBuilder(
"LocaleTest", "dummy");
var input = new File(System.getProperty("test.src", "."), "input.txt");
pb.redirectInput(input);
var oa = ProcessTools.executeProcess(pb);
if (oa.getExitValue() == -1) {
System.out.println("System.console() returns null. Ignoring the test.");
} else {
var output = oa.asLines();
var resultText =
"""
Actual output: %s
Expected output: %s
""".formatted(output, EXPECTED);
if (!output.equals(EXPECTED)) {
throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
} else {
oa.shouldHaveExitValue(0);
System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
}
}
} else {
var con = System.console();
if (con != null) {
// tests these additional methods that take a Locale
con.format(Locale.UK, FORMAT, TODAY);
con.printf("\n");
con.printf(Locale.FRANCE, FORMAT, TODAY);
con.printf("\n");
con.readLine(Locale.GERMANY, FORMAT, TODAY);
con.printf("\n");
con.readPassword(Locale.of("es"), FORMAT, TODAY);
con.printf("\n");
// tests null locale
con.format((Locale)null, FORMAT, TODAY);
con.printf("\n");
con.printf((Locale)null, FORMAT, TODAY);
con.printf("\n");
con.readLine((Locale)null, FORMAT, TODAY);
con.printf("\n");
con.readPassword((Locale)null, FORMAT, TODAY);
} else {
// Exit with -1
System.exit(-1);
}
}
}
}