This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 1a72af035d Fix more character encoding and ANSI color problems when
using SIS from command line or from JShell.
1a72af035d is described below
commit 1a72af035d9ee83abec8aa68e8f2da1cf005e7c4
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Dec 14 17:02:31 2023 +0100
Fix more character encoding and ANSI color problems
when using SIS from command line or from JShell.
---
.../main/org/apache/sis/console/AboutCommand.java | 10 +--
.../main/org/apache/sis/console/Command.java | 7 +-
.../main/org/apache/sis/console/CommandRunner.java | 68 +++++++----------
.../apache/sis/console/FormattedOutputCommand.java | 3 +
.../org/apache/sis/console/IdentifierCommand.java | 12 +--
.../apache/sis/console/ResourcesDownloader.java | 3 +-
.../main/org/apache/sis/console/SIS.java | 29 ++------
.../org/apache/sis/console/TransformCommand.java | 45 +++++------
.../main/org/apache/sis/io/wkt/AbstractParser.java | 3 +-
.../org/apache/sis/io/wkt/FormattableObject.java | 17 ++---
.../main/org/apache/sis/io/wkt/Formatter.java | 21 +-----
.../org/apache/sis/parameter/ParameterFormat.java | 11 +--
.../main/org/apache/sis/parameter/Parameters.java | 6 +-
.../sis/referencing/factory/CacheRecord.java | 5 +-
.../factory/ConcurrentAuthorityFactory.java | 24 ++++--
.../referencing/util/j2d/ShapeUtilitiesViewer.java | 5 +-
.../main/org/apache/sis/system/Environment.java | 87 ++++++++++++++++++++++
.../main/org/apache/sis/util/Printable.java | 42 +++++++++++
18 files changed, 246 insertions(+), 152 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
index 115fbec3b0..fd83a21a7e 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
@@ -161,24 +161,22 @@ final class AboutCommand extends CommandRunner {
if (warnings != null) {
out.println();
if (colors) {
- out.print(X364.BACKGROUND_RED.sequence());
- out.print(X364.BOLD.sequence());
+ color(X364.BACKGROUND_RED);
+ color(X364.BOLD);
out.print(' ');
}
Vocabulary.getResources(locale).appendLabel(Vocabulary.Keys.Warnings, out);
if (colors) {
out.print(' ');
out.println(X364.RESET.sequence());
- out.print(X364.FOREGROUND_RED.sequence());
+ color(X364.FOREGROUND_RED);
} else {
out.println();
}
for (final String warning : warnings) {
out.println(warning);
}
- if (colors) {
- out.print(X364.FOREGROUND_DEFAULT.sequence());
- }
+ color(X364.FOREGROUND_DEFAULT);
}
out.flush();
return 0;
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java
index 2d9d882e3b..4eae489efa 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/Command.java
@@ -31,6 +31,7 @@ import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.logging.Initializer;
import org.apache.sis.util.logging.MonolineFormatter;
+import org.apache.sis.system.Environment;
/**
@@ -278,9 +279,7 @@ public final class Command {
* @param faint whether to turn on the faint output.
*/
final void setFaintOutput(final boolean faint) {
- if (command.colors) {
- command.out.write((faint ? X364.FAINT : X364.NORMAL).sequence());
- }
+ command.color(faint ? X364.FAINT : X364.NORMAL);
}
/**
@@ -340,7 +339,7 @@ public final class Command {
@SuppressWarnings("UseOfSystemOutOrSystemErr")
private static void error(final String[] args, final Exception e) {
final boolean debug = ArraysExt.containsIgnoreCase(args, Option.PREFIX
+ "debug");
- final PrintWriter err = CommandRunner.writer(System.console(),
System.err);
+ final PrintWriter err = Environment.writer(System.console(),
System.err);
if (debug) {
e.printStackTrace(err);
} else {
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java
index 8de71c01f9..f61aea42fa 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/CommandRunner.java
@@ -24,19 +24,17 @@ import java.util.EnumMap;
import java.util.TimeZone;
import java.io.Console;
import java.io.IOException;
-import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.InvalidPathException;
+import org.apache.sis.system.Environment;
import org.apache.sis.util.Locales;
import org.apache.sis.util.Exceptions;
-import org.apache.sis.util.Workaround;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.internal.X364;
-import org.apache.sis.pending.jdk.JDK17;
import org.apache.sis.storage.DataOptionKey;
import org.apache.sis.storage.StorageConnector;
@@ -57,25 +55,6 @@ abstract class CommandRunner {
*/
static final String TEST = "TEST";
- /**
- * Whether the use of the console writer should be avoided.
- * In our tests with Java 21, sending non ASCII characters to the console
writer in a Linux system
- * from a JShell session resulted in wrong characters being printed,
sometime followed by JShell errors.
- * This flag is set only if the commands are run from JShell.
- *
- * @see #writer(Console, PrintStream)
- */
- @Workaround(library="jshell", version="21")
- private static boolean avoidConsoleWriter;
-
- /**
- * Notifies the command runners that the use of console writer should be
avoided.
- * This method should be invoked in JShell environment only.
- */
- static void avoidConsoleWriter() {
- avoidConsoleWriter = true;
- }
-
/**
* The instance, used by {@link ResourcesDownloader} only.
* We use this static field as a workaround for the fact that {@code
ResourcesDownloader} is not
@@ -267,32 +246,15 @@ abstract class CommandRunner {
err = out;
} else {
outputBuffer = null;
- err = writer(console, System.err);
+ err = Environment.writer(console, System.err);
if (explicitEncoding) {
out = new PrintWriter(new OutputStreamWriter(System.out,
encoding), true);
} else {
- out = writer(console, System.out);
+ out = Environment.writer(console, System.out);
}
}
}
- /**
- * Returns the console print writer, or the given alternative if the
console cannot be used.
- *
- * @param console the value of {@link System#console()}, potentially
null.
- * @param fallback the fallback to use if the console cannot be used.
- * @return the writer.
- */
- static PrintWriter writer(final Console console, final PrintStream
fallback) {
- if (console == null) {
- return new PrintWriter(fallback, true);
- } else if (avoidConsoleWriter) {
- return new PrintWriter(new OutputStreamWriter(fallback,
JDK17.charset(console)), true);
- } else {
- return console.writer();
- }
- }
-
/**
* Returns the value of the specified option as a character string.
*
@@ -394,6 +356,30 @@ abstract class CommandRunner {
return true;
}
+ /**
+ * Prints the given color to the standard output stream if ANSI X3.64
+ * escape sequences are enabled, or does nothing otherwise.
+ *
+ * @param code the ANSI X3.64 color to print.
+ */
+ final void color(final X364 code) {
+ color(colors, out, code);
+ }
+
+ /**
+ * Prints the given color to the given stream if ANSI X3.64
+ * escape sequences are enabled, or does nothing otherwise.
+ *
+ * @param colors the condition for printing the color. Usually {@link
#colors}.
+ * @param out where to print the ANSI sequence. Usually {@link #out}
or {@link #err}.
+ * @param code the ANSI X3.64 color to print.
+ */
+ static void color(final boolean colors, final PrintWriter out, final X364
code) {
+ if (colors) {
+ out.print(code.sequence());
+ }
+ }
+
/**
* Returns {@code true} if the command should use the standard input.
*/
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java
index 3f15750b64..4bda2c2de6 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/FormattedOutputCommand.java
@@ -45,6 +45,7 @@ import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.TreeTableFormat;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.internal.X364;
import org.apache.sis.measure.Range;
import org.apache.sis.setup.OptionKey;
import org.apache.sis.xml.MarshallerPool;
@@ -241,7 +242,9 @@ abstract class FormattedOutputCommand extends CommandRunner
{
if (warnings != null) {
out.flush();
err.println();
+ color(colors, err, X364.FOREGROUND_YELLOW);
err.println(warnings.toString(locale));
+ color(colors, err, X364.RESET);
}
break;
}
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/IdentifierCommand.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/IdentifierCommand.java
index 60ad797a9a..7aa7e1dd01 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/IdentifierCommand.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/IdentifierCommand.java
@@ -226,16 +226,16 @@ final class IdentifierCommand extends
FormattedOutputCommand {
if (row != null) {
states.add(row.state);
final boolean warning = colors &&
row.state.text.startsWith("!");
- if (warning) out.print(X364.FOREGROUND_RED.sequence());
+ color(warning, out, X364.FOREGROUND_RED);
out.print(row.state.text);
out.print(' ');
out.print(row.identifier);
- if (warning) out.print(X364.FOREGROUND_DEFAULT.sequence());
- if (colors) out.print(X364.FOREGROUND_GRAY.sequence());
+ color(warning, out, X364.FOREGROUND_DEFAULT);
+ color(X364.FOREGROUND_GRAY);
out.print(CharSequences.spaces(width -
row.identifier.length()));
out.print("| ");
out.println(row.description);
- if (colors) out.print(X364.FOREGROUND_DEFAULT.sequence());
+ color(X364.FOREGROUND_DEFAULT);
}
}
states.remove(State.VALID);
@@ -246,9 +246,9 @@ final class IdentifierCommand extends
FormattedOutputCommand {
final ResourceBundle resources =
ResourceBundle.getBundle("org.apache.sis.console.IdentifierState", locale);
for (final State state : states) {
final boolean warning = colors && state.text.startsWith("!");
- if (warning) out.print(X364.FOREGROUND_RED.sequence());
+ color(warning, out, X364.FOREGROUND_RED);
out.print(state.text);
- if (warning) out.print(X364.FOREGROUND_DEFAULT.sequence());
+ color(warning, out, X364.FOREGROUND_DEFAULT);
out.print(' ');
out.println(resources.getString(state.name()));
}
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
index f33658b8f1..9e7ffc824b 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/ResourcesDownloader.java
@@ -25,6 +25,7 @@ import java.io.Console;
import java.io.PrintWriter;
import org.apache.sis.util.internal.X364;
import org.apache.sis.system.Fallback;
+import org.apache.sis.system.Environment;
import org.apache.sis.setup.OptionalInstallations;
@@ -85,7 +86,7 @@ public class ResourcesDownloader extends
OptionalInstallations {
colors = false;
}
console = System.console();
- out = CommandRunner.writer(console, System.out);
+ out = Environment.writer(console, System.out);
}
/**
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
index 1f864f03d9..f46c416759 100644
--- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
+++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
@@ -18,13 +18,11 @@ package org.apache.sis.console;
import java.util.EnumMap;
import java.io.PrintWriter;
-import org.apache.sis.io.wkt.Colors;
import org.apache.sis.util.Static;
+import org.apache.sis.util.Printable;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.internal.X364;
-import org.apache.sis.io.wkt.FormattableObject;
-import org.apache.sis.io.wkt.WKTFormat;
+import org.apache.sis.system.Environment;
/**
@@ -49,7 +47,7 @@ public final class SIS extends Static {
* Problems observed with Java 21 on Linux when printing non-ASCII
characters.
*/
static {
- CommandRunner.avoidConsoleWriter();
+ Environment.avoidConsoleWriter();
}
/**
@@ -751,11 +749,6 @@ public final class SIS extends Static {
- /**
- * The object to use for formatting WKT objects, created when first needed.
- */
- private static WKTFormat wktFormat;
-
/**
* Prints the given object to the standard output stream.
*
@@ -763,20 +756,12 @@ public final class SIS extends Static {
*/
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public static void print(final Object value) {
- final PrintWriter out = CommandRunner.writer(System.console(),
System.out);
- if (value instanceof FormattableObject) {
- synchronized (SIS.class) {
- if (wktFormat == null) {
- wktFormat = new WKTFormat(null, null);
- if (X364.isAnsiSupported()) {
- wktFormat.setColors(Colors.DEFAULT);
- }
- }
- out.print(wktFormat.format(value));
- }
+ if (value instanceof Printable) {
+ ((Printable) value).print();
} else {
+ final PrintWriter out = Environment.writer(System.console(),
System.out);
out.println(value);
+ out.flush();
}
- out.flush();
}
}
diff --git
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java
index 698ee27bfa..8b4b6aff11 100644
---
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java
+++
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/TransformCommand.java
@@ -272,16 +272,21 @@ final class TransformCommand extends
FormattedOutputCommand {
}
/**
- * Prints the character for commented lines.
+ * Appends the ANSI X3.64 sequence if colors are enabled, otherwise does
nothing.
*/
- private void printCommentLinePrefix() {
+ private void outHeader(final X364 code) {
if (colors) {
- outHeader.append(X364.FOREGROUND_GRAY.sequence());
+ outHeader.append(code.sequence());
}
+ }
+
+ /**
+ * Prints the character for commented lines.
+ */
+ private void printCommentLinePrefix() {
+ outHeader(X364.FOREGROUND_GRAY);
outHeader.append("# ");
- if (colors) {
- outHeader.append(X364.FOREGROUND_DEFAULT.sequence());
- }
+ outHeader(X364.FOREGROUND_DEFAULT);
}
/**
@@ -311,15 +316,11 @@ final class TransformCommand extends
FormattedOutputCommand {
outHeader.append(object.getName().getCode());
if (identifier != null) {
outHeader.append(' ');
- if (colors) {
- outHeader.append(X364.FOREGROUND_CYAN.sequence());
- }
+ outHeader(X364.FOREGROUND_CYAN);
outHeader.append('(');
outHeader.append(identifier);
outHeader.append(')');
- if (colors) {
- outHeader.append(X364.FOREGROUND_DEFAULT.sequence());
- }
+ outHeader(X364.FOREGROUND_DEFAULT);
}
if (!idRequired) {
outHeader.nextLine();
@@ -338,13 +339,9 @@ final class TransformCommand extends
FormattedOutputCommand {
private void printOperations(final CoordinateOperation step, boolean
isNext) {
if (isNext) {
isNext = false;
- if (colors) {
- outHeader.append(X364.FOREGROUND_GREEN.sequence());
- }
+ outHeader(X364.FOREGROUND_GREEN);
outHeader.append(" → ");
- if (colors) {
- outHeader.append(X364.FOREGROUND_DEFAULT.sequence());
- }
+ outHeader(X364.FOREGROUND_DEFAULT);
}
if (!printNameAndIdentifier(step, true)) {
if (step instanceof ConcatenatedOperation) {
@@ -369,13 +366,9 @@ final class TransformCommand extends
FormattedOutputCommand {
accuracy = Formulas.LINEAR_TOLERANCE;
}
printHeader(Vocabulary.Keys.Accuracy);
- if (colors) {
- outHeader.append(X364.FOREGROUND_YELLOW.sequence()); //
Same as Colors.DEFAULT for ElementKind.NUMBER
- }
+ outHeader(X364.FOREGROUND_YELLOW); // Same as
Colors.DEFAULT for ElementKind.NUMBER
outHeader.append(Double.toString(accuracy));
- if (colors) {
- outHeader.append(X364.FOREGROUND_DEFAULT.sequence());
- }
+ outHeader(X364.FOREGROUND_DEFAULT);
outHeader.append(" metres");
outHeader.nextLine();
}
@@ -461,11 +454,11 @@ final class TransformCommand extends
FormattedOutputCommand {
}
if (quoted) fieldWidth -= 2;
out.print(CharSequences.spaces(fieldWidth - text.length()));
- if (colors) out.print(color.sequence());
+ color(color);
if (quoted) out.print('"');
out.print(text);
if (quoted) out.print('"');
- if (colors) out.print(X364.FOREGROUND_DEFAULT.sequence());
+ color(X364.FOREGROUND_DEFAULT);
}
/*
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
index fce3cbff30..439d33516c 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
@@ -239,8 +239,9 @@ abstract class AbstractParser implements Parser {
@Override
public final Object createFromWKT(final String wkt) throws
FactoryException {
final ParsePosition position = new ParsePosition(0);
+ @SuppressWarnings("LocalVariableHidesMemberVariable")
+ final Warnings warnings;
Object result = null;
- Warnings warnings;
try {
result = createFromWKT(wkt, position);
} catch (ParseException exception) {
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
index ee68bd05db..893cf1ccf3 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
@@ -22,9 +22,11 @@ import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicReference;
import jakarta.xml.bind.annotation.XmlTransient;
import org.apache.sis.util.Debug;
+import org.apache.sis.util.Printable;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.internal.X364;
import org.apache.sis.util.internal.Constants;
+import org.apache.sis.system.Environment;
/**
@@ -60,7 +62,7 @@ import org.apache.sis.util.internal.Constants;
* </ul>
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT
2 specification</a>
* @see <a
href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Legacy
WKT 1</a>
@@ -68,7 +70,7 @@ import org.apache.sis.util.internal.Constants;
* @since 0.4
*/
@XmlTransient
-public abstract class FormattableObject {
+public abstract class FormattableObject implements Printable {
/**
* The formatter for the {@link #toWKT()} and {@link #toString()} methods.
Formatters are not
* thread-safe, consequently we must make sure that only one thread uses a
given instance.
@@ -149,16 +151,13 @@ public abstract class FormattableObject {
* <p>This is a convenience method for debugging purpose and for console
applications.</p>
*/
@Debug
+ @Override
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public void print() {
final Console console = System.console();
- final PrintWriter out = (console != null) ? console.writer() : null;
- final String wkt = formatWKT(Convention.WKT2_SIMPLIFIED, (out != null)
&& X364.isAnsiSupported(), false);
- if (out != null) {
- out.println(wkt);
- } else {
- System.out.println(wkt);
- }
+ final PrintWriter out = Environment.writer(console, System.out);
+ out.println(formatWKT(Convention.WKT2_SIMPLIFIED, (console != null) &&
X364.isAnsiSupported(), false));
+ out.flush();
}
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
index 7d897f820d..2074da7e8e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
@@ -19,7 +19,6 @@ package org.apache.sis.io.wkt;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
@@ -62,13 +61,11 @@ import org.apache.sis.math.Vector;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.Localized;
-import org.apache.sis.util.Exceptions;
import org.apache.sis.util.Characters;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.collection.IntegerList;
import org.apache.sis.util.internal.X364;
import org.apache.sis.util.internal.Numerics;
@@ -1855,23 +1852,11 @@ public class Formatter implements Localized {
final String ln = System.lineSeparator();
buffer.append(ln).append(ln);
if (colors != null) {
-
buffer.append(X364.BACKGROUND_RED.sequence()).append(X364.BOLD.sequence()).append('
');
+ buffer.append(X364.FOREGROUND_YELLOW.sequence());
}
-
Vocabulary.getResources(errorLocale).appendLabel(Vocabulary.Keys.Warnings,
buffer);
+ buffer.append(warnings);
if (colors != null) {
- buffer.append('
').append(X364.RESET.sequence()).append(X364.FOREGROUND_RED.sequence());
- }
- buffer.append(ln);
- final int n = warnings.getNumMessages();
- final Set<String> done = new HashSet<>();
- for (int i=0; i<n; i++) {
- String message =
Exceptions.getLocalizedMessage(warnings.getException(i), errorLocale);
- if (message == null) {
- message = warnings.getMessage(i);
- }
- if (done.add(message)) {
- buffer.append(" • ").append(message).append(ln);
- }
+ buffer.append(X364.RESET.sequence());
}
}
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
index 9d9bd82a46..3e13498216 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
@@ -25,9 +25,9 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.TimeZone;
-import java.io.Console;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.io.PrintWriter;
import java.text.Format;
import java.text.NumberFormat;
import java.text.FieldPosition;
@@ -46,15 +46,16 @@ import org.apache.sis.measure.Range;
import org.apache.sis.io.TableAppender;
import org.apache.sis.io.TabularFormat;
import org.apache.sis.io.wkt.Colors;
+import org.apache.sis.system.Environment;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.metadata.internal.NameToIdentifier;
import org.apache.sis.util.internal.CollectionsExt;
import org.apache.sis.util.internal.X364;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.metadata.internal.NameToIdentifier;
import static org.apache.sis.util.collection.Containers.hashMapCapacity;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -998,8 +999,7 @@ public class ParameterFormat extends TabularFormat<Object> {
*/
@SuppressWarnings("UseOfSystemOutOrSystemErr")
static void print(final Object object) {
- final Console console = System.console();
- final Appendable out = (console != null) ? console.writer() :
System.out;
+ final PrintWriter out = Environment.writer();
final ParameterFormat f = getSharedInstance(Colors.NAMING);
try {
f.format(object, out);
@@ -1007,6 +1007,7 @@ public class ParameterFormat extends
TabularFormat<Object> {
throw new UncheckedIOException(e); // Should never happen
since we are writing to stdout.
}
INSTANCE.set(f);
+ out.flush();
}
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/Parameters.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/Parameters.java
index f57d0927c9..7f62e5f7d0 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/Parameters.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/Parameters.java
@@ -39,6 +39,7 @@ import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Debug;
+import org.apache.sis.util.Printable;
import org.apache.sis.util.resources.Errors;
@@ -104,11 +105,11 @@ import org.apache.sis.util.resources.Errors;
* overriding one method has no impact on other methods.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlTransient
-public abstract class Parameters implements ParameterValueGroup, Cloneable {
+public abstract class Parameters implements ParameterValueGroup, Cloneable,
Printable {
/**
* For subclass constructors only.
*/
@@ -976,6 +977,7 @@ public abstract class Parameters implements
ParameterValueGroup, Cloneable {
* @since 0.7
*/
@Debug
+ @Override
public void print() {
ParameterFormat.print(this);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/CacheRecord.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/CacheRecord.java
index 38a85cc74e..2891576e31 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/CacheRecord.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/CacheRecord.java
@@ -22,9 +22,9 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;
-import java.io.Console;
import java.io.PrintWriter;
import org.opengis.referencing.IdentifiedObject;
+import org.apache.sis.system.Environment;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Debug;
@@ -119,8 +119,7 @@ final class CacheRecord implements Comparable<CacheRecord> {
final CacheRecord[] records = list.toArray(CacheRecord[]::new);
Arrays.sort(records);
if (out == null) {
- final Console c = System.console();
- out = (c != null) ? c.writer() : new PrintWriter(System.out);
+ out = Environment.writer();
}
for (final CacheRecord record : records) {
out.print(record.key);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
index e5eb461322..cf58dad05b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
@@ -47,21 +47,22 @@ import org.opengis.metadata.citation.Citation;
import org.opengis.parameter.ParameterDescriptor;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Debug;
+import org.apache.sis.util.Printable;
import org.apache.sis.util.Disposable;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Messages;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.logging.PerformanceLevel;
import org.apache.sis.util.collection.Cache;
+import org.apache.sis.util.internal.CollectionsExt;
+import org.apache.sis.util.internal.StandardDateFormat;
import org.apache.sis.metadata.simple.SimpleCitation;
import org.apache.sis.system.ReferenceQueueConsumer;
import org.apache.sis.system.DelayedExecutor;
import org.apache.sis.system.DelayedRunnable;
import org.apache.sis.system.Configuration;
import org.apache.sis.system.Shutdown;
-import org.apache.sis.util.internal.CollectionsExt;
-import org.apache.sis.util.internal.StandardDateFormat;
-import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.resources.Messages;
/**
@@ -102,7 +103,7 @@ import org.apache.sis.util.resources.Messages;
* @since 0.7
*/
public abstract class ConcurrentAuthorityFactory<DAO extends
GeodeticAuthorityFactory>
- extends GeodeticAuthorityFactory implements AutoCloseable
+ extends GeodeticAuthorityFactory implements AutoCloseable, Printable
{
/**
* Duration of data access operations that should be logged, in
nanoseconds.
@@ -2075,6 +2076,19 @@ public abstract class ConcurrentAuthorityFactory<DAO
extends GeodeticAuthorityFa
CacheRecord.printCacheContent(cache, out);
}
+ /**
+ * Prints the cache content to the standard output stream.
+ * Keys are sorted by numerical order if possible, or alphabetical order
otherwise.
+ * This method is used for debugging purpose only.
+ *
+ * @see #isCacheable(String, Object)
+ */
+ @Debug
+ @Override
+ public void print() {
+ printCacheContent(null);
+ }
+
/**
* A hook to be executed either when the {@link
ConcurrentAuthorityFactory} is collected by the garbage collector,
* when the Java Virtual Machine is shutdown, or when the module is
uninstalled by the OSGi or Servlet container.
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/util/j2d/ShapeUtilitiesViewer.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/util/j2d/ShapeUtilitiesViewer.java
index 3259bdd8b1..e516ab4dbb 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/util/j2d/ShapeUtilitiesViewer.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/util/j2d/ShapeUtilitiesViewer.java
@@ -18,7 +18,6 @@ package org.apache.sis.referencing.util.j2d;
import java.util.Locale;
import java.util.Random;
-import java.io.Console;
import java.io.PrintWriter;
import java.awt.BorderLayout;
import java.awt.Color;
@@ -32,6 +31,7 @@ import java.awt.geom.Point2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
+import org.apache.sis.system.Environment;
import org.apache.sis.util.CharSequences;
@@ -96,8 +96,7 @@ public final class ShapeUtilitiesViewer extends JPanel {
input = new Path2D.Float();
output = new Path2D.Float();
random = new Random();
- final Console console = System.console();
- out = (console != null) ? console.writer() : new
PrintWriter(System.out);
+ out = Environment.writer();
}
/**
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/Environment.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/Environment.java
new file mode 100644
index 0000000000..c545d46fc2
--- /dev/null
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/Environment.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.system;
+
+import java.io.Console;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.OutputStreamWriter;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.Workaround;
+import org.apache.sis.pending.jdk.JDK17;
+
+
+/**
+ * Method related to the environment where Apache SIS is executed.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+public final class Environment extends Static {
+ /**
+ * Whether the use of the console writer should be avoided.
+ *
+ * @see #avoidConsoleWriter()
+ */
+ private static boolean avoidConsoleWriter;
+
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private Environment() {
+ }
+
+ /**
+ * Notifies the command runners that the use of console writer should be
avoided.
+ * In our tests with Java 21, sending non ASCII characters to the console
writer in a Linux system
+ * from a JShell session resulted in wrong characters being printed,
sometime followed by JShell errors.
+ * This flag is set only if the commands are run from JShell.
+ */
+ @Workaround(library="jshell", version="21")
+ public static void avoidConsoleWriter() {
+ avoidConsoleWriter = true;
+ }
+
+ /**
+ * Returns the console print writer, or the standard output stream if
there is no console.
+ * Caller should flush the writer after use, because there is no guarantee
that is will not
+ * be disposed by the garbage collector.
+ *
+ * @return the writer to use.
+ */
+ public static PrintWriter writer() {
+ return writer(System.console(), System.out);
+ }
+
+ /**
+ * Returns the console print writer, or the given alternative if the
console cannot be used.
+ * Caller should flush the writer after use, because there is no guarantee
that is will not
+ * be disposed by the garbage collector.
+ *
+ * @param console the value of {@link System#console()}, potentially
null.
+ * @param fallback the fallback to use if the console cannot be used.
+ * @return the writer to use.
+ */
+ public static PrintWriter writer(final Console console, final PrintStream
fallback) {
+ if (console == null) {
+ return new PrintWriter(fallback, true);
+ } else if (avoidConsoleWriter) {
+ return new PrintWriter(new OutputStreamWriter(fallback,
JDK17.charset(console)), true);
+ } else {
+ return console.writer();
+ }
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Printable.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Printable.java
new file mode 100644
index 0000000000..afabe5b65a
--- /dev/null
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Printable.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.util;
+
+
+/**
+ * Object providing a {@code print()} method for sending a string
representation to the standard output stream.
+ * A call to {@code object.print()} is often (but not necessarily) equivalent
to {@code System.out.println(object)},
+ * except that <cite>ANSI escape codes</cite> (a.k.a. ECMA-48, ISO/IEC 6429
and X3.64 standards) may be used for
+ * syntax coloring if the terminal support it. The character encoding may also
be more suitable on some platforms.
+ * Finally, some implementations may be more verbose than {@code toString()}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.5
+ * @since 1.5
+ */
+public interface Printable {
+ /**
+ * Prints a string representation of this object to the {@linkplain
System#out standard output stream}.
+ * If a {@linkplain java.io.Console console} is attached to the running
JVM (i.e. if the application is
+ * run from the command-line and the output is not redirected to a file)
and if Apache SIS thinks that
+ * the console supports the ANSI escape codes (a.k.a. X3.64), then a
syntax coloring may be applied.
+ *
+ * <p>This is a convenience method for debugging purpose and for console
applications.</p>
+ */
+ @Debug
+ void print();
+}