From 9ef736f1c7f0b8de5c7a31ee65261a315fd29954 Mon Sep 17 00:00:00 2001
From: "Piotr P. Karwasz"
Date: Wed, 16 Oct 2024 11:12:53 +0200
Subject: [PATCH] Remove JANSI dependency in `2.x` (#3070)
This commit:
- Removes support for the outdated [Jansi 1.x](http://fusesource.github.io/jansi/) version in `Console` appender.
- Rewrites `JAnsiTextRenderer`, use in the `%m{ansi}` and `%ex{ansi}` pattern converters to use our internal ANSI support instead of Jansi.
Fixes #1736.
---
.../AbstractLog4j1ConfigurationTest.java | 124 +++--
log4j-core-test/pom.xml | 7 -
.../log4j/core/test/categories/Layouts.java | 2 -
.../core/test/categories/package-info.java | 4 +-
.../ConsoleAppenderAnsiMessagesMain.java | 5 +-
.../ConsoleAppenderAnsiStyleJira180Main.java | 8 +-
.../ConsoleAppenderAnsiStyleJira272Main.java | 8 +-
.../ConsoleAppenderAnsiStyleJira319Main.java | 8 +-
.../ConsoleAppenderAnsiStyleLayoutMain.java | 6 +-
...onsoleAppenderAnsiStyleNameLayoutMain.java | 3 +-
...=> ConsoleAppenderAnsiXExceptionMain.java} | 15 +-
...oleAppenderDefaultSuppressedThrowable.java | 11 +-
...oleAppenderHighlightLayoutDefaultMain.java | 3 +-
.../ConsoleAppenderHighlightLayoutMain.java | 3 +-
.../ConsoleAppenderJAnsiMessageMain.java | 84 ----
...enderJira1002ShortThrowableLayoutMain.java | 4 +-
.../ConsoleAppenderNoAnsiStyleLayoutMain.java | 9 +-
.../appender/JansiConsoleAppenderJira965.java | 28 --
.../core/impl/ThrowableFormatOptionsTest.java | 134 +++---
.../core/pattern/JAnsiTextRendererTest.java | 58 +++
...est.java => MessageAnsiConverterTest.java} | 4 +-
.../pattern/MessageStyledConverterTest.java | 2 +-
.../resources/log4j2-console-msg-ansi.xml | 30 --
log4j-core/pom.xml | 8 -
.../log4j/core/appender/ConsoleAppender.java | 151 ++-----
.../core/impl/ThrowableFormatOptions.java | 18 +-
.../logging/log4j/core/impl/package-info.java | 2 +-
.../log4j/core/layout/PatternLayout.java | 13 +-
.../log4j/core/pattern/AnsiEscape.java | 7 +-
.../log4j/core/pattern/JAnsiTextRenderer.java | 423 ++++++++----------
.../core/pattern/MessagePatternConverter.java | 9 +-
.../log4j/core/pattern/package-info.java | 2 +-
.../logging/log4j/core/util/Loader.java | 4 +
.../log4j/smtp/SmtpAppenderAsyncTest.java | 4 +-
log4j-parent/pom.xml | 7 -
pom.xml | 7 -
src/changelog/.2.x.x/.release-notes.adoc.ftl | 6 +
.../.2.x.x/1736_split_jansi_support.xml | 8 +
.../.2.x.x/2916_rewrite_jansi_renderer.xml | 8 +
src/site/antora/antora.tmpl.yml | 1 -
src/site/antora/antora.yml | 1 -
.../modules/ROOT/pages/manual/appenders.adoc | 43 +-
.../ROOT/pages/manual/pattern-layout.adoc | 23 +-
.../ROOT/pages/manual/systemproperties.adoc | 7 -
.../systemproperties/properties-jansi.adoc | 32 --
45 files changed, 513 insertions(+), 831 deletions(-)
rename log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/{ConsoleAppenderJAnsiXExceptionMain.java => ConsoleAppenderAnsiXExceptionMain.java} (78%)
delete mode 100644 log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
delete mode 100644 log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
create mode 100644 log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
rename log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/{MessageJansiConverterTest.java => MessageAnsiConverterTest.java} (94%)
delete mode 100644 log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml
create mode 100644 src/changelog/.2.x.x/1736_split_jansi_support.xml
create mode 100644 src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml
delete mode 100644 src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
index 90214096ff1..85851f52e6b 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
@@ -31,7 +31,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
-import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
@@ -66,7 +65,6 @@
import org.apache.logging.log4j.core.filter.ThresholdFilter;
import org.apache.logging.log4j.core.layout.HtmlLayout;
import org.apache.logging.log4j.core.layout.PatternLayout;
-import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
@@ -78,7 +76,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
abstract Configuration getConfiguration(String configResourcePrefix) throws URISyntaxException, IOException;
- protected InputStream getResourceAsStream(final String configResource) throws IOException {
+ protected InputStream getResourceAsStream(final String configResource) {
final InputStream is = getClass().getClassLoader().getResourceAsStream(configResource);
assertNotNull(is);
return is;
@@ -123,7 +121,7 @@ private Layout> testConsole(final String configResource) throws Exception {
final ConsoleAppender appender = configuration.getAppender(name);
assertNotNull(
"Missing appender '" + name + "' in configuration " + configResource + " → " + configuration, appender);
- assertEquals("follow", true, getFollowProperty(appender));
+ assertTrue("follow", getFollowProperty(appender));
assertEquals(Target.SYSTEM_ERR, appender.getTarget());
//
final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
@@ -141,16 +139,15 @@ public void testConsoleTtccLayout() throws Exception {
}
public void testRollingFileAppender() throws Exception {
- testRollingFileAppender("config-1.2/log4j-RollingFileAppender", "RFA", "target/hadoop.log.%i");
+ testRollingFileAppender("config-1.2/log4j-RollingFileAppender");
}
public void testDailyRollingFileAppender() throws Exception {
- testDailyRollingFileAppender(
- "config-1.2/log4j-DailyRollingFileAppender", "DRFA", "target/hadoop.log%d{.dd-MM-yyyy}");
+ testDailyRollingFileAppender("config-1.2/log4j-DailyRollingFileAppender");
}
public void testRollingFileAppenderWithProperties() throws Exception {
- testRollingFileAppender("config-1.2/log4j-RollingFileAppender-with-props", "RFA", "target/hadoop.log.%i");
+ testRollingFileAppender("config-1.2/log4j-RollingFileAppender-with-props");
}
public void testSystemProperties1() throws Exception {
@@ -160,13 +157,13 @@ public void testSystemProperties1() throws Exception {
final Configuration configuration = getConfiguration("config-1.2/log4j-system-properties-1");
try {
final RollingFileAppender appender = configuration.getAppender("RFA");
- assertEquals("append", false, getAppendProperty(appender));
+ assertFalse("append", getAppendProperty(appender));
assertEquals("bufferSize", 1000, appender.getManager().getBufferSize());
- assertEquals("immediateFlush", false, appender.getImmediateFlush());
+ assertFalse("immediateFlush", appender.getImmediateFlush());
final DefaultRolloverStrategy rolloverStrategy =
(DefaultRolloverStrategy) appender.getManager().getRolloverStrategy();
assertEquals(16, rolloverStrategy.getMaxIndex());
- final CompositeTriggeringPolicy ctp = (CompositeTriggeringPolicy) appender.getTriggeringPolicy();
+ final CompositeTriggeringPolicy ctp = appender.getTriggeringPolicy();
final TriggeringPolicy[] triggeringPolicies = ctp.getTriggeringPolicies();
assertEquals(1, triggeringPolicies.length);
final TriggeringPolicy tp = triggeringPolicies[0];
@@ -174,17 +171,11 @@ public void testSystemProperties1() throws Exception {
final SizeBasedTriggeringPolicy sbtp = (SizeBasedTriggeringPolicy) tp;
assertEquals(20 * 1024 * 1024, sbtp.getMaxFileSize());
appender.stop(10, TimeUnit.SECONDS);
- // System.out.println("expected: " + tempFileName + " Actual: " +
- // appender.getFileName());
assertEquals(tempFileName, appender.getFileName());
} finally {
configuration.start();
configuration.stop();
- try {
- Files.deleteIfExists(tempFilePath);
- } catch (final FileSystemException e) {
- e.printStackTrace();
- }
+ Files.deleteIfExists(tempFilePath);
}
}
@@ -195,22 +186,17 @@ public void testSystemProperties2() throws Exception {
assertEquals(tmpDir + "/hadoop.log", appender.getFileName());
appender.stop(10, TimeUnit.SECONDS);
// Try to clean up
- try {
- Path path = new File(appender.getFileName()).toPath();
- Files.deleteIfExists(path);
- path = new File("${java.io.tmpdir}").toPath();
- Files.deleteIfExists(path);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ Path path = new File(appender.getFileName()).toPath();
+ Files.deleteIfExists(path);
+ path = new File("${java.io.tmpdir}").toPath();
+ Files.deleteIfExists(path);
}
- private void testRollingFileAppender(final String configResource, final String name, final String filePattern)
- throws Exception {
+ private void testRollingFileAppender(final String configResource) throws Exception {
final Configuration configuration = getConfiguration(configResource);
- final Appender appender = configuration.getAppender(name);
+ final Appender appender = configuration.getAppender("RFA");
assertNotNull(appender);
- assertEquals(name, appender.getName());
+ assertEquals("RFA", appender.getName());
assertTrue(appender.getClass().getName(), appender instanceof RollingFileAppender);
final RollingFileAppender rfa = (RollingFileAppender) appender;
@@ -218,11 +204,11 @@ private void testRollingFileAppender(final String configResource, final String n
"defaultRolloverStrategy", rfa.getManager().getRolloverStrategy() instanceof DefaultRolloverStrategy);
assertFalse(
"rolloverStrategy", ((DefaultRolloverStrategy) rfa.getManager().getRolloverStrategy()).isUseMax());
- assertEquals("append", false, getAppendProperty(rfa));
+ assertFalse("append", getAppendProperty(rfa));
assertEquals("bufferSize", 1000, rfa.getManager().getBufferSize());
- assertEquals("immediateFlush", false, rfa.getImmediateFlush());
+ assertFalse("immediateFlush", rfa.getImmediateFlush());
assertEquals("target/hadoop.log", rfa.getFileName());
- assertEquals(filePattern, rfa.getFilePattern());
+ assertEquals("target/hadoop.log.%i", rfa.getFilePattern());
final TriggeringPolicy triggeringPolicy = rfa.getTriggeringPolicy();
assertNotNull(triggeringPolicy);
assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy instanceof CompositeTriggeringPolicy);
@@ -241,20 +227,19 @@ private void testRollingFileAppender(final String configResource, final String n
configuration.stop();
}
- private void testDailyRollingFileAppender(final String configResource, final String name, final String filePattern)
- throws Exception {
+ private void testDailyRollingFileAppender(final String configResource) throws Exception {
final Configuration configuration = getConfiguration(configResource);
try {
- final Appender appender = configuration.getAppender(name);
+ final Appender appender = configuration.getAppender("DRFA");
assertNotNull(appender);
- assertEquals(name, appender.getName());
+ assertEquals("DRFA", appender.getName());
assertTrue(appender.getClass().getName(), appender instanceof RollingFileAppender);
final RollingFileAppender rfa = (RollingFileAppender) appender;
- assertEquals("append", false, getAppendProperty(rfa));
+ assertFalse("append", getAppendProperty(rfa));
assertEquals("bufferSize", 1000, rfa.getManager().getBufferSize());
- assertEquals("immediateFlush", false, rfa.getImmediateFlush());
+ assertFalse("immediateFlush", rfa.getImmediateFlush());
assertEquals("target/hadoop.log", rfa.getFileName());
- assertEquals(filePattern, rfa.getFilePattern());
+ assertEquals("target/hadoop.log%d{.dd-MM-yyyy}", rfa.getFilePattern());
final TriggeringPolicy triggeringPolicy = rfa.getTriggeringPolicy();
assertNotNull(triggeringPolicy);
assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy instanceof CompositeTriggeringPolicy);
@@ -275,8 +260,8 @@ private void testDailyRollingFileAppender(final String configResource, final Str
}
}
- private Layout> testFile(final String configResource) throws Exception {
- final Configuration configuration = getConfiguration(configResource);
+ private Layout> testFile() throws Exception {
+ final Configuration configuration = getConfiguration("config-1.2/log4j-file-SimpleLayout");
final FileAppender appender = configuration.getAppender("File");
assertNotNull(appender);
assertEquals("target/mylog.txt", appender.getFileName());
@@ -284,9 +269,9 @@ private Layout> testFile(final String configResource) throws Exception {
final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
assertNotNull(loggerConfig);
assertEquals(Level.DEBUG, loggerConfig.getLevel());
- assertEquals("append", false, getAppendProperty(appender));
+ assertFalse("append", getAppendProperty(appender));
assertEquals("bufferSize", 1000, appender.getManager().getBufferSize());
- assertEquals("immediateFlush", false, appender.getImmediateFlush());
+ assertFalse("immediateFlush", appender.getImmediateFlush());
configuration.start();
configuration.stop();
return appender.getLayout();
@@ -316,7 +301,7 @@ public void testConsoleSimpleLayout() throws Exception {
}
public void testFileSimpleLayout() throws Exception {
- final PatternLayout layout = (PatternLayout) testFile("config-1.2/log4j-file-SimpleLayout");
+ final PatternLayout layout = (PatternLayout) testFile();
assertEquals("%v1Level - %m%n", layout.getConversionPattern());
}
@@ -328,14 +313,11 @@ public void testNullAppender() throws Exception {
assertTrue(appender.getClass().getName(), appender instanceof NullAppender);
}
- private boolean getFollowProperty(final ConsoleAppender consoleAppender)
- throws Exception, NoSuchFieldException, IllegalAccessException {
- final CloseShieldOutputStream wrapperStream =
- (CloseShieldOutputStream) getOutputStream(consoleAppender.getManager());
- final Field delegateField = CloseShieldOutputStream.class.getDeclaredField("delegate");
- delegateField.setAccessible(true);
- final boolean follow = !System.out.equals(delegateField.get(wrapperStream));
- return follow;
+ private boolean getFollowProperty(final ConsoleAppender consoleAppender) throws Exception {
+ OutputStream outputStream = getOutputStream(consoleAppender.getManager());
+ String className = outputStream.getClass().getName();
+ return className.endsWith("ConsoleAppender$SystemErrStream")
+ || className.endsWith("ConsoleAppender$SystemOutStream");
}
private boolean getAppendProperty(final RollingFileAppender appender) throws Exception {
@@ -383,7 +365,7 @@ public void testDefaultValues() throws Exception {
final HtmlLayout htmlLayout = (HtmlLayout) testLayout(config, "HTMLLayout");
assertNotNull(htmlLayout);
assertEquals("title", "Log4J Log Messages", htmlLayout.getTitle());
- assertEquals("locationInfo", false, htmlLayout.isLocationInfo());
+ assertFalse("locationInfo", htmlLayout.isLocationInfo());
// PatternLayout
final PatternLayout patternLayout = (PatternLayout) testLayout(config, "PatternLayout");
assertNotNull(patternLayout);
@@ -403,7 +385,7 @@ public void testDefaultValues() throws Exception {
assertNotNull(consoleAppender);
assertEquals("target", Target.SYSTEM_OUT, consoleAppender.getTarget());
final boolean follow = getFollowProperty(consoleAppender);
- assertEquals("follow", false, follow);
+ assertFalse("follow", follow);
// DailyRollingFileAppender
final RollingFileAppender dailyRollingFileAppender = config.getAppender("DailyRollingFileAppender");
assertNotNull(dailyRollingFileAppender);
@@ -411,15 +393,15 @@ public void testDefaultValues() throws Exception {
"equivalent file pattern",
"target/dailyRollingFileAppender%d{.yyyy-MM-dd}",
dailyRollingFileAppender.getFilePattern());
- assertEquals("append", true, getAppendProperty(dailyRollingFileAppender));
+ assertTrue("append", getAppendProperty(dailyRollingFileAppender));
assertEquals("bufferSize", 8192, dailyRollingFileAppender.getManager().getBufferSize());
- assertEquals("immediateFlush", true, dailyRollingFileAppender.getImmediateFlush());
+ assertTrue("immediateFlush", dailyRollingFileAppender.getImmediateFlush());
// FileAppender
final FileAppender fileAppender = config.getAppender("FileAppender");
assertNotNull(fileAppender);
- assertEquals("append", true, getAppendProperty(fileAppender));
+ assertTrue("append", getAppendProperty(fileAppender));
assertEquals("bufferSize", 8192, fileAppender.getManager().getBufferSize());
- assertEquals("immediateFlush", true, fileAppender.getImmediateFlush());
+ assertTrue("immediateFlush", fileAppender.getImmediateFlush());
// RollingFileAppender
final RollingFileAppender rollingFileAppender = config.getAppender("RollingFileAppender");
assertNotNull(rollingFileAppender);
@@ -433,9 +415,9 @@ public void testDefaultValues() throws Exception {
final DefaultRolloverStrategy strategy =
(DefaultRolloverStrategy) rollingFileAppender.getManager().getRolloverStrategy();
assertEquals("maxBackupIndex", 1, strategy.getMaxIndex());
- assertEquals("append", true, getAppendProperty(rollingFileAppender));
+ assertTrue("append", getAppendProperty(rollingFileAppender));
assertEquals("bufferSize", 8192, rollingFileAppender.getManager().getBufferSize());
- assertEquals("immediateFlush", true, rollingFileAppender.getImmediateFlush());
+ assertTrue("immediateFlush", rollingFileAppender.getImmediateFlush());
config.start();
config.stop();
}
@@ -443,7 +425,7 @@ public void testDefaultValues() throws Exception {
/**
* Checks a hierarchy of filters.
*
- * @param filter
+ * @param filter A filter
* @return the number of filters
*/
private int checkFilters(final org.apache.logging.log4j.core.Filter filter) {
@@ -467,7 +449,7 @@ private int checkFilters(final org.apache.logging.log4j.core.Filter filter) {
/**
* Checks a hierarchy of filters.
*
- * @param filter
+ * @param filter A filter
* @return the number of filters
*/
private int checkFilters(final org.apache.log4j.spi.Filter filter) {
@@ -581,9 +563,9 @@ protected void testEnhancedRollingFileAppender(final Configuration configuration
appender = configuration.getAppender("DEFAULT_TIME");
assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender);
final RollingFileAppender defaultTime = (RollingFileAppender) appender;
- assertEquals("append", true, defaultTime.getManager().isAppend());
+ assertTrue("append", defaultTime.getManager().isAppend());
assertEquals("bufferSize", 8192, defaultTime.getManager().getBufferSize());
- assertEquals("immediateFlush", true, defaultTime.getImmediateFlush());
+ assertTrue("immediateFlush", defaultTime.getImmediateFlush());
assertEquals("fileName", "target/EnhancedRollingFileAppender/defaultTime.log", defaultTime.getFileName());
assertEquals(
"filePattern",
@@ -595,9 +577,9 @@ protected void testEnhancedRollingFileAppender(final Configuration configuration
appender = configuration.getAppender("DEFAULT_SIZE");
assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender);
final RollingFileAppender defaultSize = (RollingFileAppender) appender;
- assertEquals("append", true, defaultSize.getManager().isAppend());
+ assertTrue("append", defaultSize.getManager().isAppend());
assertEquals("bufferSize", 8192, defaultSize.getManager().getBufferSize());
- assertEquals("immediateFlush", true, defaultSize.getImmediateFlush());
+ assertTrue("immediateFlush", defaultSize.getImmediateFlush());
assertEquals("fileName", "target/EnhancedRollingFileAppender/defaultSize.log", defaultSize.getFileName());
assertEquals(
"filePattern", "target/EnhancedRollingFileAppender/defaultSize.%i.log", defaultSize.getFilePattern());
@@ -613,9 +595,9 @@ protected void testEnhancedRollingFileAppender(final Configuration configuration
appender = configuration.getAppender("TIME");
assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender);
final RollingFileAppender time = (RollingFileAppender) appender;
- assertEquals("append", false, time.getManager().isAppend());
+ assertFalse("append", time.getManager().isAppend());
assertEquals("bufferSize", 1000, time.getManager().getBufferSize());
- assertEquals("immediateFlush", false, time.getImmediateFlush());
+ assertFalse("immediateFlush", time.getImmediateFlush());
assertEquals("fileName", "target/EnhancedRollingFileAppender/time.log", time.getFileName());
assertEquals(
"filePattern", "target/EnhancedRollingFileAppender/time.%d{yyyy-MM-dd}.log", time.getFilePattern());
@@ -625,9 +607,9 @@ protected void testEnhancedRollingFileAppender(final Configuration configuration
appender = configuration.getAppender("SIZE");
assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender);
final RollingFileAppender size = (RollingFileAppender) appender;
- assertEquals("append", false, size.getManager().isAppend());
+ assertFalse("append", size.getManager().isAppend());
assertEquals("bufferSize", 1000, size.getManager().getBufferSize());
- assertEquals("immediateFlush", false, size.getImmediateFlush());
+ assertFalse("immediateFlush", size.getImmediateFlush());
assertEquals("fileName", "target/EnhancedRollingFileAppender/size.log", size.getFileName());
assertEquals("filePattern", "target/EnhancedRollingFileAppender/size.%i.log", size.getFilePattern());
policy = size.getTriggeringPolicy();
diff --git a/log4j-core-test/pom.xml b/log4j-core-test/pom.xml
index 56f7fd885f3..8c8cbc19bbd 100644
--- a/log4j-core-test/pom.xml
+++ b/log4j-core-test/pom.xml
@@ -242,13 +242,6 @@
test
-
-
- org.fusesource.jansi
- jansi
- test
-
-
javax.jms
diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
index 0cdc8b45407..89057c90c08 100644
--- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
+++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/Layouts.java
@@ -22,8 +22,6 @@
public interface Layouts {
interface Csv {}
- interface Jansi {}
-
interface Json {}
interface Xml {}
diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
index a299ed2b4c9..fbbe4172853 100644
--- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
+++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/categories/package-info.java
@@ -20,8 +20,10 @@
* integration tests, an appropriate category interface should be specified.
*/
@Export
-@Version("2.20.1")
+@Version("2.20.2")
+@BaselineIgnore("2.25.0")
package org.apache.logging.log4j.core.test.categories;
+import aQute.bnd.annotation.baseline.BaselineIgnore;
import org.osgi.annotation.bundle.Export;
import org.osgi.annotation.versioning.Version;
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
index 3088ca2bc1b..a44d064ab49 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiMessagesMain.java
@@ -30,7 +30,7 @@
*
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
*
*/
public class ConsoleAppenderAnsiMessagesMain {
@@ -38,8 +38,7 @@ public class ConsoleAppenderAnsiMessagesMain {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiMessagesMain.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- try (final LoggerContext ctx = Configurator.initialize(
+ try (final LoggerContext ignored = Configurator.initialize(
ConsoleAppenderAnsiMessagesMain.class.getName(), "target/test-classes/log4j2-console.xml")) {
LOG.fatal("\u001b[1;35mFatal message.\u001b[0m");
LOG.error("\u001b[1;31mError message.\u001b[0m");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
index dffc5b42893..bd8491c6667 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira180Main.java
@@ -23,13 +23,13 @@
import org.apache.logging.log4j.core.config.Configurator;
/**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-180
+ * Tests LOG4J2-180
*
* Running from a Windows command line from the root of the project:
*
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main log4j-core/target/test-classes/log4j2-180.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main log4j-core/target/test-classes/log4j2-180.xml
*
*/
public class ConsoleAppenderAnsiStyleJira180Main {
@@ -37,10 +37,8 @@ public class ConsoleAppenderAnsiStyleJira180Main {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira180Main.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
final String config = args.length == 0 ? "target/test-classes/log4j2-180.xml" : args[0];
- try (final LoggerContext ctx =
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
LOG.fatal("Fatal message.");
LOG.error("Error message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
index 0f2844abe77..65a4ed1ee79 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira272Main.java
@@ -23,12 +23,12 @@
import org.apache.logging.log4j.core.config.Configurator;
/**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-272
+ * Tests LOG4J2-272
*
* Running from a Windows command line from the root of the project:
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main log4j-core/target/test-classes/log4j2-272.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main log4j-core/target/test-classes/log4j2-272.xml
*
*/
public class ConsoleAppenderAnsiStyleJira272Main {
@@ -36,10 +36,8 @@ public class ConsoleAppenderAnsiStyleJira272Main {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira272Main.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
final String config = args.length == 0 ? "target/test-classes/log4j2-272.xml" : args[0];
- try (final LoggerContext ctx =
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
LOG.fatal("Fatal message.");
LOG.error("Error message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
index 48681a85f71..957a58e9bf6 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleJira319Main.java
@@ -23,13 +23,13 @@
import org.apache.logging.log4j.core.config.Configurator;
/**
- * Tests https://issues.apache.org/jira/browse/LOG4J2-319
+ * Tests LOG4J2-319
*
* Running from a Windows command line from the root of the project:
*
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main log4j-core/target/test-classes/log4j2-319.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main log4j-core/target/test-classes/log4j2-319.xml
*
*/
public class ConsoleAppenderAnsiStyleJira319Main {
@@ -37,10 +37,8 @@ public class ConsoleAppenderAnsiStyleJira319Main {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira319Main.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
final String config = args.length == 0 ? "target/test-classes/log4j2-319.xml" : args[0];
- try (final LoggerContext ctx =
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
LOG.fatal("Fatal message.");
LOG.error("Error message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
index 87730d9a5a4..2ef1c52c9fa 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleLayoutMain.java
@@ -35,7 +35,7 @@
*
* or:
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
*
*
*/
@@ -54,11 +54,9 @@ public void test() {
}
public void test(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
final String config =
args == null || args.length == 0 ? "target/test-classes/log4j2-console-style-ansi.xml" : args[0];
- try (final LoggerContext ctx =
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
final Logger logger = LogManager.getLogger(ConsoleAppenderAnsiStyleLayoutMain.class);
logger.fatal("Fatal message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
index 9088b75d47a..5cdc81ee452 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiStyleNameLayoutMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderAnsiStyleNameLayoutMain {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleNameLayoutMain.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- try (final LoggerContext ctx = Configurator.initialize(
+ try (final LoggerContext ignored = Configurator.initialize(
ConsoleAppenderAnsiMessagesMain.class.getName(),
"target/test-classes/log4j2-console-style-name-ansi.xml")) {
LOG.fatal("Fatal message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
similarity index 78%
rename from log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java
rename to log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
index d681e02c754..ee062add98e 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiXExceptionMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderAnsiXExceptionMain.java
@@ -22,9 +22,7 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configurator;
-import org.apache.logging.log4j.core.test.categories.Layouts;
import org.junit.Test;
-import org.junit.experimental.categories.Category;
/**
* Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
@@ -34,21 +32,20 @@
*
*
*
- * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain test
+ * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiXExceptionMain test
*
*
* or, on Windows:
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiXExceptionMain log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
*
*
*/
-@Category(Layouts.Jansi.class)
-public class ConsoleAppenderJAnsiXExceptionMain {
+public class ConsoleAppenderAnsiXExceptionMain {
public static void main(final String[] args) {
- new ConsoleAppenderJAnsiXExceptionMain().test(args);
+ new ConsoleAppenderAnsiXExceptionMain().test(args);
}
/**
@@ -60,12 +57,10 @@ public void test() {
}
public void test(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
final String config =
args == null || args.length == 0 ? "target/test-classes/log4j2-console-xex-ansi.xml" : args[0];
final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
- final Logger logger = LogManager.getLogger(ConsoleAppenderJAnsiXExceptionMain.class);
+ final Logger logger = LogManager.getLogger(ConsoleAppenderAnsiXExceptionMain.class);
try {
Files.getFileStore(Paths.get("?BOGUS?"));
} catch (final Exception e) {
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
index 8553eb3f1d0..2432df32c93 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
@@ -31,7 +31,7 @@
*
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
*
*/
public class ConsoleAppenderDefaultSuppressedThrowable {
@@ -41,12 +41,11 @@ public class ConsoleAppenderDefaultSuppressedThrowable {
public static void main(final String[] args) {
final String config =
args.length == 0 ? "target/test-classes/log4j2-console-default-suppressed-throwable.xml" : args[0];
- test(args, config);
+ test(config);
}
- static void test(final String[] args, final String config) {
- // System.out.println(System.getProperty("java.class.path"));
- try (final LoggerContext ctx =
+ static void test(final String config) {
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderDefaultSuppressedThrowable.class.getName(), config)) {
final IOException ioEx = new IOException("test suppressed");
ioEx.addSuppressed(new IOException("test suppressed 1", new IOException("test 1")));
@@ -55,8 +54,6 @@ static void test(final String[] args, final String config) {
ioEx.addSuppressed(new IOException("test suppressed 2", ioEx2));
final IOException e = new IOException("test", ioEx);
LOG.error("Error message {}, suppressed?", "Hi", e);
- System.out.println("printStackTrace");
- e.printStackTrace();
}
}
}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
index 7a1b7cf616e..d9b5eeba270 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutDefaultMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderHighlightLayoutDefaultMain {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutDefaultMain.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- try (final LoggerContext ctx = Configurator.initialize(
+ try (final LoggerContext ignored = Configurator.initialize(
ConsoleAppenderAnsiMessagesMain.class.getName(),
"target/test-classes/log4j2-console-highlight-default.xml")) {
LOG.fatal("Fatal message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
index dbb6958ea25..ad86c245707 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderHighlightLayoutMain.java
@@ -31,8 +31,7 @@ public class ConsoleAppenderHighlightLayoutMain {
private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutMain.class);
public static void main(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- try (final LoggerContext ctx = Configurator.initialize(
+ try (final LoggerContext ignored = Configurator.initialize(
ConsoleAppenderAnsiMessagesMain.class.getName(), "target/test-classes/log4j2-console-highlight.xml")) {
LOG.fatal("Fatal message.");
LOG.error("Error message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
deleted file mode 100644
index 56cce35a74b..00000000000
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJAnsiMessageMain.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.logging.log4j.core.appender;
-
-import static org.fusesource.jansi.Ansi.Color.CYAN;
-import static org.fusesource.jansi.Ansi.Color.RED;
-import static org.fusesource.jansi.Ansi.ansi;
-
-import java.util.Map.Entry;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.Configurator;
-import org.apache.logging.log4j.core.test.categories.Layouts;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
-
-/**
- * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
- * of the log entry (time stamp for example) is in the default color for that console.
- *
- * Running from a Windows command line from the root of the project:
- *
- *
- *
- * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain test
- *
- *
- * or, on Windows:
- *
- *
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain log4j-core/src/test/resources/log4j2-console-msg-ansi.xml
- *
- *
- */
-@Category(Layouts.Jansi.class)
-public class ConsoleAppenderJAnsiMessageMain {
-
- public static void main(final String[] args) {
- new ConsoleAppenderJAnsiMessageMain().test(args);
- }
-
- /**
- * This is a @Test method to make it easy to run from a command line with {@code mvn -Dtest=FQCN test}
- */
- @Test
- @ResourceLock(Resources.SYSTEM_PROPERTIES)
- public void test() {
- test(null);
- }
-
- public void test(final String[] args) {
- System.setProperty("log4j.skipJansi", "false"); // LOG4J2-2087: explicitly enable
- // System.out.println(System.getProperty("java.class.path"));
- final String config =
- args == null || args.length == 0 ? "target/test-classes/log4j2-console-msg-ansi.xml" : args[0];
- try (final LoggerContext ctx =
- Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
- final Logger logger = LogManager.getLogger(ConsoleAppenderJAnsiMessageMain.class);
- logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" World").reset());
- // JAnsi format:
- // logger.info("@|red Hello|@ @|cyan World|@");
- for (final Entry entry : System.getProperties().entrySet()) {
- logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
- }
- }
- }
-}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
index b75e3e03259..b1177acdd25 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderJira1002ShortThrowableLayoutMain.java
@@ -21,7 +21,7 @@
*/
public class ConsoleAppenderJira1002ShortThrowableLayoutMain {
- public static void main(final String[] args) {
- ConsoleAppenderNoAnsiStyleLayoutMain.test(args, "target/test-classes/log4j2-1002.xml");
+ public static void main() {
+ ConsoleAppenderNoAnsiStyleLayoutMain.test("target/test-classes/log4j2-1002.xml");
}
}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
index 1c35103862e..1165fc6a609 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderNoAnsiStyleLayoutMain.java
@@ -30,7 +30,7 @@
*
*
*
- * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.14\jansi-1.14.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
*
*/
public class ConsoleAppenderNoAnsiStyleLayoutMain {
@@ -43,12 +43,11 @@ private static void logThrowableFromMethod() {
public static void main(final String[] args) {
final String config = args.length == 0 ? "target/test-classes/log4j2-console-style-no-ansi.xml" : args[0];
- test(args, config);
+ test(config);
}
- static void test(final String[] args, final String config) {
- // System.out.println(System.getProperty("java.class.path"));
- try (final LoggerContext ctx =
+ static void test(final String config) {
+ try (final LoggerContext ignored =
Configurator.initialize(ConsoleAppenderNoAnsiStyleLayoutMain.class.getName(), config)) {
LOG.fatal("Fatal message.");
LOG.error("Error message.");
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
deleted file mode 100644
index 8bdd3e13efe..00000000000
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/JansiConsoleAppenderJira965.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.logging.log4j.core.appender;
-
-import org.slf4j.LoggerFactory;
-
-public class JansiConsoleAppenderJira965 {
-
- public static void main(final String[] args) {
- System.out.println("Able to print on Windows");
- LoggerFactory.getLogger(JansiConsoleAppenderJira965.class);
- System.out.println("Unable to print on Windows");
- }
-}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
index 4719db85637..10dea802505 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
@@ -16,26 +16,27 @@
*/
package org.apache.logging.log4j.core.impl;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.apache.logging.log4j.util.Strings.toRootUpperCase;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import org.apache.logging.log4j.core.pattern.AnsiEscape;
import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
import org.apache.logging.log4j.core.pattern.TextRenderer;
import org.apache.logging.log4j.util.Strings;
-import org.fusesource.jansi.AnsiRenderer.Code;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@code ThrowableFormatOptions}.
*/
-public final class ThrowableFormatOptionsTest {
+final class ThrowableFormatOptionsTest {
/**
* Runs a given test comparing against the expected values.
@@ -71,7 +72,7 @@ private static ThrowableFormatOptions test(
* Test {@code %throwable} with null options.
*/
@Test
- public void testNull() {
+ void testNull() {
test(null, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -79,7 +80,7 @@ public void testNull() {
* Test {@code %throwable}
*/
@Test
- public void testEmpty() {
+ void testEmpty() {
test(new String[] {}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -87,7 +88,7 @@ public void testEmpty() {
* Test {@code %throwable{} } with null option value.
*/
@Test
- public void testOneNullElement() {
+ void testOneNullElement() {
test(new String[] {null}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -95,7 +96,7 @@ public void testOneNullElement() {
* Test {@code %throwable{} }
*/
@Test
- public void testOneEmptyElement() {
+ void testOneEmptyElement() {
test(new String[] {""}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -103,7 +104,7 @@ public void testOneEmptyElement() {
* Test {@code %throwable{full} }
*/
@Test
- public void testFull() {
+ void testFull() {
test(new String[] {"full"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -111,7 +112,7 @@ public void testFull() {
* Test {@code %throwable{full}{ansi} }
*/
@Test
- public void testFullAnsi() {
+ void testFullAnsi() {
final ThrowableFormatOptions tfo =
test(new String[] {"full", "ansi"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
testFullAnsiEmptyConfig(tfo);
@@ -121,7 +122,7 @@ public void testFullAnsi() {
* Test {@code %throwable{full}{ansi()} }
*/
@Test
- public void testFullAnsiEmptyConfig() {
+ void testFullAnsiEmptyConfig() {
final ThrowableFormatOptions tfo =
test(new String[] {"full", "ansi()"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
testFullAnsiEmptyConfig(tfo);
@@ -130,34 +131,34 @@ public void testFullAnsiEmptyConfig() {
private void testFullAnsiEmptyConfig(final ThrowableFormatOptions tfo) {
final TextRenderer textRenderer = tfo.getTextRenderer();
assertNotNull(textRenderer);
- assertTrue(textRenderer instanceof JAnsiTextRenderer);
- final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
- final Map styleMap = jansiRenderer.getStyleMap();
+ assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+ final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) textRenderer;
+ final Map styleMap = ansiRenderer.getStyleMap();
// We have defaults
assertFalse(styleMap.isEmpty());
- assertNotNull(styleMap.get("Name"));
+ assertNotNull(styleMap.get(toRootUpperCase("Name")));
}
/**
* Test {@code %throwable{full}{ansi(Warning=red))} }
*/
@Test
- public void testFullAnsiWithCustomStyle() {
+ void testFullAnsiWithCustomStyle() {
final ThrowableFormatOptions tfo =
test(new String[] {"full", "ansi(Warning=red)"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
final TextRenderer textRenderer = tfo.getTextRenderer();
assertNotNull(textRenderer);
- assertTrue(textRenderer instanceof JAnsiTextRenderer);
- final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
- final Map styleMap = jansiRenderer.getStyleMap();
- assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
+ assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+ final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) textRenderer;
+ final Map styleMap = ansiRenderer.getStyleMap();
+ assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
}
/**
* Test {@code %throwable{full}{ansi(Warning=red Key=blue Value=cyan))} }
*/
@Test
- public void testFullAnsiWithCustomStyles() {
+ void testFullAnsiWithCustomStyles() {
final ThrowableFormatOptions tfo = test(
new String[] {"full", "ansi(Warning=red Key=blue Value=cyan)"},
Integer.MAX_VALUE,
@@ -165,19 +166,19 @@ public void testFullAnsiWithCustomStyles() {
null);
final TextRenderer textRenderer = tfo.getTextRenderer();
assertNotNull(textRenderer);
- assertTrue(textRenderer instanceof JAnsiTextRenderer);
- final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
- final Map styleMap = jansiRenderer.getStyleMap();
- assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
- assertArrayEquals(new Code[] {Code.BLUE}, styleMap.get("Key"));
- assertArrayEquals(new Code[] {Code.CYAN}, styleMap.get("Value"));
+ assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+ final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) textRenderer;
+ final Map styleMap = ansiRenderer.getStyleMap();
+ assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
+ assertThat(styleMap.get(toRootUpperCase("Key"))).isEqualTo(AnsiEscape.createSequence("BLUE"));
+ assertThat(styleMap.get(toRootUpperCase("Value"))).isEqualTo(AnsiEscape.createSequence("CYAN"));
}
/**
* Test {@code %throwable{full}{ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)} }
*/
@Test
- public void testFullAnsiWithCustomComplexStyles() {
+ void testFullAnsiWithCustomComplexStyles() {
final ThrowableFormatOptions tfo = test(
new String[] {"full", "ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)"},
Integer.MAX_VALUE,
@@ -185,19 +186,20 @@ public void testFullAnsiWithCustomComplexStyles() {
null);
final TextRenderer textRenderer = tfo.getTextRenderer();
assertNotNull(textRenderer);
- assertTrue(textRenderer instanceof JAnsiTextRenderer);
- final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
- final Map styleMap = jansiRenderer.getStyleMap();
- assertArrayEquals(new Code[] {Code.RED}, styleMap.get("Warning"));
- assertArrayEquals(new Code[] {Code.BLUE, Code.BG_RED}, styleMap.get("Key"));
- assertArrayEquals(new Code[] {Code.CYAN, Code.BG_BLACK, Code.UNDERLINE}, styleMap.get("Value"));
+ assertInstanceOf(JAnsiTextRenderer.class, textRenderer);
+ final JAnsiTextRenderer ansiRenderer = (JAnsiTextRenderer) textRenderer;
+ final Map styleMap = ansiRenderer.getStyleMap();
+ assertThat(styleMap.get(toRootUpperCase("Warning"))).isEqualTo(AnsiEscape.createSequence("RED"));
+ assertThat(styleMap.get(toRootUpperCase("Key"))).isEqualTo(AnsiEscape.createSequence("BLUE", "BG_RED"));
+ assertThat(styleMap.get(toRootUpperCase("Value")))
+ .isEqualTo(AnsiEscape.createSequence("CYAN", "BG_BLACK", "UNDERLINE"));
}
/**
* Test {@code %throwable{none} }
*/
@Test
- public void testNone() {
+ void testNone() {
test(new String[] {"none"}, 0, Strings.LINE_SEPARATOR, null);
}
@@ -205,7 +207,7 @@ public void testNone() {
* Test {@code %throwable{short} }
*/
@Test
- public void testShort() {
+ void testShort() {
test(new String[] {"short"}, 2, Strings.LINE_SEPARATOR, null);
}
@@ -213,7 +215,7 @@ public void testShort() {
* Test {@code %throwable{10} }
*/
@Test
- public void testDepth() {
+ void testDepth() {
test(new String[] {"10"}, 10, Strings.LINE_SEPARATOR, null);
}
@@ -221,7 +223,7 @@ public void testDepth() {
* Test {@code %throwable{separator(|)} }
*/
@Test
- public void testSeparator() {
+ void testSeparator() {
test(new String[] {"separator(|)"}, Integer.MAX_VALUE, "|", null);
}
@@ -229,7 +231,7 @@ public void testSeparator() {
* Test {@code %throwable{separator()} }
*/
@Test
- public void testSeparatorAsEmpty() {
+ void testSeparatorAsEmpty() {
test(new String[] {"separator()"}, Integer.MAX_VALUE, Strings.EMPTY, null);
}
@@ -237,7 +239,7 @@ public void testSeparatorAsEmpty() {
* Test {@code %throwable{separator(\n)} }
*/
@Test
- public void testSeparatorAsDefaultLineSeparator() {
+ void testSeparatorAsDefaultLineSeparator() {
test(
new String[] {"separator(" + Strings.LINE_SEPARATOR + ')'},
Integer.MAX_VALUE,
@@ -249,7 +251,7 @@ public void testSeparatorAsDefaultLineSeparator() {
* Test {@code %throwable{separator( | )} }
*/
@Test
- public void testSeparatorAsMultipleCharacters() {
+ void testSeparatorAsMultipleCharacters() {
test(new String[] {"separator( | )"}, Integer.MAX_VALUE, " | ", null);
}
@@ -257,7 +259,7 @@ public void testSeparatorAsMultipleCharacters() {
* Test {@code %throwable{full}{separator(|)} }
*/
@Test
- public void testFullAndSeparator() {
+ void testFullAndSeparator() {
test(new String[] {"full", "separator(|)"}, Integer.MAX_VALUE, "|", null);
}
@@ -265,7 +267,7 @@ public void testFullAndSeparator() {
* Test {@code %throwable{full}{filters(org.junit)}{separator(|)} }
*/
@Test
- public void testFullAndFiltersAndSeparator() {
+ void testFullAndFiltersAndSeparator() {
test(
new String[] {"full", "filters(org.junit)", "separator(|)"},
Integer.MAX_VALUE,
@@ -277,7 +279,7 @@ public void testFullAndFiltersAndSeparator() {
* Test {@code %throwable{none}{separator(|)} }
*/
@Test
- public void testNoneAndSeparator() {
+ void testNoneAndSeparator() {
test(new String[] {"none", "separator(|)"}, 0, "|", null);
}
@@ -285,7 +287,7 @@ public void testNoneAndSeparator() {
* Test {@code %throwable{short}{separator(|)} }
*/
@Test
- public void testShortAndSeparator() {
+ void testShortAndSeparator() {
test(new String[] {"short", "separator(|)"}, 2, "|", null);
}
@@ -293,7 +295,7 @@ public void testShortAndSeparator() {
* Test {@code %throwable{10}{separator(|)} }
*/
@Test
- public void testDepthAndSeparator() {
+ void testDepthAndSeparator() {
test(new String[] {"10", "separator(|)"}, 10, "|", null);
}
@@ -301,7 +303,7 @@ public void testDepthAndSeparator() {
* Test {@code %throwable{filters(packages)} }
*/
@Test
- public void testFilters() {
+ void testFilters() {
test(
new String[] {"filters(packages)"},
Integer.MAX_VALUE,
@@ -313,7 +315,7 @@ public void testFilters() {
* Test {@code %throwable{filters()} }
*/
@Test
- public void testFiltersAsEmpty() {
+ void testFiltersAsEmpty() {
test(new String[] {"filters()"}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
}
@@ -321,7 +323,7 @@ public void testFiltersAsEmpty() {
* Test {@code %throwable{filters(package1,package2)} }
*/
@Test
- public void testFiltersAsMultiplePackages() {
+ void testFiltersAsMultiplePackages() {
test(
new String[] {"filters(package1,package2)"},
Integer.MAX_VALUE,
@@ -333,7 +335,7 @@ public void testFiltersAsMultiplePackages() {
* Test {@code %throwable{full}{filters(packages)} }
*/
@Test
- public void testFullAndFilters() {
+ void testFullAndFilters() {
test(
new String[] {"full", "filters(packages)"},
Integer.MAX_VALUE,
@@ -345,7 +347,7 @@ public void testFullAndFilters() {
* Test {@code %throwable{none}{filters(packages)} }
*/
@Test
- public void testNoneAndFilters() {
+ void testNoneAndFilters() {
test(
new String[] {"none", "filters(packages)"},
0,
@@ -357,7 +359,7 @@ public void testNoneAndFilters() {
* Test {@code %throwable{short}{filters(packages)} }
*/
@Test
- public void testShortAndFilters() {
+ void testShortAndFilters() {
test(
new String[] {"short", "filters(packages)"},
2,
@@ -369,7 +371,7 @@ public void testShortAndFilters() {
* Test {@code %throwable{10}{filters(packages)} }
*/
@Test
- public void testDepthAndFilters() {
+ void testDepthAndFilters() {
test(
new String[] {"10", "filters(packages)"},
10,
@@ -381,7 +383,7 @@ public void testDepthAndFilters() {
* Test {@code %throwable{full}{separator(|)}{filters(packages)} }
*/
@Test
- public void testFullAndSeparatorAndFilter() {
+ void testFullAndSeparatorAndFilter() {
test(
new String[] {"full", "separator(|)", "filters(packages)"},
Integer.MAX_VALUE,
@@ -393,7 +395,7 @@ public void testFullAndSeparatorAndFilter() {
* Test {@code %throwable{full}{separator(|)}{filters(package1,package2)} }
*/
@Test
- public void testFullAndSeparatorAndFilters() {
+ void testFullAndSeparatorAndFilters() {
test(
new String[] {"full", "separator(|)", "filters(package1,package2)"},
Integer.MAX_VALUE,
@@ -405,7 +407,7 @@ public void testFullAndSeparatorAndFilters() {
* Test {@code %throwable{none}{separator(|)}{filters(packages)} }
*/
@Test
- public void testNoneAndSeparatorAndFilters() {
+ void testNoneAndSeparatorAndFilters() {
test(new String[] {"none", "separator(|)", "filters(packages)"}, 0, "|", Collections.singletonList("packages"));
}
@@ -413,7 +415,7 @@ public void testNoneAndSeparatorAndFilters() {
* Test {@code %throwable{short}{separator(|)}{filters(packages)} }
*/
@Test
- public void testShortAndSeparatorAndFilters() {
+ void testShortAndSeparatorAndFilters() {
test(
new String[] {"short", "separator(|)", "filters(packages)"},
2,
@@ -425,7 +427,7 @@ public void testShortAndSeparatorAndFilters() {
* Test {@code %throwable{10}{separator(|)}{filters(packages)} }
*/
@Test
- public void testDepthAndSeparatorAndFilters() {
+ void testDepthAndSeparatorAndFilters() {
test(new String[] {"10", "separator(|)", "filters(packages)"}, 10, "|", Collections.singletonList("packages"));
}
@@ -433,7 +435,7 @@ public void testDepthAndSeparatorAndFilters() {
* Test {@code %throwable{full,filters(packages)} }
*/
@Test
- public void testSingleOptionFullAndFilters() {
+ void testSingleOptionFullAndFilters() {
test(
new String[] {"full,filters(packages)"},
Integer.MAX_VALUE,
@@ -445,7 +447,7 @@ public void testSingleOptionFullAndFilters() {
* Test {@code %throwable{none,filters(packages)} }
*/
@Test
- public void testSingleOptionNoneAndFilters() {
+ void testSingleOptionNoneAndFilters() {
test(new String[] {"none,filters(packages)"}, 0, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
}
@@ -453,7 +455,7 @@ public void testSingleOptionNoneAndFilters() {
* Test {@code %throwable{short,filters(packages)} }
*/
@Test
- public void testSingleOptionShortAndFilters() {
+ void testSingleOptionShortAndFilters() {
test(
new String[] {"short,filters(packages)"},
2,
@@ -465,7 +467,7 @@ public void testSingleOptionShortAndFilters() {
* Test {@code %throwable{none,filters(packages)} }
*/
@Test
- public void testSingleOptionDepthAndFilters() {
+ void testSingleOptionDepthAndFilters() {
test(new String[] {"10,filters(packages)"}, 10, Strings.LINE_SEPARATOR, Collections.singletonList("packages"));
}
@@ -473,7 +475,7 @@ public void testSingleOptionDepthAndFilters() {
* Test {@code %throwable{full,filters(package1,package2)} }
*/
@Test
- public void testSingleOptionFullAndMultipleFilters() {
+ void testSingleOptionFullAndMultipleFilters() {
test(
new String[] {"full,filters(package1,package2)"},
Integer.MAX_VALUE,
@@ -485,7 +487,7 @@ public void testSingleOptionFullAndMultipleFilters() {
* Test {@code %throwable{none,filters(package1,package2)} }
*/
@Test
- public void testSingleOptionNoneAndMultipleFilters() {
+ void testSingleOptionNoneAndMultipleFilters() {
test(
new String[] {"none,filters(package1,package2)"},
0,
@@ -497,7 +499,7 @@ public void testSingleOptionNoneAndMultipleFilters() {
* Test {@code %throwable{short,filters(package1,package2)} }
*/
@Test
- public void testSingleOptionShortAndMultipleFilters() {
+ void testSingleOptionShortAndMultipleFilters() {
test(
new String[] {"short,filters(package1,package2)"},
2,
@@ -509,7 +511,7 @@ public void testSingleOptionShortAndMultipleFilters() {
* Test {@code %throwable{none,filters(package1,package2)} }
*/
@Test
- public void testSingleOptionDepthAndMultipleFilters() {
+ void testSingleOptionDepthAndMultipleFilters() {
test(
new String[] {"10,filters(package1,package2)"},
10,
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
new file mode 100644
index 00000000000..0595f68533d
--- /dev/null
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/JAnsiTextRendererTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.logging.log4j.core.pattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.presentation.HexadecimalRepresentation.HEXA_REPRESENTATION;
+
+import java.util.Collections;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class JAnsiTextRendererTest {
+
+ public static Stream testRendering() {
+ return Stream.of(
+ // Use style names
+ Arguments.of(
+ "KeyStyle=white ValueStyle=cyan,bold",
+ "@|KeyStyle key|@ = @|ValueStyle some value|@",
+ "\u001b[37mkey\u001b[m = \u001b[36;1msome value\u001b[m"),
+ // Use AnsiEscape codes directly
+ Arguments.of(
+ "",
+ "@|white key|@ = @|cyan,bold some value|@",
+ "\u001b[37mkey\u001b[m = \u001b[36;1msome value\u001b[m"),
+ // Return broken escapes as is
+ Arguments.of("", "Hello @|crazy|@ world!", "Hello @|crazy|@ world!"),
+ Arguments.of("", "Hello @|world!", "Hello @|world!"));
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void testRendering(final String format, final String text, final String expected) {
+ final JAnsiTextRenderer renderer = new JAnsiTextRenderer(new String[] {"ansi", format}, Collections.emptyMap());
+ final StringBuilder actual = new StringBuilder();
+ renderer.render(new StringBuilder(text), actual);
+ assertThat(actual.toString())
+ .as("Rendering text '%s'", text)
+ .withRepresentation(HEXA_REPRESENTATION)
+ .isEqualTo(expected);
+ }
+}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
similarity index 94%
rename from log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java
rename to log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
index 294355a173f..51278a04d6e 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageJansiConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageAnsiConverterTest.java
@@ -31,7 +31,7 @@
import org.junit.jupiter.api.Test;
@LoggerContextSource("log4j-message-ansi.xml")
-public class MessageJansiConverterTest {
+public class MessageAnsiConverterTest {
private static final String EXPECTED =
"\u001B[31;1mWarning!\u001B[m Pants on \u001B[31mfire!\u001B[m" + Strings.LINE_SEPARATOR;
@@ -47,7 +47,7 @@ public void setUp(final LoggerContext context, @Named("List") final ListAppender
@Test
public void testReplacement() {
- // See org.fusesource.jansi.AnsiRenderer
+ // See https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html
logger.error("@|red,bold Warning!|@ Pants on @|red fire!|@");
final List msgs = app.getMessages();
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
index 71fb6fbc77b..06ab681fedd 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/MessageStyledConverterTest.java
@@ -47,7 +47,7 @@ public void setUp(final LoggerContext context, @Named("List") final ListAppender
@Test
public void testReplacement() {
- // See org.fusesource.jansi.AnsiRenderer
+ // See https://www.javadoc.io/doc/org.jline/jline/latest/org/jline/jansi/AnsiRenderer.html
logger.error("@|WarningStyle Warning!|@ Pants on @|WarningStyle fire!|@");
final List msgs = app.getMessages();
diff --git a/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml b/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml
deleted file mode 100644
index d30b0fb406b..00000000000
--- a/log4j-core-test/src/test/resources/log4j2-console-msg-ansi.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index 1e35ebce729..f5693dc2e92 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -66,7 +66,6 @@
org.apache.commons.csv;resolution:=optional,
org.apache.kafka.*;resolution:=optional,
org.codehaus.stax2;resolution:=optional,
- org.fusesource.jansi;resolution:=optional,
org.jctools.*;resolution:=optional,
org.zeromq;resolution:=optional,
javax.lang.model.*;resolution:=optional,
@@ -97,7 +96,6 @@
java.management;transitive=false;static=true,
java.naming;transitive=false,
org.apache.commons.csv;transitive=false,
- org.fusesource.jansi;transitive=false,
org.jspecify;transitive=false,
org.zeromq.jeromq;transitive=false,
@@ -194,12 +192,6 @@
jackson-dataformat-yaml
true
-
-
- org.fusesource.jansi
- jansi
- true
-
org.jctools
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
index 986c82863f3..1b1bf5e2bdb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
@@ -20,10 +20,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.PrintStream;
import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Constructor;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.logging.log4j.core.Appender;
@@ -35,12 +32,8 @@
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
-import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.util.Booleans;
import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
-import org.apache.logging.log4j.core.util.Loader;
-import org.apache.logging.log4j.core.util.Throwables;
-import org.apache.logging.log4j.util.Chars;
import org.apache.logging.log4j.util.PropertiesUtil;
/**
@@ -61,8 +54,7 @@
public final class ConsoleAppender extends AbstractOutputStreamAppender {
public static final String PLUGIN_NAME = "Console";
- private static final String JANSI_CLASS = "org.fusesource.jansi.WindowsAnsiOutputStream";
- private static ConsoleManagerFactory factory = new ConsoleManagerFactory();
+ private static final ConsoleManagerFactory factory = new ConsoleManagerFactory();
private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
private static final AtomicInteger COUNT = new AtomicInteger();
@@ -116,10 +108,10 @@ private ConsoleAppender(
*
* @param layout The layout to use (required).
* @param filter The Filter or null.
- * @param targetStr The target ("SYSTEM_OUT" or "SYSTEM_ERR"). The default is "SYSTEM_OUT".
+ * @param target The target ("SYSTEM_OUT" or "SYSTEM_ERR"). The default is "SYSTEM_OUT".
* @param name The name of the Appender (required).
* @param follow If true will follow changes to the underlying output stream.
- * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they
+ * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they
* are propagated to the caller.
* @return The ConsoleAppender.
* @deprecated Deprecated in 2.7; use {@link #newBuilder()}.
@@ -128,22 +120,18 @@ private ConsoleAppender(
public static ConsoleAppender createAppender(
Layout extends Serializable> layout,
final Filter filter,
- final String targetStr,
+ final String target,
final String name,
final String follow,
- final String ignore) {
- if (name == null) {
- LOGGER.error("No name provided for ConsoleAppender");
- return null;
- }
- if (layout == null) {
- layout = PatternLayout.createDefaultLayout();
- }
- final boolean isFollow = Boolean.parseBoolean(follow);
- final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
- final Target target = targetStr == null ? DEFAULT_TARGET : Target.valueOf(targetStr);
- return new ConsoleAppender(
- name, layout, filter, getManager(target, isFollow, false, layout), ignoreExceptions, target, null);
+ final String ignoreExceptions) {
+ return newBuilder()
+ .setLayout(layout)
+ .setFilter(filter)
+ .setTarget(target == null ? DEFAULT_TARGET : Target.valueOf(target))
+ .setName(name)
+ .setFollow(Boolean.parseBoolean(follow))
+ .setIgnoreExceptions(Booleans.parseBoolean(ignoreExceptions, true))
+ .build();
}
/**
@@ -171,21 +159,15 @@ public static ConsoleAppender createAppender(
final boolean follow,
final boolean direct,
final boolean ignoreExceptions) {
- // @formatter:on
- if (name == null) {
- LOGGER.error("No name provided for ConsoleAppender");
- return null;
- }
- if (layout == null) {
- layout = PatternLayout.createDefaultLayout();
- }
- target = target == null ? Target.SYSTEM_OUT : target;
- if (follow && direct) {
- LOGGER.error("Cannot use both follow and direct on ConsoleAppender");
- return null;
- }
- return new ConsoleAppender(
- name, layout, filter, getManager(target, follow, direct, layout), ignoreExceptions, target, null);
+ return newBuilder()
+ .setLayout(layout)
+ .setFilter(filter)
+ .setTarget(target)
+ .setName(name)
+ .setFollow(follow)
+ .setDirect(direct)
+ .setIgnoreExceptions(ignoreExceptions)
+ .build();
}
public static ConsoleAppender createDefaultAppenderForLayout(final Layout extends Serializable> layout) {
@@ -194,7 +176,7 @@ public static ConsoleAppender createDefaultAppenderForLayout(final Layout exte
"DefaultConsole-" + COUNT.incrementAndGet(),
layout,
null,
- getDefaultManager(DEFAULT_TARGET, false, false, layout),
+ getDefaultManager(layout),
true,
DEFAULT_TARGET,
null);
@@ -242,85 +224,42 @@ public ConsoleAppender build() {
if (!isValid()) {
return null;
}
- if (follow && direct) {
- throw new IllegalArgumentException(
- "Cannot use both follow and direct on ConsoleAppender '" + getName() + "'");
+ if (direct && follow) {
+ LOGGER.error("Cannot use both `direct` and `follow` on ConsoleAppender.");
+ return null;
}
final Layout extends Serializable> layout = getOrCreateLayout(target.getDefaultCharset());
+
+ OutputStream stream = direct
+ ? getDirectOutputStream(target)
+ : follow ? getFollowOutputStream(target) : getDefaultOutputStream(target);
+
+ final String managerName = target.name() + '.' + follow + '.' + direct;
+ final OutputStreamManager manager =
+ OutputStreamManager.getManager(managerName, new FactoryData(stream, managerName, layout), factory);
return new ConsoleAppender(
- getName(),
- layout,
- getFilter(),
- getManager(target, follow, direct, layout),
- isIgnoreExceptions(),
- target,
- getPropertyArray());
+ getName(), layout, getFilter(), manager, isIgnoreExceptions(), target, getPropertyArray());
}
}
- private static OutputStreamManager getDefaultManager(
- final Target target,
- final boolean follow,
- final boolean direct,
- final Layout extends Serializable> layout) {
- final OutputStream os = getOutputStream(follow, direct, target);
-
+ private static OutputStreamManager getDefaultManager(final Layout extends Serializable> layout) {
+ final OutputStream os = getDefaultOutputStream(ConsoleAppender.DEFAULT_TARGET);
// LOG4J2-1176 DefaultConfiguration should not share OutputStreamManager instances to avoid memory leaks.
- final String managerName = target.name() + '.' + follow + '.' + direct + "-" + COUNT.get();
+ final String managerName = ConsoleAppender.DEFAULT_TARGET.name() + ".false.false-" + COUNT.get();
return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory);
}
- private static OutputStreamManager getManager(
- final Target target,
- final boolean follow,
- final boolean direct,
- final Layout extends Serializable> layout) {
- final OutputStream os = getOutputStream(follow, direct, target);
- final String managerName = target.name() + '.' + follow + '.' + direct;
- return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory);
+ private static OutputStream getDefaultOutputStream(Target target) {
+ return new CloseShieldOutputStream(target == Target.SYSTEM_OUT ? System.out : System.err);
}
- private static OutputStream getOutputStream(final boolean follow, final boolean direct, final Target target) {
- final String enc = Charset.defaultCharset().name();
- OutputStream outputStream;
- try {
- // @formatter:off
- outputStream = target == Target.SYSTEM_OUT
- ? direct
- ? new FileOutputStream(FileDescriptor.out)
- : (follow ? new PrintStream(new SystemOutStream(), true, enc) : System.out)
- : direct
- ? new FileOutputStream(FileDescriptor.err)
- : (follow ? new PrintStream(new SystemErrStream(), true, enc) : System.err);
- // @formatter:on
- outputStream = new CloseShieldOutputStream(outputStream);
- } catch (final UnsupportedEncodingException ex) { // should never happen
- throw new IllegalStateException("Unsupported default encoding " + enc, ex);
- }
- final PropertiesUtil propsUtil = PropertiesUtil.getProperties();
- if (!propsUtil.isOsWindows() || propsUtil.getBooleanProperty("log4j.skipJansi", true) || direct) {
- return outputStream;
- }
- try {
- // We type the parameter as a wildcard to avoid a hard reference to Jansi.
- final Class> clazz = Loader.loadClass(JANSI_CLASS);
- final Constructor> constructor = clazz.getConstructor(OutputStream.class);
- return new CloseShieldOutputStream((OutputStream) constructor.newInstance(outputStream));
- } catch (final ClassNotFoundException cnfe) {
- LOGGER.debug("Jansi is not installed, cannot find {}", JANSI_CLASS);
- } catch (final NoSuchMethodException nsme) {
- LOGGER.warn("{} is missing the proper constructor", JANSI_CLASS);
- } catch (final Exception ex) {
- LOGGER.warn(
- "Unable to instantiate {} due to {}",
- JANSI_CLASS,
- clean(Throwables.getRootCause(ex).toString()).trim());
- }
- return outputStream;
+ private static OutputStream getDirectOutputStream(Target target) {
+ return new CloseShieldOutputStream(
+ new FileOutputStream(target == Target.SYSTEM_OUT ? FileDescriptor.out : FileDescriptor.err));
}
- private static String clean(final String string) {
- return string.replace(Chars.NUL, Chars.SPACE);
+ private static OutputStream getFollowOutputStream(Target target) {
+ return target == Target.SYSTEM_OUT ? new SystemOutStream() : new SystemErrStream();
}
/**
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
index 5df74e5d9cd..74bc937ab61 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
@@ -23,9 +23,7 @@
import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
import org.apache.logging.log4j.core.pattern.TextRenderer;
import org.apache.logging.log4j.core.util.Integers;
-import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.core.util.Patterns;
-import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Strings;
/**
@@ -290,17 +288,11 @@ public static ThrowableFormatOptions newInstance(String[] options) {
|| option.equalsIgnoreCase(LOCALIZED_MESSAGE)) {
lines = 2;
} else if (option.startsWith("ansi(") && option.endsWith(")") || option.equals("ansi")) {
- if (Loader.isJansiAvailable()) {
- final String styleMapStr = option.equals("ansi")
- ? Strings.EMPTY
- : option.substring("ansi(".length(), option.length() - 1);
- ansiRenderer = new JAnsiTextRenderer(
- new String[] {null, styleMapStr}, JAnsiTextRenderer.DefaultExceptionStyleMap);
- } else {
- StatusLogger.getLogger()
- .warn(
- "You requested ANSI exception rendering but JANSI is not on the classpath. Please see https://logging.apache.org/log4j/2.x/runtime-dependencies.html");
- }
+ final String styleMapStr = option.equals("ansi")
+ ? Strings.EMPTY
+ : option.substring("ansi(".length(), option.length() - 1);
+ ansiRenderer = new JAnsiTextRenderer(
+ new String[] {null, styleMapStr}, JAnsiTextRenderer.DefaultExceptionStyleMap);
} else if (option.startsWith("S(") && option.endsWith(")")) {
suffix = option.substring("S(".length(), option.length() - 1);
} else if (option.startsWith("suffix(") && option.endsWith(")")) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
index 2d4bdcd199c..666e8325ed8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/package-info.java
@@ -18,7 +18,7 @@
* Log4j 2 private implementation classes.
*/
@Export
-@Version("2.25.0")
+@Version("2.24.1")
package org.apache.logging.log4j.core.impl;
import org.osgi.annotation.bundle.Export;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
index a915cdadfbc..5f6e4299277 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
@@ -38,7 +38,6 @@
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;
import org.apache.logging.log4j.core.pattern.RegexReplacement;
-import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.Strings;
/**
@@ -652,7 +651,7 @@ public static class Builder implements org.apache.logging.log4j.core.util.Builde
private boolean alwaysWriteExceptions = true;
@PluginBuilderAttribute
- private boolean disableAnsi = !useAnsiEscapeCodes();
+ private boolean disableAnsi;
@PluginBuilderAttribute
private boolean noConsoleNoAnsi;
@@ -665,13 +664,6 @@ public static class Builder implements org.apache.logging.log4j.core.util.Builde
private Builder() {}
- private boolean useAnsiEscapeCodes() {
- final PropertiesUtil propertiesUtil = PropertiesUtil.getProperties();
- final boolean isPlatformSupportsAnsi = !propertiesUtil.isOsWindows();
- final boolean isJansiRequested = !propertiesUtil.getBooleanProperty("log4j.skipJansi", true);
- return isPlatformSupportsAnsi || isJansiRequested;
- }
-
/**
* @param pattern
* The pattern. If not specified, defaults to DEFAULT_CONVERSION_PATTERN.
@@ -731,8 +723,7 @@ public Builder withAlwaysWriteExceptions(final boolean alwaysWriteExceptions) {
/**
* @param disableAnsi
- * If {@code "true"} (default is value of system property `log4j.skipJansi`, or `true` if undefined),
- * do not output ANSI escape codes
+ * If {@code true}, do not output ANSI escape codes.
*/
public Builder withDisableAnsi(final boolean disableAnsi) {
this.disableAnsi = disableAnsi;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index 74633b10a1d..34213373dfb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -421,6 +421,11 @@ public static Map createMap(final String values, final String[]
* @return a new map
*/
public static Map createMap(final String[] values, final String[] dontEscapeKeys) {
+ return createMap(values, dontEscapeKeys, "\\s");
+ }
+
+ static Map createMap(
+ final String[] values, final String[] dontEscapeKeys, final String separatorRegex) {
final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : Strings.EMPTY_ARRAY;
Arrays.sort(sortedIgnoreKeys);
final Map map = new HashMap<>();
@@ -430,7 +435,7 @@ public static Map createMap(final String[] values, final String[
final String key = toRootUpperCase(keyValue[0]);
final String value = keyValue[1];
final boolean escape = Arrays.binarySearch(sortedIgnoreKeys, key) < 0;
- map.put(key, escape ? createSequence(value.split("\\s")) : value);
+ map.put(key, escape ? createSequence(value.split(separatorRegex)) : value);
} else {
LOGGER.warn("Syntax error, missing '=': Expected \"{KEY1=VALUE, KEY2=VALUE, ...}");
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
index b9529573452..072dfeb87ff 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
@@ -16,28 +16,31 @@
*/
package org.apache.logging.log4j.core.pattern;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.BG_RED;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.BOLD;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.RED;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.WHITE;
+import static org.apache.logging.log4j.core.pattern.AnsiEscape.YELLOW;
import static org.apache.logging.log4j.util.Strings.toRootUpperCase;
-import static org.fusesource.jansi.AnsiRenderer.Code.BG_RED;
-import static org.fusesource.jansi.AnsiRenderer.Code.BOLD;
-import static org.fusesource.jansi.AnsiRenderer.Code.RED;
-import static org.fusesource.jansi.AnsiRenderer.Code.WHITE;
-import static org.fusesource.jansi.AnsiRenderer.Code.YELLOW;
+import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
+import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.AnsiRenderer;
-import org.fusesource.jansi.AnsiRenderer.Code;
/**
* Renders an input as ANSI escaped output.
- *
- * Uses the JAnsi rendering syntax as the default to render a message into an ANSI escaped string.
- *
+ *
+ * Uses the
+ * JLine AnsiRenderer syntax
+ * to render a message into an ANSI escaped string.
+ *
+ *
* The default syntax for embedded ANSI codes is:
- *
+ *
*
* @|code (,code )* text |@
*
@@ -72,279 +75,245 @@
* logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
*
*
- * Note: This class originally copied and then heavily modified code from JAnsi's AnsiRenderer (which is licensed as
- * Apache 2.0.)
- *
- * @see AnsiRenderer
+ *
+ * Note: this class was originally copied and then heavily modified from
+ * JAnsi/JLine AnsiRenderer ,
+ * licensed under an Apache Software License, version 2.0.
+ *
*/
public final class JAnsiTextRenderer implements TextRenderer {
- public static final Map DefaultExceptionStyleMap;
- static final Map DefaultMessageStyleMap;
- private static final Map> PrefedinedStyleMaps;
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ public static final Map DefaultExceptionStyleMap;
+ static final Map DEFAULT_MESSAGE_STYLE_MAP;
+ private static final Map> PREFEDINED_STYLE_MAPS;
- private static void put(final Map map, final String name, final Code... codes) {
- map.put(name, codes);
+ private static final String BEGIN_TOKEN = "@|";
+ private static final String END_TOKEN = "|@";
+ // The length of AnsiEscape.CSI
+ private static final int CSI_LENGTH = 2;
+
+ private static Map.Entry entry(final String name, final AnsiEscape... codes) {
+ final StringBuilder sb = new StringBuilder(AnsiEscape.CSI.getCode());
+ for (final AnsiEscape code : codes) {
+ sb.append(code.getCode());
+ }
+ return new AbstractMap.SimpleImmutableEntry<>(name, sb.toString());
+ }
+
+ @SafeVarargs
+ private static Map ofEntries(final Map.Entry... entries) {
+ final Map map = new HashMap<>(entries.length);
+ for (final Map.Entry entry : entries) {
+ map.put(entry.getKey(), entry.getValue());
+ }
+ return Collections.unmodifiableMap(map);
}
static {
- final Map> tempPreDefs = new HashMap<>();
// Default style: Spock
- {
- // TODO Should the keys be in an enum?
- final Map map = new HashMap<>();
- put(map, "Prefix", WHITE);
- put(map, "Name", BG_RED, WHITE);
- put(map, "NameMessageSeparator", BG_RED, WHITE);
- put(map, "Message", BG_RED, WHITE, BOLD);
- put(map, "At", WHITE);
- put(map, "CauseLabel", WHITE);
- put(map, "Text", WHITE);
- put(map, "More", WHITE);
- put(map, "Suppressed", WHITE);
- // StackTraceElement
- put(map, "StackTraceElement.ClassLoaderName", WHITE);
- put(map, "StackTraceElement.ClassLoaderSeparator", WHITE);
- put(map, "StackTraceElement.ModuleName", WHITE);
- put(map, "StackTraceElement.ModuleVersionSeparator", WHITE);
- put(map, "StackTraceElement.ModuleVersion", WHITE);
- put(map, "StackTraceElement.ModuleNameSeparator", WHITE);
- put(map, "StackTraceElement.ClassName", YELLOW);
- put(map, "StackTraceElement.ClassMethodSeparator", YELLOW);
- put(map, "StackTraceElement.MethodName", YELLOW);
- put(map, "StackTraceElement.NativeMethod", YELLOW);
- put(map, "StackTraceElement.FileName", RED);
- put(map, "StackTraceElement.LineNumber", RED);
- put(map, "StackTraceElement.Container", RED);
- put(map, "StackTraceElement.ContainerSeparator", WHITE);
- put(map, "StackTraceElement.UnknownSource", RED);
- // ExtraClassInfo
- put(map, "ExtraClassInfo.Inexact", YELLOW);
- put(map, "ExtraClassInfo.Container", YELLOW);
- put(map, "ExtraClassInfo.ContainerSeparator", YELLOW);
- put(map, "ExtraClassInfo.Location", YELLOW);
- put(map, "ExtraClassInfo.Version", YELLOW);
- // Save
- DefaultExceptionStyleMap = Collections.unmodifiableMap(map);
- tempPreDefs.put("Spock", DefaultExceptionStyleMap);
- }
+ final Map spock = ofEntries(
+ entry("Prefix", WHITE),
+ entry("Name", BG_RED, WHITE),
+ entry("NameMessageSeparator", BG_RED, WHITE),
+ entry("Message", BG_RED, WHITE, BOLD),
+ entry("At", WHITE),
+ entry("CauseLabel", WHITE),
+ entry("Text", WHITE),
+ entry("More", WHITE),
+ entry("Suppressed", WHITE),
+ // StackTraceElement
+ entry("StackTraceElement.ClassLoaderName", WHITE),
+ entry("StackTraceElement.ClassLoaderSeparator", WHITE),
+ entry("StackTraceElement.ModuleName", WHITE),
+ entry("StackTraceElement.ModuleVersionSeparator", WHITE),
+ entry("StackTraceElement.ModuleVersion", WHITE),
+ entry("StackTraceElement.ModuleNameSeparator", WHITE),
+ entry("StackTraceElement.ClassName", YELLOW),
+ entry("StackTraceElement.ClassMethodSeparator", YELLOW),
+ entry("StackTraceElement.MethodName", YELLOW),
+ entry("StackTraceElement.NativeMethod", YELLOW),
+ entry("StackTraceElement.FileName", RED),
+ entry("StackTraceElement.LineNumber", RED),
+ entry("StackTraceElement.Container", RED),
+ entry("StackTraceElement.ContainerSeparator", WHITE),
+ entry("StackTraceElement.UnknownSource", RED),
+ // ExtraClassInfo
+ entry("ExtraClassInfo.Inexact", YELLOW),
+ entry("ExtraClassInfo.Container", YELLOW),
+ entry("ExtraClassInfo.ContainerSeparator", YELLOW),
+ entry("ExtraClassInfo.Location", YELLOW),
+ entry("ExtraClassInfo.Version", YELLOW));
+
// Style: Kirk
- {
- // TODO Should the keys be in an enum?
- final Map map = new HashMap<>();
- put(map, "Prefix", WHITE);
- put(map, "Name", BG_RED, YELLOW, BOLD);
- put(map, "NameMessageSeparator", BG_RED, YELLOW);
- put(map, "Message", BG_RED, WHITE, BOLD);
- put(map, "At", WHITE);
- put(map, "CauseLabel", WHITE);
- put(map, "Text", WHITE);
- put(map, "More", WHITE);
- put(map, "Suppressed", WHITE);
- // StackTraceElement
- put(map, "StackTraceElement.ClassLoaderName", WHITE);
- put(map, "StackTraceElement.ClassLoaderSeparator", WHITE);
- put(map, "StackTraceElement.ModuleName", WHITE);
- put(map, "StackTraceElement.ModuleVersionSeparator", WHITE);
- put(map, "StackTraceElement.ModuleVersion", WHITE);
- put(map, "StackTraceElement.ModuleNameSeparator", WHITE);
- put(map, "StackTraceElement.ClassName", BG_RED, WHITE);
- put(map, "StackTraceElement.ClassMethodSeparator", BG_RED, YELLOW);
- put(map, "StackTraceElement.MethodName", BG_RED, YELLOW);
- put(map, "StackTraceElement.NativeMethod", BG_RED, YELLOW);
- put(map, "StackTraceElement.FileName", RED);
- put(map, "StackTraceElement.LineNumber", RED);
- put(map, "StackTraceElement.Container", RED);
- put(map, "StackTraceElement.ContainerSeparator", WHITE);
- put(map, "StackTraceElement.UnknownSource", RED);
- // ExtraClassInfo
- put(map, "ExtraClassInfo.Inexact", YELLOW);
- put(map, "ExtraClassInfo.Container", WHITE);
- put(map, "ExtraClassInfo.ContainerSeparator", WHITE);
- put(map, "ExtraClassInfo.Location", YELLOW);
- put(map, "ExtraClassInfo.Version", YELLOW);
- // Save
- tempPreDefs.put("Kirk", Collections.unmodifiableMap(map));
- }
- {
- final Map temp = new HashMap<>();
- // TODO
- DefaultMessageStyleMap = Collections.unmodifiableMap(temp);
- }
- PrefedinedStyleMaps = Collections.unmodifiableMap(tempPreDefs);
+ final Map kirk = ofEntries(
+ entry("Prefix", WHITE),
+ entry("Name", BG_RED, YELLOW, BOLD),
+ entry("NameMessageSeparator", BG_RED, YELLOW),
+ entry("Message", BG_RED, WHITE, BOLD),
+ entry("At", WHITE),
+ entry("CauseLabel", WHITE),
+ entry("Text", WHITE),
+ entry("More", WHITE),
+ entry("Suppressed", WHITE),
+ // StackTraceElement
+ entry("StackTraceElement.ClassLoaderName", WHITE),
+ entry("StackTraceElement.ClassLoaderSeparator", WHITE),
+ entry("StackTraceElement.ModuleName", WHITE),
+ entry("StackTraceElement.ModuleVersionSeparator", WHITE),
+ entry("StackTraceElement.ModuleVersion", WHITE),
+ entry("StackTraceElement.ModuleNameSeparator", WHITE),
+ entry("StackTraceElement.ClassName", BG_RED, WHITE),
+ entry("StackTraceElement.ClassMethodSeparator", BG_RED, YELLOW),
+ entry("StackTraceElement.MethodName", BG_RED, YELLOW),
+ entry("StackTraceElement.NativeMethod", BG_RED, YELLOW),
+ entry("StackTraceElement.FileName", RED),
+ entry("StackTraceElement.LineNumber", RED),
+ entry("StackTraceElement.Container", RED),
+ entry("StackTraceElement.ContainerSeparator", WHITE),
+ entry("StackTraceElement.UnknownSource", RED),
+ // ExtraClassInfo
+ entry("ExtraClassInfo.Inexact", YELLOW),
+ entry("ExtraClassInfo.Container", WHITE),
+ entry("ExtraClassInfo.ContainerSeparator", WHITE),
+ entry("ExtraClassInfo.Location", YELLOW),
+ entry("ExtraClassInfo.Version", YELLOW));
+
+ // Save
+ DefaultExceptionStyleMap = spock;
+ DEFAULT_MESSAGE_STYLE_MAP = Collections.emptyMap();
+ Map> predefinedStyleMaps = new HashMap<>();
+ predefinedStyleMaps.put("Spock", spock);
+ predefinedStyleMaps.put("Kirk", kirk);
+ PREFEDINED_STYLE_MAPS = Collections.unmodifiableMap(predefinedStyleMaps);
}
private final String beginToken;
private final int beginTokenLen;
private final String endToken;
private final int endTokenLen;
- private final Map styleMap;
+ private final Map styleMap;
- public JAnsiTextRenderer(final String[] formats, final Map defaultStyleMap) {
- String tempBeginToken = AnsiRenderer.BEGIN_TOKEN;
- String tempEndToken = AnsiRenderer.END_TOKEN;
- final Map map;
+ public JAnsiTextRenderer(final String[] formats, final Map defaultStyleMap) {
+ // The format string is a list of whitespace-separated expressions:
+ // Key=AnsiEscape(,AnsiEscape)*
if (formats.length > 1) {
- final String allStylesStr = formats[1];
- // Style def split
- final String[] allStyleAssignmentsArr = allStylesStr.split(" ");
- map = new HashMap<>(allStyleAssignmentsArr.length + defaultStyleMap.size());
- map.putAll(defaultStyleMap);
- for (final String styleAssignmentStr : allStyleAssignmentsArr) {
- final String[] styleAssignmentArr = styleAssignmentStr.split("=");
- if (styleAssignmentArr.length != 2) {
- StatusLogger.getLogger()
- .warn(
- "{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
- getClass().getSimpleName(),
- styleAssignmentStr);
+ final String stylesStr = formats[1];
+ final Map map = AnsiEscape.createMap(
+ stylesStr.split("\\s", -1), new String[] {"BeginToken", "EndToken", "Style"}, ",");
+
+ // Handle the special tokens
+ beginToken = Objects.toString(map.remove("BeginToken"), BEGIN_TOKEN);
+ endToken = Objects.toString(map.remove("EndToken"), END_TOKEN);
+ final String predefinedStyle = map.remove("Style");
+
+ // Create style map
+ final Map styleMap = new HashMap<>(map.size() + defaultStyleMap.size());
+ defaultStyleMap.forEach((k, v) -> styleMap.put(toRootUpperCase(k), v));
+ if (predefinedStyle != null) {
+ final Map predefinedMap = PREFEDINED_STYLE_MAPS.get(predefinedStyle);
+ if (predefinedMap != null) {
+ map.putAll(predefinedMap);
} else {
- final String styleName = styleAssignmentArr[0];
- final String codeListStr = styleAssignmentArr[1];
- final String[] codeNames = codeListStr.split(",");
- if (codeNames.length == 0) {
- StatusLogger.getLogger()
- .warn(
- "{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
- getClass().getSimpleName(),
- styleAssignmentStr);
- } else {
- switch (styleName) {
- case "BeginToken":
- tempBeginToken = codeNames[0];
- break;
- case "EndToken":
- tempEndToken = codeNames[0];
- break;
- case "StyleMapName":
- final String predefinedMapName = codeNames[0];
- final Map predefinedMap = PrefedinedStyleMaps.get(predefinedMapName);
- if (predefinedMap != null) {
- map.putAll(predefinedMap);
- } else {
- StatusLogger.getLogger()
- .warn(
- "Unknown predefined map name {}, pick one of {}",
- predefinedMapName,
- null);
- }
- break;
- default:
- final Code[] codes = new Code[codeNames.length];
- for (int i = 0; i < codes.length; i++) {
- codes[i] = toCode(codeNames[i]);
- }
- map.put(styleName, codes);
- }
- }
+ LOGGER.warn(
+ "Unknown predefined map name {}, pick one of {}",
+ predefinedStyle,
+ PREFEDINED_STYLE_MAPS.keySet());
}
}
+ styleMap.putAll(map);
+ this.styleMap = Collections.unmodifiableMap(styleMap);
} else {
- map = defaultStyleMap;
- }
- styleMap = map;
- beginToken = tempBeginToken;
- endToken = tempEndToken;
- beginTokenLen = tempBeginToken.length();
- endTokenLen = tempEndToken.length();
- }
-
- public Map getStyleMap() {
- return styleMap;
- }
-
- private void render(final Ansi ansi, final Code code) {
- if (code.isColor()) {
- if (code.isBackground()) {
- ansi.bg(code.getColor());
- } else {
- ansi.fg(code.getColor());
- }
- } else if (code.isAttribute()) {
- ansi.a(code.getAttribute());
- }
- }
-
- private void render(final Ansi ansi, final Code... codes) {
- for (final Code code : codes) {
- render(ansi, code);
+ beginToken = BEGIN_TOKEN;
+ endToken = END_TOKEN;
+ this.styleMap = Collections.unmodifiableMap(defaultStyleMap);
}
+ beginTokenLen = beginToken.length();
+ endTokenLen = endToken.length();
}
/**
- * Renders the given text with the given names which can be ANSI code names or Log4j style names.
+ * Renders the given input with the given names which can be ANSI code names or Log4j style names.
*
- * @param text
- * The text to render
- * @param names
+ * @param input
+ * The input to render
+ * @param styleNames
* ANSI code names or Log4j style names.
- * @return A rendered string containing ANSI codes.
*/
- private String render(final String text, final String... names) {
- final Ansi ansi = Ansi.ansi();
- for (final String name : names) {
- final Code[] codes = styleMap.get(name);
- if (codes != null) {
- render(ansi, codes);
+ private void render(final String input, final StringBuilder output, final String... styleNames) {
+ boolean first = true;
+ for (final String styleName : styleNames) {
+ final String escape = styleMap.get(toRootUpperCase(styleName));
+ if (escape != null) {
+ merge(escape, output, first);
} else {
- render(ansi, toCode(name));
+ merge(AnsiEscape.createSequence(styleName), output, first);
}
+ first = false;
+ }
+ output.append(input).append(AnsiEscape.getDefaultStyle());
+ }
+
+ private static void merge(final String escapeSequence, final StringBuilder output, final boolean first) {
+ if (first) {
+ output.append(escapeSequence);
+ } else {
+ // Delete the trailing AnsiEscape.SUFFIX
+ output.setLength(output.length() - 1);
+ output.append(AnsiEscape.SEPARATOR.getCode());
+ output.append(escapeSequence.substring(CSI_LENGTH));
}
- return ansi.a(text).reset().toString();
}
// EXACT COPY OF StringBuilder version of the method but typed as String for input
@Override
public void render(final String input, final StringBuilder output, final String styleName)
throws IllegalArgumentException {
- output.append(render(input, styleName));
+ render(input, output, styleName.split(",", -1));
}
@Override
public void render(final StringBuilder input, final StringBuilder output) throws IllegalArgumentException {
- int i = 0;
- int j, k;
+ int pos = 0;
+ int beginTokenPos, endTokenPos;
while (true) {
- j = input.indexOf(beginToken, i);
- if (j == -1) {
- if (i == 0) {
- output.append(input);
- return;
- }
- output.append(input.substring(i, input.length()));
+ beginTokenPos = input.indexOf(beginToken, pos);
+ if (beginTokenPos == -1) {
+ output.append(pos == 0 ? input : input.substring(pos, input.length()));
return;
}
- output.append(input.substring(i, j));
- k = input.indexOf(endToken, j);
+ output.append(input.substring(pos, beginTokenPos));
+ endTokenPos = input.indexOf(endToken, beginTokenPos);
- if (k == -1) {
- output.append(input);
+ if (endTokenPos == -1) {
+ LOGGER.warn(
+ "Missing matching end token {} for token at position {}: '{}'", endToken, beginTokenPos, input);
+ output.append(beginTokenPos == 0 ? input : input.substring(beginTokenPos, input.length()));
return;
}
- j += beginTokenLen;
- final String spec = input.substring(j, k);
+ beginTokenPos += beginTokenLen;
+ final String spec = input.substring(beginTokenPos, endTokenPos);
- final String[] items = spec.split(AnsiRenderer.CODE_TEXT_SEPARATOR, 2);
+ final String[] items = spec.split("\\s", 2);
if (items.length == 1) {
- output.append(input);
- return;
+ LOGGER.warn("Missing argument in ANSI escape specification '{}'", spec);
+ output.append(beginToken).append(spec).append(endToken);
+ } else {
+ render(items[1], output, items[0].split(",", -1));
}
- final String replacement = render(items[1], items[0].split(","));
-
- output.append(replacement);
-
- i = k + endTokenLen;
+ pos = endTokenPos + endTokenLen;
}
}
- private Code toCode(final String name) {
- return Code.valueOf(toRootUpperCase(name));
+ public Map getStyleMap() {
+ return styleMap;
}
@Override
public String toString() {
- return "JAnsiMessageRenderer [beginToken=" + beginToken + ", beginTokenLen=" + beginTokenLen + ", endToken="
+ return "AnsiMessageRenderer [beginToken=" + beginToken + ", beginTokenLen=" + beginTokenLen + ", endToken="
+ endToken + ", endTokenLen=" + endTokenLen + ", styleMap=" + styleMap + "]";
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
index 44016664afd..dd7df75faff 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
@@ -23,10 +23,8 @@
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.MultiformatMessage;
-import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.MultiFormatStringBuilderFormattable;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.apache.logging.log4j.util.StringBuilderFormattable;
@@ -52,12 +50,7 @@ private static TextRenderer loadMessageRenderer(final String[] options) {
for (final String option : options) {
switch (toRootUpperCase(option)) {
case "ANSI":
- if (Loader.isJansiAvailable()) {
- return new JAnsiTextRenderer(options, JAnsiTextRenderer.DefaultMessageStyleMap);
- }
- StatusLogger.getLogger()
- .warn("You requested ANSI message rendering but JANSI is not on the classpath.");
- return null;
+ return new JAnsiTextRenderer(options, JAnsiTextRenderer.DEFAULT_MESSAGE_STYLE_MAP);
case "HTML":
return new HtmlTextRenderer(options);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
index 5c047848b57..ac6407f47b3 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/package-info.java
@@ -18,7 +18,7 @@
* Provides classes implementing format specifiers in conversion patterns.
*/
@Export
-@Version("2.25.0")
+@Version("2.24.1")
package org.apache.logging.log4j.core.pattern;
import org.osgi.annotation.bundle.Export;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
index 64ee6be3599..4ae5d463353 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
@@ -349,6 +349,10 @@ public static boolean isClassAvailable(final String className) {
}
}
+ /**
+ * @deprecated Since 2.25.0 without a replacement.
+ */
+ @Deprecated
public static boolean isJansiAvailable() {
return isClassAvailable("org.fusesource.jansi.AnsiRenderer");
}
diff --git a/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java b/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
index 0dbd426d30e..f460c5c6079 100644
--- a/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
+++ b/log4j-jakarta-smtp/src/test/java/org/apache/logging/log4j/smtp/SmtpAppenderAsyncTest.java
@@ -16,8 +16,8 @@
*/
package org.apache.logging.log4j.smtp;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
import java.util.Iterator;
import org.apache.logging.log4j.ThreadContext;
diff --git a/log4j-parent/pom.xml b/log4j-parent/pom.xml
index 4c82d04e146..3ae996ef972 100644
--- a/log4j-parent/pom.xml
+++ b/log4j-parent/pom.xml
@@ -100,7 +100,6 @@
2.2
4.0.1
2.3.3
- 2.4.1
3.3.4
0.22.1
1.7.0
@@ -471,12 +470,6 @@
${jakarta-mail.version}
-
- org.fusesource.jansi
- jansi
- ${jansi.version}
-
-
com.google.code.java-allocation-instrumenter
diff --git a/pom.xml b/pom.xml
index 03760b9eb0a..88bf7db62ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -345,7 +345,6 @@
4.0.0
1.11.0
2.18.0
- 1.18
1.6.2
4.0.5
18.3.12
@@ -769,12 +768,6 @@
pom
-
- org.fusesource.jansi
- jansi
- ${site-jansi.version}
-
-
com.sun.mail
javax.mail
diff --git a/src/changelog/.2.x.x/.release-notes.adoc.ftl b/src/changelog/.2.x.x/.release-notes.adoc.ftl
index 16be1ddfc7f..47b4447337a 100644
--- a/src/changelog/.2.x.x/.release-notes.adoc.ftl
+++ b/src/changelog/.2.x.x/.release-notes.adoc.ftl
@@ -38,4 +38,10 @@ This effectively helped with fixing some bugs by matching the feature parity of
Additionally, rendered stack traces are ensured to be prefixed with a newline, which used to be a whitespace in earlier versions.
The support for the `\{ansi}` option in exception converters is removed too.
+=== ANSI support on Windows
+
+Since 2017, Windows 10 and newer have offered native support for ANSI escapes.
+The support for the outdated Jansi 1.x library has therefore been removed.
+See xref:manual/pattern-layout.adoc#jansi[ANSI styling on Windows] for more information.
+
<#include "../.changelog.adoc.ftl">
diff --git a/src/changelog/.2.x.x/1736_split_jansi_support.xml b/src/changelog/.2.x.x/1736_split_jansi_support.xml
new file mode 100644
index 00000000000..a585fed74f4
--- /dev/null
+++ b/src/changelog/.2.x.x/1736_split_jansi_support.xml
@@ -0,0 +1,8 @@
+
+
+
+ Remove JAnsi library support. Windows 10 console has supported ANSI escapes since 2017.
+
diff --git a/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml b/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml
new file mode 100644
index 00000000000..7fad82b6d5b
--- /dev/null
+++ b/src/changelog/.2.x.x/2916_rewrite_jansi_renderer.xml
@@ -0,0 +1,8 @@
+
+
+
+ Rewrite `JAnsiTextRenderer` to work without JAnsi library.
+
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index 8ec9a597b23..7cdcf41ecfb 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -59,7 +59,6 @@ asciidoc:
disruptor-version: "${site-disruptor.version}"
flume-version: "${site-flume.version}"
jackson-version: "${site-jackson.version}"
- jansi-version: "${site-jansi.version}"
javax-mail-version: "${site-javax-mail.version}"
jctools-version: "${site-jctools.version}"
je-version: "${site-je.version}"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index 21652d7e98f..ff6edf566a9 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -59,7 +59,6 @@ asciidoc:
disruptor-version: "1.2.3-disruptor"
flume-version: "1.2.3-flume"
jackson-version: "1.2.3-jackson"
- jansi-version: "1.2.3-jansi"
javax-mail-version: "1.2.3-javax-mail"
jctools-version: "1.2.3-jctools"
je-version: "1.2.3-je"
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index 6f0c4aaad7d..a43675fb547 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@ -216,7 +216,7 @@ They are documented in separate pages based on their target resource:
=== Console Appender
As one might expect, the Console Appender writes its output to either the standard output or standard error output.
-The appender supports four different ways to access the output streams:
+The appender supports three different ways to access the output streams:
`direct`::
This mode gives the best performance.
@@ -236,39 +236,6 @@ This setting might be useful in multi-application environments.
Some application servers modify `System.out` and `System.err` to always point to the currently running application.
====
-`JANSI`::
-If the application is running on Windows and the
-https://fusesource.github.io/jansi/[JANSI library]
-is available, the Console appender will use JANSI to emulate ANSI sequence support.
-This mode can be disabled by setting the
-xref:manual/systemproperties.adoc#log4j2.skipJansi[`log4j2.skipJansi`]
-configuration attribute to `true`.
-+
-Additional runtime dependencies are required to use JANSI:
-+
-[tabs]
-====
-Maven::
-+
-[source,xml,subs="+attributes"]
-----
-
- org.fusesource.jansi
- jansi
- {jansi-version}
-
-
-----
-
-Gradle::
-+
-[source,groovy,subs="+attributes"]
-----
-runtimeOnly 'org.fusesource.jansi:jansi:{jansi-version}'
-----
-
-====
-
[#ConsoleAppender-attributes]
.Console Appender configuration attributes
[cols="1m,1,1,5"]
@@ -311,9 +278,7 @@ If other logging backends or the application itself uses `System.out/System.err`
====
This setting is incompatible with the
-<>
-and
-xref:manual/systemproperties.adoc#log4j2.skipJansi[JANSI support].
+<>.
| [[ConsoleAppender-attr-follow]]
follow
@@ -328,9 +293,7 @@ https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#setOut-java.io.P
Otherwise, the value of `System.out` (resp. `System.err`) at configuration time will be used.
This setting is incompatible with the
-<>
-and
-xref:manual/systemproperties.adoc#log4j2.skipJansi[JANSI support].
+<>.
| [[ConsoleAppender-attr-ignoreExceptions]]
ignoreExceptions
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index 1817b388229..49723986482 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -209,7 +209,7 @@ The optional footer to include at the bottom of each log file
|Default value |`false`
|===
-If `true`, do not output ANSI escape codes
+If `true`, do not output ANSI escape codes.
[#plugin-attr-noConsoleNoAnsi]
==== `noConsoleNoAnsi`
@@ -220,7 +220,7 @@ If `true`, do not output ANSI escape codes
|Default value |`false`
|===
-If `true` and `System.console()` is null, do not output ANSI escape codes
+If `true` and `System.console()` is `null`, do not output ANSI escape codes
[#plugin-elements]
=== Plugin elements
@@ -1598,19 +1598,14 @@ If your terminal supports 24-bit colors, you can specify:
[#jansi]
==== ANSI styling on Windows
-ANSI escape sequences are supported natively on many platforms, but not by default on Windows.
-To enable ANSI support add the
-http://fusesource.github.io/jansi/[Jansi]
-dependency to your application, and set xref:manual/systemproperties.adoc#log4j2.skipJansi[the `log4j2.skipJansi` system property] to `false`.
-This allows Log4j to use Jansi to add ANSI escape codes when writing to the console.
+ANSI escape sequences are supported natively on many platforms, but are disabled by default in `cmd.exe` on Windows.
+To enable ANSI escape sequences, create a registry key named `HKEY_CURRENT_USER\Console\VirtualTerminalLevel` of type `DWORD` and set its value to `0x1`.
-[NOTE]
-====
-Before Log4j 2.10, Jansi was enabled by default.
-The fact that Jansi requires native code means that Jansi can only be loaded by a single class loader.
-For web applications, this means the Jansi jar has to be in the web container's classpath.
-To avoid causing problems for web applications, Log4j no longer automatically tries to load Jansi without explicit configuration from Log4j 2.10 onward.
-====
+See
+https://devblogs.microsoft.com/commandline/understanding-windows-console-host-settings/[Understanding Windows Console Host Settings]
+and
+https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences[Console Virtual Terminal Sequences]
+Microsoft documentation for more details.
[#garbage-free]
=== Garbage-free configuration
diff --git a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
index 2bd4b6e75e5..318c745e10a 100644
--- a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
@@ -149,13 +149,6 @@ include::partial$manual/systemproperties/properties-configuration-factory.adoc[l
include::partial$manual/systemproperties/properties-garbage-collection.adoc[leveloffset=+2]
-[id=properties-jansi]
-=== JANSI
-
-If the https://fusesource.github.io/jansi/[JANSI] library is on the runtime classpath of the application, the following property can be used to control its usage:
-
-include::partial$manual/systemproperties/properties-jansi.adoc[leveloffset=+2]
-
[id=properties-jmx]
=== JMX
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
deleted file mode 100644
index 6b58ac8c586..00000000000
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-jansi.adoc
+++ /dev/null
@@ -1,32 +0,0 @@
-////
- 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.
-////
-[id=log4j2.skipJansi]
-== `log4j2.skipJansi`
-
-[cols="1h,5"]
-|===
-| Env. variable | `LOG4J_SKIP_JANSI`
-| Type | `boolean`
-| Default value | `true`
-|===
-
-If the following conditions are satisfied:
-
-* Log4j runs on Windows,
-* this property is set to `false`,
-
-Log4j will use the JANSI library to color the output of the console appender.
\ No newline at end of file