From d4804f9b85daac1df9baf927111cf10bfde14ce8 Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Thu, 19 Dec 2024 16:21:17 +0100 Subject: [PATCH] fix incompatibile change, Spring-Boot issue 885 Signed-off-by: Ceki Gulcu --- .../pattern/LegacyPatternLayoutTest.java | 69 +++++++++++++++++++ .../classic/pattern/SubPatternLayoutTest.java | 38 ---------- .../ch/qos/logback/core/CoreConstants.java | 11 +++ .../qos/logback/core/html/HTMLLayoutBase.java | 2 +- .../processor/ConversionRuleModelHandler.java | 6 +- .../core/pattern/PatternLayoutBase.java | 35 ++++++---- 6 files changed, 106 insertions(+), 55 deletions(-) create mode 100644 logback-classic/src/test/java/ch/qos/logback/classic/pattern/LegacyPatternLayoutTest.java delete mode 100644 logback-classic/src/test/java/ch/qos/logback/classic/pattern/SubPatternLayoutTest.java diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LegacyPatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LegacyPatternLayoutTest.java new file mode 100644 index 0000000000..e04c7402c4 --- /dev/null +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LegacyPatternLayoutTest.java @@ -0,0 +1,69 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.CoreConstants; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class LegacyPatternLayoutTest { + + LoggerContext context = new LoggerContext(); + + @Test public void subPattern() { + SubPatternLayout layout = new SubPatternLayout(); + layout.setPattern("%"+SubPatternLayout.DOOO); + layout.setContext(context); + layout.start(); + LoggingEvent event = new LoggingEvent(); + event.setTimeStamp(0); + + String result = layout.doLayout(event); + assertEquals("1970-01-01 01:00:00,000", result); + } + + @Test + public void fromContext() { + Map registry = (Map) this.context + .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + // + assertNull(registry); + if(registry == null) { + registry = new HashMap(); + this.context.putObject(CoreConstants.PATTERN_RULE_REGISTRY, registry); + } + + registry.put("legacy", LevelConverter.class.getName()); + + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setPattern("%legacy"); + patternLayout.setContext(context); + patternLayout.start(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.WARN); + String result = patternLayout.doLayout(event); + assertEquals("WARN", result); + } + +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/SubPatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/SubPatternLayoutTest.java deleted file mode 100644 index e6f21bb751..0000000000 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/SubPatternLayoutTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2024, QOS.ch. All rights reserved. - * - * This program and the accompanying materials are dual-licensed under - * either the terms of the Eclipse Public License v1.0 as published by - * the Eclipse Foundation - * - * or (per the licensee's choosing) - * - * under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation. - */ - -package ch.qos.logback.classic.pattern; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggingEvent; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class SubPatternLayoutTest { - - LoggerContext context = new LoggerContext(); - - @Test public void smoke() { - SubPatternLayout layout = new SubPatternLayout(); - layout.setPattern("%"+SubPatternLayout.DOOO); - layout.setContext(context); - layout.start(); - LoggingEvent event = new LoggingEvent(); - event.setTimeStamp(0); - - String result = layout.doLayout(event); - assertEquals("1970-01-01 01:00:00,000", result); - } -} diff --git a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java index 8ecd8d7e77..93d2ddce4c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java @@ -52,12 +52,23 @@ public class CoreConstants { * The default context name. */ public static final String DEFAULT_CONTEXT_NAME = "default"; + + /** + * Customized pattern conversion rules are stored under this key in the + * {@link Context} object store. + * + * @since 1.5.14 + */ + public static final String PATTERN_RULE_REGISTRY_FOR_SUPPLIERS = "PATTERN_RULE_REGISTRY_FOR_SUPPLIERS"; + /** * Customized pattern conversion rules are stored under this key in the * {@link Context} object store. */ public static final String PATTERN_RULE_REGISTRY = "PATTERN_RULE_REGISTRY"; + + public static final String ISO8601_STR = "ISO8601"; public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java index 8bbbd737d8..7a34cb3162 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java @@ -117,7 +117,7 @@ public Map> getEffectiveConverterMap() { if (context != null) { @SuppressWarnings("unchecked") Map> contextMap = (Map>) context - .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + .getObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS); if (contextMap != null) { effectiveMap.putAll(contextMap); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/processor/ConversionRuleModelHandler.java b/logback-core/src/main/java/ch/qos/logback/core/model/processor/ConversionRuleModelHandler.java index 9d60d5a5fa..d467a5cc41 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/model/processor/ConversionRuleModelHandler.java +++ b/logback-core/src/main/java/ch/qos/logback/core/model/processor/ConversionRuleModelHandler.java @@ -26,8 +26,6 @@ import java.util.Map; import java.util.function.Supplier; -import static ch.qos.logback.core.joran.JoranConstants.CONVERSION_WORD_ATTRIBUTE; - public class ConversionRuleModelHandler extends ModelHandlerBase { private boolean inError; @@ -59,10 +57,10 @@ public void handle(ModelInterpretationContext mic, Model model) throws ModelHand try { Map> ruleRegistry = (Map>) context - .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + .getObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS); if (ruleRegistry == null) { ruleRegistry = new HashMap<>(); - context.putObject(CoreConstants.PATTERN_RULE_REGISTRY, ruleRegistry); + context.putObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS, ruleRegistry); } // put the new rule into the rule registry addInfo("registering conversion word " + conversionWord + " with class [" + converterClass + "]"); diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java index 8a0fcb27d7..ca194345e0 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java @@ -81,14 +81,14 @@ public Map> getEffectiveConverterMap() { effectiveMap.putAll(defaultConverterSupplierMap); } - caterForLegacy_DefaultConverterMap(effectiveMap); + caterForLegacyConverterMaps(effectiveMap); // contextMap is more specific than the default map Context context = getContext(); if (context != null) { @SuppressWarnings("unchecked") Map> contextMap = (Map>) context - .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + .getObject(CoreConstants.PATTERN_RULE_REGISTRY_FOR_SUPPLIERS); if (contextMap != null) { effectiveMap.putAll(contextMap); } @@ -104,18 +104,29 @@ public Map> getEffectiveConverterMap() { * * @param effectiveMap */ - private void caterForLegacy_DefaultConverterMap(Map> effectiveMap) { - // this transformation is for backward compatibility of existing code + private void caterForLegacyConverterMaps(Map> effectiveMap) { + Map mapFromContext = (Map) this.context + .getObject(CoreConstants.PATTERN_RULE_REGISTRY); + + migrateFromStringMapToSupplierMap(mapFromContext, effectiveMap); + Map defaultConverterMap = getDefaultConverterMap(); - if(defaultConverterMap != null) { - for(Map.Entry entry: defaultConverterMap.entrySet()) { - String key = entry.getKey().toString(); - String converterClassName = entry.getValue(); - ConverterSupplierByClassName converterSupplierByClassName = new ConverterSupplierByClassName(key, converterClassName); - converterSupplierByClassName.setContext(getContext()); - effectiveMap.put(key, converterSupplierByClassName); - } + migrateFromStringMapToSupplierMap(defaultConverterMap, effectiveMap); + } + + private void migrateFromStringMapToSupplierMap(Map legacyMap, Map> targetSupplierMap) { + if(legacyMap == null) + return; + + // this transformation is for backward compatibility of existing code + for(Map.Entry entry: legacyMap.entrySet()) { + String key = entry.getKey(); + String converterClassName = entry.getValue(); + ConverterSupplierByClassName converterSupplierByClassName = new ConverterSupplierByClassName(key, converterClassName); + converterSupplierByClassName.setContext(getContext()); + targetSupplierMap.put(key, converterSupplierByClassName); } + } public void start() {