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 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 layout) { @@ -194,7 +176,7 @@ public static ConsoleAppender createDefaultAppenderForLayout(final Layout 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 layout) { - final OutputStream os = getOutputStream(follow, direct, target); - + private static OutputStreamManager getDefaultManager(final Layout 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 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