From a496a040fab5dae285bccc87f8431941ed390c5e Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Mon, 7 Oct 2024 22:23:32 +0200 Subject: [PATCH] adding http scan capability, had to move tests Signed-off-by: Ceki Gulcu --- logback-classic-blackbox/pom.xml | 16 + .../joran/roct/inclusion/inner0.xml | 0 .../joran/roct/inclusion/topByResource.xml | 2 +- .../joran/roct/inclusion/topLevel0.xml | 4 +- .../test/blackboxInput}/joran/roct/scan 1.xml | 0 .../joran/roct/scan_logback_474.xml | 4 +- .../joran/roct/scan_period_default.xml | 0 .../issue/lbclassic135/LoggingRunnable.java | 8 +- .../lbclassic135/LoggingToFileThroughput.java | 38 +- .../joran/ChangeDetectedListener.java | 7 +- ...urationEndedSuccessfullyEventListener.java | 4 +- .../joran/ReconfigurationDoneListener.java | 5 +- ...tionTaskRegisteredConfigEventListener.java | 5 +- .../joran/ReconfigureOnChangeTaskHarness.java | 6 +- .../joran/ReconfigureOnChangeTaskTest.java | 99 ++-- .../joran}/RecursivelyLoggingAppender474.java | 5 +- .../blackbox}/joran/UpdaterRunnable.java | 4 +- .../joran/spi/ConfigEmbeddedJetty.java | 68 +++ .../blackbox/joran/spi/ConfigFileServlet.java | 91 ++++ .../joran/spi/ConfigurationWatchListTest.java | 149 ++++++ .../src/test/java/module-info.java | 6 + .../src/test/resources/asResource/inner1.xml | 0 .../classic/joran/PropertiesConfigurator.java | 10 +- .../joran/ReconfigureOnChangeTask.java | 53 +- logback-classic/src/test/input/fqcn.txt | 10 +- .../LoggerContextConcurrentResetTest.java | 4 +- .../classic/LoggerContextPerfTest.java | 2 +- .../lbclassic135/lbclassic139/Accessor.java | 2 +- .../lbclassic135/lbclassic139/Worker.java | 2 +- .../SelectiveDateFormattingRunnable.java | 2 +- .../joran/PropertiesConfiguratorTest.java | 23 + .../turbo/ReconfigureOnChangeTest.java | 455 ------------------ .../classic/turbo/ReconfigurePerf.java | 95 ---- logback-core-blackbox/pom.xml | 1 - .../src/test/java/module-info.java | 2 - .../ch/qos/logback/core/CoreConstants.java | 4 +- .../logback/core/OutputStreamAppender.java | 9 +- .../joran/spi/ConfigurationWatchList.java | 166 ++++++- .../qos/logback/core/joran/spi/HttpUtil.java | 137 ++++++ .../util/ConfigurationWatchListUtil.java | 13 +- .../model/processor/IncludeModelHandler.java | 1 - .../AbstractMultiThreadedHarness.java | 6 +- .../testUtil}/RunnableWithCounterAndDone.java | 6 +- .../ch/qos/logback/core/util/MD5Util.java | 61 +++ .../core/FileAppenderResilienceTest.java | 2 +- .../PrudentFileAppenderInterruptTest.java | 2 +- .../core/contention/MultiThreadedHarness.java | 2 + .../ThreadedThroughputCalculator.java | 2 + .../WaitOnExecutionMultiThreadedHarness.java | 2 + .../logback/core/issue/LockThroughput.java | 2 +- .../logback/core/issue/NoLockThroughput.java | 2 +- .../core/issue/SelectiveLockRunnable.java | 2 +- .../joran/spi/ConfigurationWatchListTest.java | 4 +- .../rolling/MultiThreadedRollingTest.java | 2 +- .../logback/core/util/InvocationGateTest.java | 4 +- .../ch/qos/logback/core/util/MD5Test.java | 34 ++ pom.xml | 1 + 57 files changed, 937 insertions(+), 709 deletions(-) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/inclusion/inner0.xml (100%) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/inclusion/topByResource.xml (64%) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/inclusion/topLevel0.xml (63%) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/scan 1.xml (100%) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/scan_logback_474.xml (66%) rename {logback-classic/src/test/input => logback-classic-blackbox/src/test/blackboxInput}/joran/roct/scan_period_default.xml (100%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/issue/lbclassic135/LoggingRunnable.java (86%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/issue/lbclassic135/LoggingToFileThroughput.java (80%) mode change 100755 => 100644 rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/ChangeDetectedListener.java (81%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/PartialConfigurationEndedSuccessfullyEventListener.java (84%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/ReconfigurationDoneListener.java (89%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/ReconfigurationTaskRegisteredConfigEventListener.java (88%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/ReconfigureOnChangeTaskHarness.java (90%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/ReconfigureOnChangeTaskTest.java (90%) mode change 100755 => 100644 rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran}/RecursivelyLoggingAppender474.java (86%) rename {logback-classic/src/test/java/ch/qos/logback/classic => logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox}/joran/UpdaterRunnable.java (96%) create mode 100644 logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigEmbeddedJetty.java create mode 100644 logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigFileServlet.java create mode 100644 logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigurationWatchListTest.java rename {logback-classic => logback-classic-blackbox}/src/test/resources/asResource/inner1.xml (100%) delete mode 100755 logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java delete mode 100644 logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java create mode 100644 logback-core/src/main/java/ch/qos/logback/core/joran/spi/HttpUtil.java rename logback-core/src/{test/java/ch/qos/logback/core/contention => main/java/ch/qos/logback/core/testUtil}/AbstractMultiThreadedHarness.java (92%) rename logback-core/src/{test/java/ch/qos/logback/core/contention => main/java/ch/qos/logback/core/testUtil}/RunnableWithCounterAndDone.java (89%) create mode 100644 logback-core/src/main/java/ch/qos/logback/core/util/MD5Util.java create mode 100644 logback-core/src/test/java/ch/qos/logback/core/util/MD5Test.java diff --git a/logback-classic-blackbox/pom.xml b/logback-classic-blackbox/pom.xml index b4d7440b8e..91f6b34b3e 100644 --- a/logback-classic-blackbox/pom.xml +++ b/logback-classic-blackbox/pom.xml @@ -22,9 +22,24 @@ logback-classic + + org.eclipse.jetty + jetty-server + ${jetty.version} + test + + + + org.eclipse.jetty.ee10 + jetty-ee10-servlet + ${jetty.version} + + + jakarta.servlet jakarta.servlet-api + 6.0.0 @@ -66,6 +81,7 @@ + diff --git a/logback-classic/src/test/input/joran/roct/inclusion/inner0.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/inner0.xml similarity index 100% rename from logback-classic/src/test/input/joran/roct/inclusion/inner0.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/inner0.xml diff --git a/logback-classic/src/test/input/joran/roct/inclusion/topByResource.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topByResource.xml similarity index 64% rename from logback-classic/src/test/input/joran/roct/inclusion/topByResource.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topByResource.xml index ad450cf6d0..683f17d436 100644 --- a/logback-classic/src/test/input/joran/roct/inclusion/topByResource.xml +++ b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topByResource.xml @@ -2,7 +2,7 @@ - + diff --git a/logback-classic/src/test/input/joran/roct/inclusion/topLevel0.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topLevel0.xml similarity index 63% rename from logback-classic/src/test/input/joran/roct/inclusion/topLevel0.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topLevel0.xml index 77ebde0433..ab691e2248 100644 --- a/logback-classic/src/test/input/joran/roct/inclusion/topLevel0.xml +++ b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/inclusion/topLevel0.xml @@ -3,7 +3,7 @@ - + - \ No newline at end of file + diff --git a/logback-classic/src/test/input/joran/roct/scan 1.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan 1.xml similarity index 100% rename from logback-classic/src/test/input/joran/roct/scan 1.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan 1.xml diff --git a/logback-classic/src/test/input/joran/roct/scan_logback_474.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan_logback_474.xml similarity index 66% rename from logback-classic/src/test/input/joran/roct/scan_logback_474.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan_logback_474.xml index f1e5918c0b..29ecc5d289 100755 --- a/logback-classic/src/test/input/joran/roct/scan_logback_474.xml +++ b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan_logback_474.xml @@ -1,7 +1,7 @@ - + @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/logback-classic/src/test/input/joran/roct/scan_period_default.xml b/logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan_period_default.xml similarity index 100% rename from logback-classic/src/test/input/joran/roct/scan_period_default.xml rename to logback-classic-blackbox/src/test/blackboxInput/joran/roct/scan_period_default.xml diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingRunnable.java similarity index 86% rename from logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingRunnable.java index 2b8f6f4226..a99b6f2c47 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingRunnable.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingRunnable.java @@ -1,6 +1,6 @@ -/** +/* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, QOS.ch. All rights reserved. + * 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 @@ -11,10 +11,10 @@ * 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.issue.lbclassic135; +package ch.qos.logback.classic.blackbox.issue.lbclassic135; import org.slf4j.Logger; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; public class LoggingRunnable extends RunnableWithCounterAndDone { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThroughput.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingToFileThroughput.java old mode 100755 new mode 100644 similarity index 80% rename from logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThroughput.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingToFileThroughput.java index 1b8ee15214..e6fa5731a4 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/LoggingToFileThroughput.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/issue/lbclassic135/LoggingToFileThroughput.java @@ -1,6 +1,6 @@ -/** +/* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, QOS.ch. All rights reserved. + * 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 @@ -11,15 +11,15 @@ * 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.issue.lbclassic135; +package ch.qos.logback.classic.blackbox.issue.lbclassic135; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; -import ch.qos.logback.core.contention.ThreadedThroughputCalculator; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; +//import ch.qos.logback.core.contention.ThreadedThroughputCalculator; /** * Short sample code testing the throughput of a fair lock. @@ -33,20 +33,20 @@ public class LoggingToFileThroughput { public static void main(String args[]) throws InterruptedException { - ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator(OVERALL_DURATION_IN_MILLIS); - tp.printEnvironmentInfo("lbclassic135 LoggingToFileThrouhput"); - - LoggerContext lc = new LoggerContext(); - Logger logger = buildLoggerContext(lc); - - for (int i = 0; i < 2; i++) { - tp.execute(buildArray(logger)); - } - - RunnableWithCounterAndDone[] runnnableArray = buildArray(logger); - tp.execute(runnnableArray); - tp.printThroughput(runnnableArray, "File: "); - lc.stop(); +// ThreadedThroughputCalculator tp = new ThreadedThroughputCalculator(OVERALL_DURATION_IN_MILLIS); +// tp.printEnvironmentInfo("lbclassic135 LoggingToFileThrouhput"); +// +// LoggerContext lc = new LoggerContext(); +// Logger logger = buildLoggerContext(lc); +// +// for (int i = 0; i < 2; i++) { +// tp.execute(buildArray(logger)); +// } +// +// RunnableWithCounterAndDone[] runnnableArray = buildArray(logger); +// tp.execute(runnnableArray); +// tp.printThroughput(runnnableArray, "File: "); +// lc.stop(); } static Logger buildLoggerContext(LoggerContext lc) { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ChangeDetectedListener.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ChangeDetectedListener.java similarity index 81% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/ChangeDetectedListener.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ChangeDetectedListener.java index aa070ee502..805e18e13f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ChangeDetectedListener.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ChangeDetectedListener.java @@ -1,6 +1,6 @@ /* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2022, QOS.ch. All rights reserved. + * 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 @@ -12,8 +12,9 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; +import ch.qos.logback.classic.joran.ReconfigureOnChangeTask; import ch.qos.logback.core.spi.ConfigurationEvent; import ch.qos.logback.core.spi.ConfigurationEventListener; @@ -33,7 +34,7 @@ class ChangeDetectedListener implements ConfigurationEventListener { public void listen(ConfigurationEvent configurationEvent) { switch (configurationEvent.getEventType()) { case CHANGE_DETECTED: - System.out.println(this.toString() + "#listen Change detected " + configurationEvent +" count="+countDownLatch.getCount()); + //System.out.println(this.toString() + "#listen Change detected " + configurationEvent +" count="+countDownLatch.getCount()); countDownLatch.countDown(); Object data = configurationEvent.getData(); diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/PartialConfigurationEndedSuccessfullyEventListener.java similarity index 84% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/PartialConfigurationEndedSuccessfullyEventListener.java index 19f7e5c230..d11d872dc6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/PartialConfigurationEndedSuccessfullyEventListener.java @@ -12,7 +12,7 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; import ch.qos.logback.core.spi.ConfigurationEvent; import ch.qos.logback.core.spi.ConfigurationEventListener; @@ -31,7 +31,7 @@ class PartialConfigurationEndedSuccessfullyEventListener implements Configuratio public void listen(ConfigurationEvent configurationEvent) { switch (configurationEvent.getEventType()) { case PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY: - System.out.println(this.toString() + "#listen PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY detected " + configurationEvent +" count="+countDownLatch.getCount()); + //System.out.println(this.toString() + "#listen PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY detected " + configurationEvent +" count="+countDownLatch.getCount()); countDownLatch.countDown(); break; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationDoneListener.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationDoneListener.java similarity index 89% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationDoneListener.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationDoneListener.java index 99f3d4b3a7..d7641dadc7 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationDoneListener.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationDoneListener.java @@ -1,6 +1,6 @@ /* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2022, QOS.ch. All rights reserved. + * 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 @@ -12,8 +12,9 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; +import ch.qos.logback.classic.joran.ReconfigureOnChangeTask; import ch.qos.logback.core.spi.ConfigurationEvent; import ch.qos.logback.core.spi.ConfigurationEventListener; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationTaskRegisteredConfigEventListener.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationTaskRegisteredConfigEventListener.java similarity index 88% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationTaskRegisteredConfigEventListener.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationTaskRegisteredConfigEventListener.java index f8b30b91d7..80d21f464b 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigurationTaskRegisteredConfigEventListener.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigurationTaskRegisteredConfigEventListener.java @@ -1,6 +1,6 @@ /* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2022, QOS.ch. All rights reserved. + * 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 @@ -12,8 +12,9 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; +import ch.qos.logback.classic.joran.ReconfigureOnChangeTask; import ch.qos.logback.core.spi.ConfigurationEvent; import ch.qos.logback.core.spi.ConfigurationEventListener; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskHarness.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskHarness.java similarity index 90% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskHarness.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskHarness.java index 34cc0365e6..e48280d186 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskHarness.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskHarness.java @@ -1,6 +1,6 @@ /* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2022, QOS.ch. All rights reserved. + * 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 @@ -12,10 +12,10 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.contention.AbstractMultiThreadedHarness; +import ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness; import ch.qos.logback.core.status.InfoStatus; import java.util.concurrent.CountDownLatch; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskTest.java old mode 100755 new mode 100644 similarity index 90% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskTest.java index c946888a40..60490a03c4 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/ReconfigureOnChangeTaskTest.java @@ -1,61 +1,52 @@ -/** - * Logback: the reliable, generic, fast and flexible logging framework. Copyright (C) 1999-2015, QOS.ch. All rights - * reserved. +/* + * 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 + * 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) + * 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. + * 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.joran; - -import static ch.qos.logback.classic.ClassicTestConstants.JORAN_INPUT_PREFIX; -import static ch.qos.logback.classic.joran.ReconfigureOnChangeTask.DETECTED_CHANGE_IN_CONFIGURATION_FILES; -import static ch.qos.logback.classic.joran.ReconfigureOnChangeTask.FALLING_BACK_TO_SAFE_CONFIGURATION; -import static ch.qos.logback.classic.joran.ReconfigureOnChangeTask.RE_REGISTERING_PREVIOUS_SAFE_CONFIGURATION; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.*; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; +package ch.qos.logback.classic.blackbox.joran; import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.model.processor.ConfigurationModelHandlerFull; -import ch.qos.logback.core.spi.ConfigurationEvent; -import ch.qos.logback.core.spi.ConfigurationEventListener; -import ch.qos.logback.core.status.OnConsoleStatusListener; -import ch.qos.logback.core.status.WarnStatus; -import ch.qos.logback.core.util.StatusPrinter2; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable; +import ch.qos.logback.classic.blackbox.issue.lbclassic135.LoggingRunnable; +import ch.qos.logback.classic.joran.*; +import ch.qos.logback.classic.model.processor.ConfigurationModelHandlerFull; import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.joran.spi.ConfigurationWatchList; import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.spi.ConfigurationEvent; +import ch.qos.logback.core.spi.ConfigurationEventListener; import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.OnConsoleStatusListener; import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.WarnStatus; import ch.qos.logback.core.testUtil.CoreTestConstants; import ch.qos.logback.core.testUtil.FileTestUtil; import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.status.testUtil.StatusChecker; import ch.qos.logback.core.util.StatusPrinter; -import org.junit.jupiter.api.Timeout; +import ch.qos.logback.core.util.StatusPrinter2; +import org.junit.jupiter.api.*; + +import java.io.*; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static ch.qos.logback.classic.blackbox.BlackboxClassicTestConstants.JORAN_INPUT_PREFIX; +import static ch.qos.logback.classic.joran.ReconfigureOnChangeTask.*; +import static org.junit.jupiter.api.Assertions.*; public class ReconfigureOnChangeTaskTest { final static int THREAD_COUNT = 5; @@ -86,6 +77,7 @@ public class ReconfigureOnChangeTaskTest { StatusChecker statusChecker = new StatusChecker(loggerContext); StatusPrinter2 statusPrinter2 = new StatusPrinter2(); + @BeforeAll static public void classSetup() { FileTestUtil.makeTestOutputDir(); @@ -102,7 +94,7 @@ void configure(File file) throws JoranException { jc.doConfigure(file); } - void configure(InputStream is) throws JoranException { + protected void configure(InputStream is) throws JoranException { JoranConfigurator jc = new JoranConfigurator(); jc.setContext(loggerContext); jc.doConfigure(is); @@ -149,7 +141,7 @@ public void scanWithFileInclusion() throws JoranException, IOException, Interrup } @Test - @Timeout(value = TIMEOUT, unit = TimeUnit.SECONDS) + //@Timeout(value = TIMEOUT, unit = TimeUnit.SECONDS) public void scanWithResourceInclusion() throws JoranException, IOException, InterruptedException { File topLevelFile = new File(INCLUSION_SCAN_TOP_BY_RESOURCE_AS_STR); File innerFile = new File(INCLUSION_SCAN_INNER1_AS_STR); @@ -165,7 +157,7 @@ public void propertiesConfigurationTest() throws IOException, JoranException, In String loggerName = "abc"; String propertiesFileStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "roct-" + diff + ".properties"; File propertiesFile = new File(propertiesFileStr); - String configurationStr = ""; + String configurationStr = ""; writeToFile(propertiesFile, PropertiesConfigurator.LOGBACK_LOGGER_PREFIX + loggerName+"=INFO"); configure(asBAIS(configurationStr)); Logger abcLogger = loggerContext.getLogger(loggerName); @@ -185,10 +177,29 @@ public void propertiesConfigurationTest() throws IOException, JoranException, In writeToFile(propertiesFile, PropertiesConfigurator.LOGBACK_LOGGER_PREFIX + loggerName+"=ERROR"); changeDetectedLatch1.await(); configurationDoneLatch1.await(); + assertEquals(Level.ERROR, abcLogger.getLevel()); - statusPrinter2.print(loggerContext); + } + + @Disabled + @Test + void propertiesFromHTTPS() throws InterruptedException, UnsupportedEncodingException, JoranException { + String loggerName = "com.bazinga"; + String propertiesURLStr = "https://www.qos.ch/foo.properties"; + Logger aLogger = loggerContext.getLogger(loggerName); + String configurationStr = ""; + + configure(asBAIS(configurationStr)); + assertEquals(Level.WARN, aLogger.getLevel()); + System.out.println("first phase OK"); + CountDownLatch changeDetectedLatch0 = registerChangeDetectedListener(); + CountDownLatch configurationDoneLatch0 = registerPartialConfigurationEndedSuccessfullyEventListener(); + changeDetectedLatch0.await(); + System.out.println("after changeDetectedLatch0.await();"); + configurationDoneLatch0.await(); + assertEquals(Level.ERROR, aLogger.getLevel()); } // See also http://jira.qos.ch/browse/LOGBACK-338 diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/RecursivelyLoggingAppender474.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/RecursivelyLoggingAppender474.java similarity index 86% rename from logback-classic/src/test/java/ch/qos/logback/classic/RecursivelyLoggingAppender474.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/RecursivelyLoggingAppender474.java index ddd26468e1..6e91f0b402 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/RecursivelyLoggingAppender474.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/RecursivelyLoggingAppender474.java @@ -1,6 +1,6 @@ /* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2022, QOS.ch. All rights reserved. + * 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 @@ -11,8 +11,9 @@ * 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; +package ch.qos.logback.classic.blackbox.joran; +import ch.qos.logback.classic.LoggerContext; import org.slf4j.Logger; import ch.qos.logback.classic.spi.ILoggingEvent; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/UpdaterRunnable.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/UpdaterRunnable.java similarity index 96% rename from logback-classic/src/test/java/ch/qos/logback/classic/joran/UpdaterRunnable.java rename to logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/UpdaterRunnable.java index bee5ca7a57..e5e5302c46 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/UpdaterRunnable.java +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/UpdaterRunnable.java @@ -12,9 +12,9 @@ * as published by the Free Software Foundation. */ -package ch.qos.logback.classic.joran; +package ch.qos.logback.classic.blackbox.joran; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import java.io.File; import java.io.IOException; diff --git a/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigEmbeddedJetty.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigEmbeddedJetty.java new file mode 100644 index 0000000000..5d0f419987 --- /dev/null +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigEmbeddedJetty.java @@ -0,0 +1,68 @@ +/* + * 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.blackbox.joran.spi; + +import jakarta.servlet.http.HttpServlet; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; + +import java.util.HashMap; +import java.util.Map; + +public class ConfigEmbeddedJetty { + + int port; + Server server = new Server(port); + Map servletPathMap = new HashMap<>(); + + public ConfigEmbeddedJetty(int port) { + this.port = port; + } + + public Map getServletMap() { + return servletPathMap; + } + + // new ConfigFileServlet() + public void init() throws Exception { + Server server = new Server(port); + + // Create a handler for the root context + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + + + servletPathMap.forEach( (path, servlet) -> context.addServlet(new ServletHolder(servlet), path)); + + // Set the handler for the server + server.setHandler(context); + + System.out.println("Starting jetty server on port: " + port); + // Start the server + server.start(); + + System.out.println("After Jetty server start(). Joining"); + + while(!server.isStarted()) { + Thread.sleep(10); + } + System.out.println("Jetty server started"); + } + + public void stop() throws Exception { + server.stop(); + } +} diff --git a/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigFileServlet.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigFileServlet.java new file mode 100644 index 0000000000..2258149438 --- /dev/null +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigFileServlet.java @@ -0,0 +1,91 @@ +/* + * 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.blackbox.joran.spi; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +public class ConfigFileServlet extends HttpServlet { + + Map headers = new HashMap(); + static final String DEFAULT_CONTENT = "That was all"; + String contents; + static final String LAST_MODIFIED = "last-modified"; + public final static String CONTENT_KEY = "content"; + + public ConfigFileServlet(String contents) { + this.contents = contents; + } + + public ConfigFileServlet() { + this(DEFAULT_CONTENT); + } + + /** + * Returns data set when {@link #doPost(HttpServletRequest, HttpServletResponse)} was called + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/txt;charset=utf-8"); + + String lastModifiedHeaderValue = headers.get(LAST_MODIFIED); + if(lastModifiedHeaderValue != null) { + response.setHeader(LAST_MODIFIED, lastModifiedHeaderValue); + } + + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println(contents); + } + + /** + * Remembers posted values to be returned when {@link #doGet(HttpServletRequest, HttpServletResponse)} is called. + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Enumeration paramNames = request.getParameterNames(); + while (paramNames.hasMoreElements()) { + String paramName = paramNames.nextElement(); + String[] paramValues = request.getParameterValues(paramName); + // Handle single or multiple values for the parameter + if (paramValues.length >= 1) { + if(CONTENT_KEY.equals(paramName)) { + contents = paramValues[0]; + } else { + headers.put(paramName, paramValues[0]); + } + } + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println(contents); + } + + + } + +} diff --git a/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigurationWatchListTest.java b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigurationWatchListTest.java new file mode 100644 index 0000000000..98c6365fb1 --- /dev/null +++ b/logback-classic-blackbox/src/test/java/ch/qos/logback/classic/blackbox/joran/spi/ConfigurationWatchListTest.java @@ -0,0 +1,149 @@ +/* + * 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.blackbox.joran.spi; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +//import ch.qos.logback.classic.blackbox.joran.ReconfigureOnChangeTaskTest; +//import ch.qos.logback.classic.blackbox.joran.ReconfigureOnChangeTaskTest; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.joran.spi.ConfigurationWatchList; +import ch.qos.logback.core.joran.spi.HttpUtil; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.testUtil.RandomUtil; +import jakarta.servlet.http.HttpServlet; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.CountDownLatch; + +import static org.junit.jupiter.api.Assertions.*; + +public class ConfigurationWatchListTest { + + +// static String BAZINGA_LOGGER_0 = "logback.logger.com.bazinga=WARN"; +// static String BAZINGA_LOGGER_1 = "logback.logger.com.bazinga=ERROR" +// +// int randomPort = RandomUtil.getRandomServerPort(); +// ConfigEmbeddedJetty configEmbeddedJetty; +// LoggerContext loggerContext = new LoggerContext(); +// ConfigurationWatchList cwl = new ConfigurationWatchList(); +// String urlString = "http://127.0.0.1:"+randomPort+"/"; +// +// @BeforeEach +// public void setUp() throws Exception { +// Logger rootLogger = (Logger) LoggerFactory.getLogger( Logger.ROOT_LOGGER_NAME ); +// rootLogger.setLevel(Level.INFO); +// +// configEmbeddedJetty = new ConfigEmbeddedJetty(randomPort); +// +// cwl.setContext(loggerContext); +// +// HttpServlet configServlet = new ConfigFileServlet(); +// configEmbeddedJetty.getServletMap().put("/", configServlet); +// //configEmbeddedJetty.getServletMap().put("/mod", configServlet); +// +// configEmbeddedJetty.init(); +// +// } +// +// @AfterEach +// public void tearDown() throws Exception { +// configEmbeddedJetty.stop(); +// } +// +// @Test +// public void testInfrastructure() throws MalformedURLException { +// HttpUtil httpGetUtil0 = new HttpUtil(HttpUtil.RequestMethod.GET, urlString); +// +// HttpURLConnection getConnection0 = httpGetUtil0.connectTextTxt(); +// String response = httpGetUtil0.readResponse(getConnection0); +// assertNotNull(response); +// Assertions.assertEquals(ConfigFileServlet.DEFAULT_CONTENT, response); +// +// HttpUtil httpPostUtil1 = new HttpUtil(HttpUtil.RequestMethod.POST, urlString); +// HttpURLConnection postConnection1 = httpPostUtil1.connectTextTxt(); +// String setResponse1 = "bla bla"; +// httpPostUtil1.post(postConnection1, ConfigFileServlet.CONTENT_KEY+ CoreConstants.EQUALS_CHAR+setResponse1); +// +// String response1 = httpPostUtil1.readResponse(postConnection1); +// assertEquals(response1, setResponse1); +// //System.out.println( "POST response1="+response1); +// HttpUtil httpGetUtil2 = new HttpUtil(HttpUtil.RequestMethod.GET, urlString); +// +// HttpURLConnection getConnection2 = httpGetUtil2.connectTextTxt(); +// String response2 = httpGetUtil2.readResponse(getConnection2); +// assertEquals(response1, response2); +// +// } +// +// @Test +// public void smoke() throws MalformedURLException { +// URL url = new URL(urlString); +// cwl.addToWatchList(url); +// URL changedURL0 = cwl.changeDetectedInURL(); +// assertNull(changedURL0); +// HttpUtil httpPostUtil1 = new HttpUtil(HttpUtil.RequestMethod.POST, urlString); +// HttpURLConnection postConnection1 = httpPostUtil1.connectTextTxt(); +// String setResponse1 = "bla bla"; +// httpPostUtil1.post(postConnection1, ConfigFileServlet.CONTENT_KEY+ CoreConstants.EQUALS_CHAR+setResponse1); +// +// String response1 = httpPostUtil1.readResponse(postConnection1); +// assertEquals(response1, setResponse1); +// URL changedURL1 = cwl.changeDetectedInURL(); +// assertEquals(urlString, changedURL1.toString()); +// +// URL changedURL2 = cwl.changeDetectedInURL(); +// assertNull(changedURL2); +// +// URL changedURL3 = cwl.changeDetectedInURL(); +// assertNull(changedURL3); +// } +// +// +// @Test +// public void propertiesFromHTTP() throws UnsupportedEncodingException, JoranException { +// String loggerName = "com.bazinga"; +// String propertiesURLStr = "https://127.0.0.1:"+randomPort+"/"; +// Logger aLogger = loggerContext.getLogger(loggerName); +// String configurationStr = ""; +// +// configure(asBAIS(configurationStr)); +// +// assertEquals(Level.WARN, aLogger.getLevel()); +// System.out.println("first phase OK"); +// CountDownLatch changeDetectedLatch0 = registerChangeDetectedListener(); +// CountDownLatch configurationDoneLatch0 = registerPartialConfigurationEndedSuccessfullyEventListener(); +// +// changeDetectedLatch0.await(); +// System.out.println("after changeDetectedLatch0.await();"); +// configurationDoneLatch0.await(); +// assertEquals(Level.ERROR, aLogger.getLevel()); +// } +// + +} diff --git a/logback-classic-blackbox/src/test/java/module-info.java b/logback-classic-blackbox/src/test/java/module-info.java index afde459b40..844afc4caa 100644 --- a/logback-classic-blackbox/src/test/java/module-info.java +++ b/logback-classic-blackbox/src/test/java/module-info.java @@ -12,12 +12,18 @@ requires org.junit.jupiter.engine; requires org.slf4j; + requires org.eclipse.jetty.ee10.servlet; + requires java.logging; exports ch.qos.logback.classic.blackbox.boolex; exports ch.qos.logback.classic.blackbox.joran; exports ch.qos.logback.classic.blackbox.joran.conditional; + exports ch.qos.logback.classic.blackbox.joran.spi; exports ch.qos.logback.classic.blackbox.html; exports ch.qos.logback.classic.blackbox.net; + + // resources in named modules are accessible only if opened + opens asResource; } \ No newline at end of file diff --git a/logback-classic/src/test/resources/asResource/inner1.xml b/logback-classic-blackbox/src/test/resources/asResource/inner1.xml similarity index 100% rename from logback-classic/src/test/resources/asResource/inner1.xml rename to logback-classic-blackbox/src/test/resources/asResource/inner1.xml diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertiesConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertiesConfigurator.java index f143122d3f..db2e7410fe 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertiesConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertiesConfigurator.java @@ -43,7 +43,12 @@ public int compare(String o1, String o2) { int len1 = o1 == null ? 0 : o1.length(); int len2 = o2 == null ? 0 : o2.length(); // longer strings first - return len2 - len1; + int diff = len2 - len1; + if (diff != 0) { + return diff; + } else { + return o2.compareTo(o1); + } } }; @@ -51,7 +56,7 @@ public int compare(String o1, String o2) { static final String LOGBACK_ROOT_LOGGER_PREFIX = LOGBACK_PREFIX + DOT + "root"; static final int LOGBACK_ROOT_LOGGER_PREFIX_LENGTH = LOGBACK_ROOT_LOGGER_PREFIX.length(); - static final String LOGBACK_LOGGER_PREFIX = LOGBACK_PREFIX + DOT + "logger" + DOT; + public static final String LOGBACK_LOGGER_PREFIX = LOGBACK_PREFIX + DOT + "logger" + DOT; static final int LOGBACK_LOGGER_PREFIX_LENGTH = LOGBACK_LOGGER_PREFIX.length(); VariableSubstitutionsHelper variableSubstitutionsHelper; @@ -132,7 +137,6 @@ void configureRootLogger(Map instructionMap) { } void configureLoggers(Map instructionMap) { - for (String key : instructionMap.keySet()) { if (key.startsWith(LOGBACK_LOGGER_PREFIX)) { String loggerName = key.substring(LOGBACK_LOGGER_PREFIX_LENGTH); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java index d5945eb1ca..a59e8e1121 100755 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java @@ -35,8 +35,8 @@ public class ReconfigureOnChangeTask extends ContextAwareBase implements Runnable { public static final String DETECTED_CHANGE_IN_CONFIGURATION_FILES = "Detected change in configuration files."; - static final String RE_REGISTERING_PREVIOUS_SAFE_CONFIGURATION = "Re-registering previous fallback configuration once more as a fallback configuration point"; - static final String FALLING_BACK_TO_SAFE_CONFIGURATION = "Given previous errors, falling back to previously registered safe configuration."; + public static final String RE_REGISTERING_PREVIOUS_SAFE_CONFIGURATION = "Re-registering previous fallback configuration once more as a fallback configuration point"; + public static final String FALLING_BACK_TO_SAFE_CONFIGURATION = "Given previous errors, falling back to previously registered safe configuration."; long birthdate = System.currentTimeMillis(); List listeners = null; @@ -53,28 +53,44 @@ public void run() { return; } - List filesToWatch = configurationWatchList.getCopyOfFileWatchList(); - if (filesToWatch == null || filesToWatch.isEmpty()) { - addInfo("Empty watch file list. Disabling "); + if (configurationWatchList.emptyWatchLists()) { + addInfo("Both watch lists are empty. Disabling "); return; } - File changedFile = configurationWatchList.changeDetected(); - if (changedFile == null) { + + File changedFile = configurationWatchList.changeDetectedInFile(); + URL changedURL = configurationWatchList.changeDetectedInURL(); + + if (changedFile == null && changedURL == null) { return; } - context.fireConfigurationEvent(ConfigurationEvent.newConfigurationChangeDetectedEvent(this)); + context.fireConfigurationEvent(ConfigurationEvent.newConfigurationChangeDetectedEvent(this)); addInfo(DETECTED_CHANGE_IN_CONFIGURATION_FILES); - addInfo(CoreConstants.RESET_MSG_PREFIX + "named [" + context.getName() + "]"); + if(changedFile != null) { + changeInFile(changedFile, configurationWatchList); + } + + if(changedURL != null) { + changeInURL(changedURL); + } + } + + private void changeInURL(URL url) { + String path = url.getPath(); + if(path.endsWith(PROPERTIES_FILE_EXTENSION)) { + runPropertiesConfigurator(url); + } + } + private void changeInFile(File changedFile, ConfigurationWatchList configurationWatchList) { if(changedFile.getName().endsWith(PROPERTIES_FILE_EXTENSION)) { runPropertiesConfigurator(changedFile); - // no further processing return; } // ======== fuller processing below - + addInfo(CoreConstants.RESET_MSG_PREFIX + "named [" + context.getName() + "]"); cancelFutureInvocationsOfThisTaskInstance(); URL mainConfigurationURL = configurationWatchList.getMainURL(); @@ -84,18 +100,23 @@ public void run() { } else if (mainConfigurationURL.toString().endsWith("groovy")) { addError("Groovy configuration disabled due to Java 9 compilation issues."); } - //fireDoneReconfiguring(); } - private void runPropertiesConfigurator(File changedFile) { - addInfo("Will run PropertyConfigurator on "+changedFile.getAbsolutePath()); + private void runPropertiesConfigurator(Object changedObject) { + addInfo("Will run PropertyConfigurator on "+changedObject); PropertiesConfigurator propertiesConfigurator = new PropertiesConfigurator(); propertiesConfigurator.setContext(context); try { - propertiesConfigurator.doConfigure(changedFile); + if(changedObject instanceof File) { + File changedFile = (File) changedObject; + propertiesConfigurator.doConfigure(changedFile); + } else if(changedObject instanceof URL) { + URL changedURL = (URL) changedObject; + propertiesConfigurator.doConfigure(changedURL); + } context.fireConfigurationEvent(newPartialConfigurationEndedSuccessfullyEvent(this)); } catch (JoranException e) { - addError("Failed to reload "+ changedFile); + addError("Failed to reload "+ changedObject); } } diff --git a/logback-classic/src/test/input/fqcn.txt b/logback-classic/src/test/input/fqcn.txt index 281b302164..65a6500c34 100644 --- a/logback-classic/src/test/input/fqcn.txt +++ b/logback-classic/src/test/input/fqcn.txt @@ -322,8 +322,8 @@ ch.qos.logback.classic.html.XHTMLEntityResolver ch.qos.logback.classic.issue.lbclassic135.lbclassic139.Accessor ch.qos.logback.classic.issue.lbclassic135.lbclassic139.LB139_DeadlockTest ch.qos.logback.classic.issue.lbclassic135.lbclassic139.Worker -ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable -ch.qos.logback.classic.issue.lbclassic135.LoggingToFileThroughput +ch.qos.logback.classic.blackbox.issue.lbclassic135.LoggingRunnable +ch.qos.logback.classic.blackbox.issue.lbclassic135.LoggingToFileThroughput ch.qos.logback.classic.issue.lbclassic180.HtmlEscapedMessageConverter ch.qos.logback.classic.issue.lbclassic180.Main ch.qos.logback.classic.issue.lbclassic323.Barebones @@ -353,7 +353,7 @@ ch.qos.logback.classic.jmx.JMXConfiguratorTest ch.qos.logback.classic.blackbox.joran.conditional.ConditionalTest ch.qos.logback.classic.joran.EvaluatorJoranTest ch.qos.logback.classic.joran.JoranConfiguratorTest -ch.qos.logback.classic.joran.ReconfigureOnChangeTaskTest +ch.qos.logback.classic.blackbox.joran.ReconfigureOnChangeTaskTest ch.qos.logback.classic.jul.LevelChangePropagatorTest ch.qos.logback.classic.layout.TTLLLayoutTest ch.qos.logback.classic.LevelTest @@ -846,9 +846,9 @@ ch.qos.logback.core.testUtil.XTeeOutputStream ch.qos.logback.core.AsyncAppenderBaseTest ch.qos.logback.core.BasicStatusManagerTest ch.qos.logback.core.boolex.MatcherTest -ch.qos.logback.core.contention.AbstractMultiThreadedHarness +ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness ch.qos.logback.core.contention.MultiThreadedHarness -ch.qos.logback.core.contention.RunnableWithCounterAndDone +ch.qos.logback.core.testUtil.RunnableWithCounterAndDone ch.qos.logback.core.contention.ThreadedThroughputCalculator ch.qos.logback.core.contention.WaitOnExecutionMultiThreadedHarness ch.qos.logback.core.ContextBaseTest diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextConcurrentResetTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextConcurrentResetTest.java index 20353c8e03..56ba846b4d 100755 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextConcurrentResetTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextConcurrentResetTest.java @@ -5,8 +5,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import ch.qos.logback.core.contention.AbstractMultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.status.testUtil.StatusChecker; import org.junit.jupiter.api.Timeout; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextPerfTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextPerfTest.java index f8362bca5d..29cc827e70 100755 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextPerfTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerContextPerfTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.Test; import ch.qos.logback.classic.corpus.CorpusModel; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.contention.ThreadedThroughputCalculator; @Disabled diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Accessor.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Accessor.java index 62b6c53fb9..5c999d3ab0 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Accessor.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Accessor.java @@ -16,7 +16,7 @@ import org.slf4j.Logger; import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; /** * diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Worker.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Worker.java index b6dd4874e2..109e0e467a 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Worker.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic135/lbclassic139/Worker.java @@ -16,7 +16,7 @@ import org.slf4j.Logger; import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; /** * diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java index 84f54b9014..0be0ca3b30 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/issue/lbclassic36/SelectiveDateFormattingRunnable.java @@ -17,7 +17,7 @@ //import org.joda.time.format.DateTimeFormat; //import org.joda.time.format.DateTimeFormatter; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; /** * A runnable which behaves differently depending on the desired locking model. diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PropertiesConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PropertiesConfiguratorTest.java index 7c3139804a..d3d6596d3f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PropertiesConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PropertiesConfiguratorTest.java @@ -14,9 +14,11 @@ package ch.qos.logback.classic.joran; +import ch.qos.logback.classic.ClassicConstants; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.JoranConstants; import ch.qos.logback.core.util.StatusPrinter2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -72,6 +74,27 @@ public void withVariables() { } + @Test + void inheritedLevelString() { + String loggerName0 = "com.abc.some0"; + String loggerName1 = "com.abc.some1"; + + Logger aLogger0 = lc.getLogger(loggerName0); + aLogger0.setLevel(Level.ERROR); + + Logger aLogger1 = lc.getLogger(loggerName1); + aLogger1.setLevel(Level.WARN); + + + props.setProperty(PropertiesConfigurator.LOGBACK_LOGGER_PREFIX + loggerName0, JoranConstants.INHERITED); + props.setProperty(PropertiesConfigurator.LOGBACK_LOGGER_PREFIX + loggerName1, JoranConstants.NULL); + pc.doConfigure(props); + + //statusPrinter2.print(lc); + assertEquals(null, aLogger0.getLevel()); + assertEquals(null, aLogger1.getLevel()); + } + String asVar(String v) { return "${"+v+"}"; } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java deleted file mode 100755 index 141aa94985..0000000000 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java +++ /dev/null @@ -1,455 +0,0 @@ -/** - * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, 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.turbo; - -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.TurboFilterList; -import ch.qos.logback.core.CoreConstants; -import ch.qos.logback.core.contention.AbstractMultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; -import ch.qos.logback.core.contention.WaitOnExecutionMultiThreadedHarness; -import ch.qos.logback.core.joran.spi.ConfigurationWatchList; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; -import ch.qos.logback.core.status.InfoStatus; -import ch.qos.logback.core.status.Status; -import ch.qos.logback.core.testUtil.CoreTestConstants; -import ch.qos.logback.core.testUtil.EnvUtilForTests; -import ch.qos.logback.core.testUtil.FileTestUtil; -import ch.qos.logback.core.testUtil.RandomUtil; -import ch.qos.logback.core.status.testUtil.StatusChecker; -import ch.qos.logback.core.util.StatusPrinter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -@Disabled -public class ReconfigureOnChangeTest { - final static int THREAD_COUNT = 5; - final static int LOOP_LEN = 1000 * 1000; - - int diff = RandomUtil.getPositiveInt(); - - // the space in the file name mandated by - // http://jira.qos.ch/browse/LBCORE-119 - final static String SCAN1_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan 1.xml"; - - final static String G_SCAN1_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan 1.groovy"; - - final static String SCAN_LOGBACK_474_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan_logback_474.xml"; - - final static String INCLUSION_SCAN_TOPLEVEL0_AS_STR = ClassicTestConstants.INPUT_PREFIX - + "turbo/inclusion/topLevel0.xml"; - - final static String INCLUSION_SCAN_TOP_BY_RESOURCE_AS_STR = ClassicTestConstants.INPUT_PREFIX - + "turbo/inclusion/topByResource.xml"; - - final static String INCLUSION_SCAN_INNER0_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/inclusion/inner0.xml"; - - final static String INCLUSION_SCAN_INNER1_AS_STR = "target/test-classes/asResource/inner1.xml"; - - // it actually takes time for Windows to propagate file modification changes - // values below 100 milliseconds can be problematic the same propagation - // latency occurs in Linux but is even larger (>600 ms) - // final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 60; - - int sleepBetweenUpdates = 100; - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(this.getClass()); - ExecutorService executorService = loggerContext.getScheduledExecutorService(); - - StatusChecker checker = new StatusChecker(loggerContext); - AbstractMultiThreadedHarness harness; - - ThreadPoolExecutor executor = (ThreadPoolExecutor) loggerContext.getScheduledExecutorService(); - - int expectedResets = 2; - - @BeforeAll - static public void classSetup() { - FileTestUtil.makeTestOutputDir(); - } - - @BeforeEach - public void setUp() { - harness = new WaitOnExecutionMultiThreadedHarness(executor, expectedResets); - } - - @AfterEach - public void tearDown() { - } - - void configure(File file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(file); - } - - void configure(InputStream is) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(is); - } - -// void gConfigure(File file) throws JoranException { -// GafferConfigurator gc = new GafferConfigurator(loggerContext); -// gc.run(file); -// } - - RunnableWithCounterAndDone[] buildRunnableArray(File configFile, UpdateType updateType) { - RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[THREAD_COUNT]; - rArray[0] = new Updater(configFile, updateType); - for (int i = 1; i < THREAD_COUNT; i++) { - rArray[i] = new LoggingRunnable(logger); - } - return rArray; - } - - // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter - @Test - public void installFilter() throws JoranException, IOException, InterruptedException { - File file = new File(SCAN1_FILE_AS_STR); - configure(file); - List fileList = getConfigurationFileList(loggerContext); - assertThatListContainsFile(fileList, file); - assertThatFirstFilterIsROCF(); - StatusPrinter.print(loggerContext); - } - -// @Test -// public void gafferInstallFilter() throws JoranException, IOException, InterruptedException { -// File file = new File(G_SCAN1_FILE_AS_STR); -// gConfigure(file); -// List fileList = getConfigurationFileList(loggerContext); -// assertThatListContainsFile(fileList, file); -// assertThatFirstFilterIsROCF(); -// -// rocfDetachReconfigurationToNewThreadAndAwaitTermination(); -// -// fileList = getConfigurationFileList(loggerContext); -// assertThatListContainsFile(fileList, file); -// assertThatFirstFilterIsROCF(); -// -// // check that rcof filter installed on two occasions -// assertEquals(2, checker.matchCount("Will scan for changes in")); -// } - - private void rocfDetachReconfigurationToNewThreadAndAwaitTermination() throws InterruptedException { - ReconfigureOnChangeFilter reconfigureOnChangeFilter = (ReconfigureOnChangeFilter) getFirstTurboFilter(); - reconfigureOnChangeFilter.detachReconfigurationToNewThread(); - executorService.shutdown(); - executorService.awaitTermination(1000, TimeUnit.MILLISECONDS); - } - - List getConfigurationFileList(LoggerContext context) { - ConfigurationWatchList configurationWatchList = ConfigurationWatchListUtil - .getConfigurationWatchList(loggerContext); - return configurationWatchList.getCopyOfFileWatchList(); - } - - @Test - @Timeout(value = 4) - public void scanWithFileInclusion() throws JoranException, IOException, InterruptedException { - File topLevelFile = new File(INCLUSION_SCAN_TOPLEVEL0_AS_STR); - File innerFile = new File(INCLUSION_SCAN_INNER0_AS_STR); - configure(topLevelFile); - List fileList = getConfigurationFileList(loggerContext); - assertThatListContainsFile(fileList, topLevelFile); - assertThatListContainsFile(fileList, innerFile); - } - - @Test - @Timeout(value = 4, unit= TimeUnit.SECONDS) - public void scanWithResourceInclusion() throws JoranException, IOException, InterruptedException { - File topLevelFile = new File(INCLUSION_SCAN_TOP_BY_RESOURCE_AS_STR); - File innerFile = new File(INCLUSION_SCAN_INNER1_AS_STR); - configure(topLevelFile); - - List fileList = getConfigurationFileList(loggerContext); - assertThatListContainsFile(fileList, topLevelFile); - assertThatListContainsFile(fileList, innerFile); - } - - // See also http://jira.qos.ch/browse/LOGBACK-338 - @Test - public void includeScanViaInputStreamSuppliedConfigFile() throws IOException, JoranException, InterruptedException { - String configurationStr = ""; - configure(new ByteArrayInputStream(configurationStr.getBytes("UTF-8"))); - - ConfigurationWatchList configurationWatchList = ConfigurationWatchListUtil - .getConfigurationWatchList(loggerContext); - assertNull(configurationWatchList.getMainURL()); - - ReconfigureOnChangeFilter reconfigureOnChangeFilter = (ReconfigureOnChangeFilter) getFirstTurboFilter(); - // without a top level file, reconfigureOnChangeFilter should not start - assertFalse(reconfigureOnChangeFilter.isStarted()); - } - - @Test - @Timeout(value = 4, unit= TimeUnit.SECONDS) - public void fallbackToSafe() throws IOException, JoranException, InterruptedException { - String path = CoreTestConstants.OUTPUT_DIR_PREFIX + "reconfigureOnChangeConfig_fallbackToSafe-" + diff + ".xml"; - File topLevelFile = new File(path); - writeToFile(topLevelFile, - " "); - configure(topLevelFile); - - writeToFile(topLevelFile, - "\n" + " "); - - rocfDetachReconfigurationToNewThreadAndAwaitTermination(); - - checker.assertContainsMatch(Status.WARN, "Falling back to previously registered safe configuration."); - checker.assertContainsMatch(Status.INFO, "Re-registering previous fallback configuration once more"); - - assertThatFirstFilterIsROCF(); - } - - @Test - @Timeout(value = 4) - public void fallbackToSafeWithIncludedFile() throws IOException, JoranException, InterruptedException { - String topLevelFileAsStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "reconfigureOnChangeConfig_top-" + diff - + ".xml"; - String innerFileAsStr = CoreTestConstants.OUTPUT_DIR_PREFIX + "reconfigureOnChangeConfig_inner-" + diff - + ".xml"; - File topLevelFile = new File(topLevelFileAsStr); - writeToFile(topLevelFile, " "); - - File innerFile = new File(innerFileAsStr); - writeToFile(innerFile, " "); - configure(topLevelFile); - writeToFile(innerFile, "\n\n"); - rocfDetachReconfigurationToNewThreadAndAwaitTermination(); - - checker.assertContainsMatch(Status.WARN, "Falling back to previously registered safe configuration."); - checker.assertContainsMatch(Status.INFO, "Re-registering previous fallback configuration once more"); - - assertThatFirstFilterIsROCF(); - } - - // check for deadlocks - @Test - @Timeout(value = 4) - public void scan_LOGBACK_474() throws JoranException, IOException, InterruptedException { - File file = new File(SCAN_LOGBACK_474_FILE_AS_STR); - configure(file); - - RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(file, UpdateType.TOUCH); - harness.execute(runnableArray); - - loggerContext.getStatusManager().add(new InfoStatus("end of execution ", this)); - - verify(expectedResets); - } - - private void assertThatListContainsFile(List fileList, File file) { - // conversion to absolute file seems to work nicely - assertTrue(fileList.contains(file.getAbsoluteFile())); - } - - private TurboFilter getFirstTurboFilter() { - TurboFilterList turboFilterList = loggerContext.getTurboFilterList(); - return turboFilterList.get(0); - } - - private void assertThatFirstFilterIsROCF() { - assertTrue(getFirstTurboFilter() instanceof ReconfigureOnChangeFilter); - } - - private void verify(int expected) { - StatusChecker checker = new StatusChecker(loggerContext); - // StatusPrinter.print(loggerContext); - checker.assertIsErrorFree(); - - int effectiveResets = checker.matchCount(CoreConstants.RESET_MSG_PREFIX); - - String failMsg = "effective=" + effectiveResets + ", expected=" + expected; - - // there might be more effective resets than the expected amount - // since the harness may be sleeping while a reset occurs - assertTrue(expected <= effectiveResets && (expected + 2) >= effectiveResets, failMsg); - - } - - ReconfigureOnChangeFilter initROCF() throws MalformedURLException { - ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); - rocf.setContext(loggerContext); - File file = new File(SCAN1_FILE_AS_STR); - ConfigurationWatchListUtil.setMainWatchURL(loggerContext, file.toURI().toURL()); - rocf.start(); - return rocf; - } - - @Test - @Disabled - public void directPerfTest() throws MalformedURLException { - if (EnvUtilForTests.isLinux()) { - // for some reason this test does not pass on Linux (AMD 64 bit, - // Dual Core Opteron 170) - return; - } - - ReconfigureOnChangeFilter rocf = initROCF(); - assertTrue(rocf.isStarted()); - - for (int i = 0; i < 30; i++) { - directLoop(rocf); - } - double avg = directLoop(rocf); - System.out.println("directPerfTest: " + avg); - } - - public double directLoop(ReconfigureOnChangeFilter rocf) { - long start = System.nanoTime(); - for (int i = 0; i < LOOP_LEN; i++) { - rocf.decide(null, logger, Level.DEBUG, " ", null, null); - } - long end = System.nanoTime(); - return (end - start) / (1.0d * LOOP_LEN); - } - - @Disabled - @Test - public void indirectPerfTest() throws MalformedURLException { - if (EnvUtilForTests.isLinux()) { - // for some reason this test does not pass on Linux (AMD 64 bit, - // Dual Core - // Opteron 170) - return; - } - - ReconfigureOnChangeFilter rocf = initROCF(); - assertTrue(rocf.isStarted()); - loggerContext.addTurboFilter(rocf); - logger.setLevel(Level.ERROR); - - indirectLoop(); - double avg = indirectLoop(); - System.out.println(avg); - // the reference was computed on Orion (Ceki's computer) - @SuppressWarnings("unused") - long referencePerf = 68; - // BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); - } - - void addInfo(String msg, Object o) { - loggerContext.getStatusManager().add(new InfoStatus(msg, o)); - } - - public double indirectLoop() { - long start = System.nanoTime(); - for (int i = 0; i < LOOP_LEN; i++) { - logger.debug("hello"); - } - long end = System.nanoTime(); - return (end - start) / (1.0d * LOOP_LEN); - } - - enum UpdateType { - TOUCH, MALFORMED, MALFORMED_INNER - } - - void writeToFile(File file, String contents) throws IOException { - FileWriter fw = new FileWriter(file); - fw.write(contents); - fw.close(); - } - - class Updater extends RunnableWithCounterAndDone { - File configFile; - UpdateType updateType; - - Updater(File configFile, UpdateType updateType) { - this.configFile = configFile; - this.updateType = updateType; - } - - Updater(File configFile) { - this(configFile, UpdateType.TOUCH); - } - - public void run() { - while (!isDone()) { - try { - Thread.sleep(sleepBetweenUpdates); - } catch (InterruptedException e) { - } - if (isDone()) { - return; - } - counter++; - ReconfigureOnChangeTest.this.addInfo("***settting last modified", this); - switch (updateType) { - case TOUCH: - touchFile(); - break; - case MALFORMED: - try { - malformedUpdate(); - } catch (IOException e) { - e.printStackTrace(); - fail("malformedUpdate failed"); - } - break; - case MALFORMED_INNER: - try { - malformedInnerUpdate(); - } catch (IOException e) { - e.printStackTrace(); - fail("malformedInnerUpdate failed"); - } - } - } - } - - private void malformedUpdate() throws IOException { - writeToFile(configFile, "\n" - + " \n" + ""); - } - - private void malformedInnerUpdate() throws IOException { - writeToFile(configFile, "\n" + " \n" + ""); - } - - void touchFile() { - configFile.setLastModified(System.currentTimeMillis()); - } - } - -} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java deleted file mode 100644 index 950dba6488..0000000000 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, 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.turbo; - -import java.io.File; -import java.io.IOException; - -import ch.qos.logback.core.testUtil.EnvUtilForTests; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import ch.qos.logback.classic.ClassicTestConstants; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.issue.lbclassic135.LoggingRunnable; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.contention.MultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; -import ch.qos.logback.core.joran.spi.JoranException; - -@Disabled -public class ReconfigurePerf { - final static int THREAD_COUNT = 500; - // final static int LOOP_LEN = 1000 * 1000; - - // the space in the file name mandated by - // http://jira.qos.ch/browse/LBCORE-119 - final static String CONF_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX + "turbo/scan_perf.xml"; - - // it actually takes time for Windows to propagate file modification changes - // values below 100 milliseconds can be problematic the same propagation - // latency occurs in Linux but is even larger (>600 ms) - final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 110; - - int sleepBetweenUpdates = DEFAULT_SLEEP_BETWEEN_UPDATES; - - static int numberOfCycles = 100; - static int totalTestDuration; - - LoggerContext loggerContext = new LoggerContext(); - Logger logger = loggerContext.getLogger(this.getClass()); - MultiThreadedHarness harness; - - @BeforeEach - public void setUp() { - // take into account propagation latency occurs on Linux - if (EnvUtilForTests.isLinux()) { - sleepBetweenUpdates = 850; - totalTestDuration = sleepBetweenUpdates * numberOfCycles; - } else { - totalTestDuration = sleepBetweenUpdates * numberOfCycles * 2; - } - harness = new MultiThreadedHarness(totalTestDuration); - } - - void configure(File file) throws JoranException { - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(loggerContext); - jc.doConfigure(file); - } - - RunnableWithCounterAndDone[] buildRunnableArray() { - RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[THREAD_COUNT]; - for (int i = 0; i < THREAD_COUNT; i++) { - rArray[i] = new LoggingRunnable(logger); - } - return rArray; - } - - // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter - @Test - public void scan1() throws JoranException, IOException, InterruptedException { - File file = new File(CONF_FILE_AS_STR); - configure(file); - System.out.println("Running scan1()"); - doRun(); - } - - void doRun() throws InterruptedException { - RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(); - harness.execute(runnableArray); - } -} diff --git a/logback-core-blackbox/pom.xml b/logback-core-blackbox/pom.xml index eaea5a7794..4ae09a14db 100644 --- a/logback-core-blackbox/pom.xml +++ b/logback-core-blackbox/pom.xml @@ -23,7 +23,6 @@ logback-core - org.codehaus.janino janino diff --git a/logback-core-blackbox/src/test/java/module-info.java b/logback-core-blackbox/src/test/java/module-info.java index 665710eed3..a0f27635a8 100644 --- a/logback-core-blackbox/src/test/java/module-info.java +++ b/logback-core-blackbox/src/test/java/module-info.java @@ -1,5 +1,4 @@ module ch.qos.logback.core.blackbox { - requires java.xml; requires ch.qos.logback.core; @@ -11,6 +10,5 @@ exports ch.qos.logback.core.blackbox.joran.conditional; exports ch.qos.logback.core.blackbox.joran; - exports ch.qos.logback.core.blackbox.appender; } \ No newline at end of file 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 a1e4d2c99d..593328c35c 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 @@ -150,6 +150,8 @@ public class CoreConstants { public static final char SINGLE_QUOTE_CHAR = '\''; public static final char COLON_CHAR = ':'; public static final char DASH_CHAR = '-'; + public static final char EQUALS_CHAR = '='; + public static final String DEFAULT_VALUE_SEPARATOR = ":-"; public static final String NULL_STR = "null"; @@ -237,7 +239,7 @@ public class CoreConstants { public static final int UNBOUND_HISTORY = UNBOUNDED_HISTORY; //public static final String RECONFIGURE_ON_CHANGE_TASK = "RECONFIGURE_ON_CHANGE_TASK"; - public static final String SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED = "SizeAndTimeBasedFNATP is deprecated. Use SizeAndTimeBasedRollingPolicy instead"; + public static final String SIZE_AND_TIME_BASED_FNATP_IS_DEPRECATED = "SizeAndTimeBasedFileNamingAndTriggeringPolicy is deprecated. Use SizeAndTimeBasedRollingPolicy instead"; public static final String LOGBACK_CLASSIC_VERSION_MESSAGE = "This is logback-classic version "; public static final char JSON_LINE_SEPARATOR = '\n'; diff --git a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java index 114d310f52..10e41ab5af 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java @@ -174,8 +174,13 @@ public void setOutputStream(OutputStream outputStream) { closeOutputStream(); this.outputStream = outputStream; - // after opening we have to output the header - encoderInit(); + // the first call to setOutputStream() is made on a non started appender + // However, in subsequent calls to setOutputStream() the appender will be in + // started state. In subsequent calls, in particular when opening a file after rollover, + // we have to output the header hence the call to encoderInit(). + if(isStarted()) { + encoderInit(); + } } finally { streamWriteLock.unlock(); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java index 77b295c7a8..9bc6270f90 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java @@ -14,12 +14,18 @@ package ch.qos.logback.core.joran.spi; import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.MD5Util; import java.io.File; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import static ch.qos.logback.core.CoreConstants.PROPERTIES_FILE_EXTENSION; @@ -28,15 +34,27 @@ */ public class ConfigurationWatchList extends ContextAwareBase { + public static final String HTTPS_PROTOCOL_STR = "https"; + public static final String HTTP_PROTOCOL_STR = "http"; + public static final String FILE_PROTOCOL_STR = "file"; + + static final String[] WATCHABLE_PROTOCOLS = new String[] { FILE_PROTOCOL_STR, HTTPS_PROTOCOL_STR, HTTP_PROTOCOL_STR }; + + static final byte[] BUF_ZERO = new byte[] { 0 }; + URL mainURL; - List fileWatchList = new ArrayList(); - List lastModifiedList = new ArrayList(); + List fileWatchList = new ArrayList<>(); + List urlWatchList = new ArrayList<>(); + List lastHashList = new ArrayList<>(); + + List lastModifiedList = new ArrayList<>(); public ConfigurationWatchList buildClone() { ConfigurationWatchList out = new ConfigurationWatchList(); out.mainURL = this.mainURL; out.fileWatchList = new ArrayList(this.fileWatchList); out.lastModifiedList = new ArrayList(this.lastModifiedList); + out.lastHashList = new ArrayList<>(this.lastHashList); return out; } @@ -44,11 +62,13 @@ public void clear() { this.mainURL = null; lastModifiedList.clear(); fileWatchList.clear(); + urlWatchList.clear(); + lastHashList.clear(); } /** * The mainURL for the configuration file. Null values are allowed. - * + * * @param mainURL */ public void setMainURL(URL mainURL) { @@ -59,14 +79,22 @@ public void setMainURL(URL mainURL) { } public boolean watchPredicateFulfilled() { - if(hasMainURLAndNonEmptyFileList()) { - return true; + if (hasMainURLAndNonEmptyFileList()) { + return true; + } + + if(urlListContainsProperties()) { + return true; } return fileWatchListContainsProperties(); } + private boolean urlListContainsProperties() { + return urlWatchList.stream().anyMatch(url -> url.toString().endsWith(PROPERTIES_FILE_EXTENSION)); + } + private boolean hasMainURLAndNonEmptyFileList() { return mainURL != null && !fileWatchList.isEmpty(); } @@ -84,13 +112,37 @@ private void addAsFileToWatch(URL url) { } } + + private boolean isHTTP_Or_HTTPS(URL url) { + String protocolStr = url.getProtocol(); + return isHTTP_Or_HTTPS(protocolStr); + } + + private boolean isHTTP_Or_HTTPS(String protocolStr) { + return (protocolStr.equals(HTTP_PROTOCOL_STR) || protocolStr.equals(HTTPS_PROTOCOL_STR)); + } + + private void addAsHTTP_or_HTTPS_URLToWatch(URL url) { + if(isHTTP_Or_HTTPS(url)) { + urlWatchList.add(url); + lastHashList.add(BUF_ZERO); + } + } + /** * Add the url but only if it is file://. * @param url should be a file */ public void addToWatchList(URL url) { - addAsFileToWatch(url); + String protocolStr = url.getProtocol(); + if (protocolStr.equals(FILE_PROTOCOL_STR)) { + addAsFileToWatch(url); + } else if (isHTTP_Or_HTTPS(protocolStr)) { + addAsHTTP_or_HTTPS_URLToWatch(url); + } else { + addInfo("Cannot watch ["+url + "] as its protocol is not one of file, http or https."); + } } public URL getMainURL() { @@ -101,7 +153,32 @@ public List getCopyOfFileWatchList() { return new ArrayList(fileWatchList); } + + public boolean emptyWatchLists() { + if(fileWatchList != null && !fileWatchList.isEmpty()) { + return false; + } + + if(urlWatchList != null && !urlWatchList.isEmpty()) { + return false; + } + return true; + } + + + /** + * + * @deprecated replaced by {@link #changeDetectedInFile()} + */ public File changeDetected() { + return changeDetectedInFile(); + } + + /** + * Has a changed been detected in one of the files being watched? + * @return + */ + public File changeDetectedInFile() { int len = fileWatchList.size(); for (int i = 0; i < len; i++) { @@ -118,6 +195,48 @@ public File changeDetected() { return null; } + public URL changeDetectedInURL() { + int len = urlWatchList.size(); + + for (int i = 0; i < len; i++) { + byte[] lastHash = this.lastHashList.get(i); + URL url = urlWatchList.get(i); + + HttpUtil httpGetUtil = new HttpUtil(HttpUtil.RequestMethod.GET, url); + HttpURLConnection getConnection = httpGetUtil.connectTextTxt(); + String response = httpGetUtil.readResponse(getConnection); + + byte[] hash = computeHash(response); + if (lastHash == BUF_ZERO) { + this.lastHashList.set(i, hash); + return null; + } + + if (Arrays.equals(lastHash, hash)) { + return null; + } else { + this.lastHashList.set(i, hash); + return url; + } + } + return null; + } + + private byte[] computeHash(String response) { + if (response == null || response.trim().length() == 0) { + return null; + } + + try { + MD5Util md5Util = new MD5Util(); + byte[] hashBytes = md5Util.md5Hash(response); + return hashBytes; + } catch (NoSuchAlgorithmException e) { + addError("missing MD5 algorithm", e); + return null; + } + } + @SuppressWarnings("deprecation") File convertToFile(URL url) { String protocol = url.getProtocol(); @@ -137,4 +256,39 @@ File convertToFile(URL url) { public boolean hasAtLeastOneWatchableFile() { return !fileWatchList.isEmpty(); } + + /** + * Is protocol for the given URL a protocol that we can watch for. + * + * @param url + * @return true if watchable, false otherwise + * @since 1.5.9 + */ + static public boolean isWatchableProtocol(URL url) { + if (url == null) { + return false; + } + String protocolStr = url.getProtocol(); + return Arrays.stream(WATCHABLE_PROTOCOLS).anyMatch(protocol -> protocol.equalsIgnoreCase(protocolStr)); + } + + /** + * Is the given protocol a protocol that we can watch for. + * + * @param protocolStr + * @return true if watchable, false otherwise + * @since 1.5.9 + */ + static public boolean isWatchableProtocol(String protocolStr) { + return Arrays.stream(WATCHABLE_PROTOCOLS).anyMatch(protocol -> protocol.equalsIgnoreCase(protocolStr)); + } + + @Override + public String toString() { + + String fileWatchListStr = fileWatchList.stream().map(File::getPath).collect(Collectors.joining(", ")); + String urlWatchListStr = urlWatchList.stream().map(URL::toString).collect(Collectors.joining(", ")); + + return "ConfigurationWatchList(" + "mainURL=" + mainURL + ", fileWatchList={" + fileWatchListStr + "}, urlWatchList=[" + urlWatchListStr + "})"; + } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HttpUtil.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HttpUtil.java new file mode 100644 index 0000000000..d75ed6b4f1 --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/HttpUtil.java @@ -0,0 +1,137 @@ +/* + * 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.core.joran.spi; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class HttpUtil { + + URL url; + + public enum RequestMethod { + GET, + POST; + } + + + HttpURLConnection conn; + RequestMethod requestMethod; + + Map headerMap = new HashMap<>(2); + + public HttpUtil(RequestMethod requestMethod, URL url) { + this.requestMethod = requestMethod; + this.url =url; + } + + public HttpUtil(RequestMethod requestMethod, String urlStr) throws MalformedURLException { + this(requestMethod, new URL(urlStr)); + } + + Map getHeaderMap() { + return headerMap; + } + + public HttpURLConnection connectTextTxt() { + return connectType( "text/txt;charset=utf-8"); + } + + public HttpURLConnection connectTextPlain() { + return connectType("text/plain; charset=utf-8"); + } + + public HttpURLConnection connectType(String acceptType) { + try { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod(requestMethod.name()); + headerMap.forEach((h, v) -> conn.setRequestProperty(h, v)); + conn.setRequestProperty("Accept", acceptType); + + if(requestMethod == RequestMethod.POST) { + conn.setDoOutput(true); + } + + conn.connect(); + return conn; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public String readResponse(HttpURLConnection conn) { + if(conn == null) + return null; + + try { + int responseCode = conn.getResponseCode(); + if(responseCode == HttpURLConnection.HTTP_OK) { + return innerReadResponse(conn); + } else { + System.out.println("status="+ responseCode+ " Failed response"); + return null; + } + } catch (IOException e) { + System.out.println("url="+ url.toString()+" failed to read status"); + e.printStackTrace(); + return null; + } + } + + private String innerReadResponse(HttpURLConnection conn) { + try (InputStream is = conn.getInputStream()) { + BufferedReader in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + String inputLine; + StringBuffer buffer = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + buffer.append(inputLine); + } + return buffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public boolean post(HttpURLConnection conn, String str) { + if (conn == null) { + System.out.println("null HttpURLConnection object"); + return false; + } + + if(requestMethod != RequestMethod.POST) { + System.out.println("Incorrect request method "+requestMethod.name()); + return false; + } + + try (OutputStream os = conn.getOutputStream()) { + OutputStreamWriter wr = new OutputStreamWriter(os); + wr.write(str); + wr.flush(); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java index d038aa795b..51a451ad5e 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java @@ -77,7 +77,7 @@ public static void addToWatchList(Context context, URL url) { public static void addToWatchList(Context context, URL url, boolean createCWL) { ConfigurationWatchList cwl = getConfigurationWatchList(context); if(cwl == null) { - if(createCWL && isWatchable(url)) { + if(createCWL && ConfigurationWatchList.isWatchableProtocol(url)) { cwl = registerNewConfigurationWatchListWithContext(context); } else { addWarn(context, "Null ConfigurationWatchList. Cannot add " + url); @@ -97,17 +97,6 @@ private static ConfigurationWatchList registerNewConfigurationWatchListWithConte return cwl; } - private static boolean isWatchable(URL url) { - if(url == null) { - return false; - } - - String protocol = url.getProtocol(); - return "file".equalsIgnoreCase(protocol); - } - - - public static ConfigurationWatchList getConfigurationWatchList(Context context) { return (ConfigurationWatchList) context.getObject(CoreConstants.CONFIGURATION_WATCH_LIST); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java b/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java index fdb29b76de..97a0d30150 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java +++ b/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java @@ -119,7 +119,6 @@ private InputStream getInputStream(ModelInterpretationContext mic, IncludeModel URL inputURL = getInputURL(mic, includeModel); if (inputURL == null) return null; - ConfigurationWatchListUtil.addToWatchList(context, inputURL); return openURL(inputURL); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/AbstractMultiThreadedHarness.java b/logback-core/src/main/java/ch/qos/logback/core/testUtil/AbstractMultiThreadedHarness.java similarity index 92% rename from logback-core/src/test/java/ch/qos/logback/core/contention/AbstractMultiThreadedHarness.java rename to logback-core/src/main/java/ch/qos/logback/core/testUtil/AbstractMultiThreadedHarness.java index 906cbbe975..243cc8dd3e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/AbstractMultiThreadedHarness.java +++ b/logback-core/src/main/java/ch/qos/logback/core/testUtil/AbstractMultiThreadedHarness.java @@ -1,6 +1,6 @@ -/** +/* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, QOS.ch. All rights reserved. + * 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 @@ -11,7 +11,7 @@ * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */ -package ch.qos.logback.core.contention; +package ch.qos.logback.core.testUtil; abstract public class AbstractMultiThreadedHarness { diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java b/logback-core/src/main/java/ch/qos/logback/core/testUtil/RunnableWithCounterAndDone.java similarity index 89% rename from logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java rename to logback-core/src/main/java/ch/qos/logback/core/testUtil/RunnableWithCounterAndDone.java index 10bab5aba0..15d9b6df42 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/RunnableWithCounterAndDone.java +++ b/logback-core/src/main/java/ch/qos/logback/core/testUtil/RunnableWithCounterAndDone.java @@ -1,6 +1,6 @@ -/** +/* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, QOS.ch. All rights reserved. + * 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 @@ -11,7 +11,7 @@ * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */ -package ch.qos.logback.core.contention; +package ch.qos.logback.core.testUtil; /** * A runnable with 'done' and 'counter' fields. diff --git a/logback-core/src/main/java/ch/qos/logback/core/util/MD5Util.java b/logback-core/src/main/java/ch/qos/logback/core/util/MD5Util.java new file mode 100644 index 0000000000..cf6c5ba9b4 --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/util/MD5Util.java @@ -0,0 +1,61 @@ +/* + * 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.core.util; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +public class MD5Util { + + + static String MD5_ALGORITHM_KEY = "MD5"; + final MessageDigest md5; + + public MD5Util() throws NoSuchAlgorithmException { + md5 = MessageDigest.getInstance(MD5_ALGORITHM_KEY); + + } + + + public boolean equalsHash(byte[] b0, byte[] b1) { + return Arrays.equals(b0, b1); + } + + /** + * Compute hash for input string. The hash is computed on the input alone + * with no previous or subsequent data. + * + * @param input + * @return + */ + public byte[] md5Hash(String input) { + byte[] messageDigest = md5.digest(input.getBytes()); + md5.reset(); + return messageDigest; + } + + public String asHexString(byte[] messageDigest) { + BigInteger number = new BigInteger(1, messageDigest); + StringBuilder hexString = new StringBuilder(number.toString(16)); + // Pad with zeros if necessary + while (hexString.length() < 32) { + hexString.insert(0, '0'); + } + return hexString.toString(); + } + +} diff --git a/logback-core/src/test/java/ch/qos/logback/core/FileAppenderResilienceTest.java b/logback-core/src/test/java/ch/qos/logback/core/FileAppenderResilienceTest.java index 26973a8bff..51b3f25c33 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/FileAppenderResilienceTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/FileAppenderResilienceTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.encoder.EchoEncoder; import ch.qos.logback.core.recovery.RecoveryCoordinator; import ch.qos.logback.core.recovery.RecoveryListener; diff --git a/logback-core/src/test/java/ch/qos/logback/core/PrudentFileAppenderInterruptTest.java b/logback-core/src/test/java/ch/qos/logback/core/PrudentFileAppenderInterruptTest.java index c8e9f5323e..d1ddf8da4e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/PrudentFileAppenderInterruptTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/PrudentFileAppenderInterruptTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.encoder.EchoEncoder; import ch.qos.logback.core.status.OnConsoleStatusListener; import ch.qos.logback.core.testUtil.CoreTestConstants; diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java b/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java index 3fa9def9e3..4f08c6e6b8 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/MultiThreadedHarness.java @@ -13,6 +13,8 @@ */ package ch.qos.logback.core.contention; +import ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness; + /** * Useful scaffolding/harness to start and processPriorToRemoval multiple * threads. diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java b/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java index 27e0ca0940..87e43e4661 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/ThreadedThroughputCalculator.java @@ -13,6 +13,8 @@ */ package ch.qos.logback.core.contention; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; + /** * Useful scaffolding to measure the throughput of certain operations when * invoked by multiple threads. diff --git a/logback-core/src/test/java/ch/qos/logback/core/contention/WaitOnExecutionMultiThreadedHarness.java b/logback-core/src/test/java/ch/qos/logback/core/contention/WaitOnExecutionMultiThreadedHarness.java index a7da102bf6..1087c1aa5b 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/contention/WaitOnExecutionMultiThreadedHarness.java +++ b/logback-core/src/test/java/ch/qos/logback/core/contention/WaitOnExecutionMultiThreadedHarness.java @@ -13,6 +13,8 @@ */ package ch.qos.logback.core.contention; +import ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness; + import java.util.concurrent.ThreadPoolExecutor; public class WaitOnExecutionMultiThreadedHarness extends AbstractMultiThreadedHarness { diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java b/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java index 583413d9ec..fb298144b6 100755 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/LockThroughput.java @@ -13,7 +13,7 @@ */ package ch.qos.logback.core.issue; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.contention.ThreadedThroughputCalculator; import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java index 1322eb5c81..4cd7c3626e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/NoLockThroughput.java @@ -13,7 +13,7 @@ */ package ch.qos.logback.core.issue; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.contention.ThreadedThroughputCalculator; import ch.qos.logback.core.issue.SelectiveLockRunnable.LockingModel; diff --git a/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java b/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java index b03d47c036..df4555ecb9 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java +++ b/logback-core/src/test/java/ch/qos/logback/core/issue/SelectiveLockRunnable.java @@ -16,7 +16,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; /** * A runnable which behaves differently depending on the desired locking model. diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java index e12919cb45..60050fe7d3 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java @@ -1,6 +1,6 @@ -/** +/* * Logback: the reliable, generic, fast and flexible logging framework. - * Copyright (C) 1999-2015, QOS.ch. All rights reserved. + * 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 diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java index 704f7f0f4f..945298c403 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/MultiThreadedRollingTest.java @@ -33,7 +33,7 @@ import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.contention.MultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import ch.qos.logback.core.encoder.EchoEncoder; import ch.qos.logback.core.encoder.Encoder; import ch.qos.logback.core.testUtil.RandomUtil; diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/InvocationGateTest.java b/logback-core/src/test/java/ch/qos/logback/core/util/InvocationGateTest.java index 05557f3845..83311d4677 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/util/InvocationGateTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/util/InvocationGateTest.java @@ -14,8 +14,8 @@ package ch.qos.logback.core.util; -import ch.qos.logback.core.contention.AbstractMultiThreadedHarness; -import ch.qos.logback.core.contention.RunnableWithCounterAndDone; +import ch.qos.logback.core.testUtil.AbstractMultiThreadedHarness; +import ch.qos.logback.core.testUtil.RunnableWithCounterAndDone; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; diff --git a/logback-core/src/test/java/ch/qos/logback/core/util/MD5Test.java b/logback-core/src/test/java/ch/qos/logback/core/util/MD5Test.java new file mode 100644 index 0000000000..902b5dc11f --- /dev/null +++ b/logback-core/src/test/java/ch/qos/logback/core/util/MD5Test.java @@ -0,0 +1,34 @@ +/* + * 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.core.util; + +import org.junit.jupiter.api.Test; + +import java.security.NoSuchAlgorithmException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MD5Test { + + @Test + void smoke() throws NoSuchAlgorithmException { + MD5Util md5Util = new MD5Util(); + byte[] hash = md5Util.md5Hash("toto"); + String asHexStr = md5Util.asHexString(hash); + assertEquals("f71dbe52628a3f83a77ab494817525c6", asHexStr); + System.out.println(asHexStr); + + } +} diff --git a/pom.xml b/pom.xml index 655729aedf..af308878c0 100755 --- a/pom.xml +++ b/pom.xml @@ -102,6 +102,7 @@ 3.1.0 1.10.12 2.7 + 12.0.13