This is an automated email from the ASF dual-hosted git repository.

rgoers pushed a commit to branch Spring-33450
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 7c4452bca03b38203e0a3c9a7322fd25ed289c5f
Author: Ralph Goers <[email protected]>
AuthorDate: Mon Dec 4 20:15:38 2023 -0700

    1799 - Spring shutdown fails due to ClassCastException. Spring 33450 - 
Spring shutdown fails due to IllegalStateException
---
 .../logging/log4j/util/PropertiesUtilTest.java     |  38 +++
 .../apache/logging/log4j/util/PropertiesUtil.java  |  58 ++++-
 .../logging/log4j/util/PropertyEnvironment.java    |   6 +
 .../logging/log4j/core/LoggerContextTest.java      |  46 ++++
 .../log4j/core/config/MissingRootLoggerTest.java   |   6 +-
 .../java/org/apache/logging/log4j/core/Logger.java |  11 +
 .../apache/logging/log4j/core/LoggerContext.java   |  10 +
 .../log4j/core/config/ConfigurationFactory.java    |  12 +
 .../log4j/core/impl/Log4jContextFactory.java       | 219 +++++++++-------
 .../core/impl/internal/InternalLoggerContext.java  | 290 +++++++++++++++++++++
 .../org/apache/logging/log4j/core/jmx/Server.java  |  12 +-
 .../.3.x.x/1799_ignore _propertysource_errors.xml  |  10 +
 12 files changed, 608 insertions(+), 110 deletions(-)

diff --git 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/PropertiesUtilTest.java
 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/PropertiesUtilTest.java
index 5aef842655..cb836fd617 100644
--- 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/PropertiesUtilTest.java
+++ 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/PropertiesUtilTest.java
@@ -140,6 +140,23 @@ public class PropertiesUtilTest {
         assertEquals("Log4j", value);
     }
 
+    @Test
+    @ResourceLock(Resources.SYSTEM_PROPERTIES)
+    public void testBadPropertysource() {
+        final String key1 = "testKey";
+        System.getProperties().put(key1, "test");
+        final PropertiesUtil util = new PropertiesUtil(new Properties());
+        ErrorPropertySource source = new ErrorPropertySource();
+        util.addPropertySource(source);
+        try {
+            assertEquals("test", util.getStringProperty(key1));
+            assertTrue(source.exceptionThrown);
+        } finally {
+            util.removePropertySource(source);
+            System.getProperties().remove(key1);
+        }
+    }
+
     private static final String[][] data = {
         {null, "org.apache.logging.log4j.level"},
         {null, "Log4jAnotherProperty"},
@@ -184,4 +201,25 @@ public class PropertiesUtilTest {
         final PropertiesUtil util = new PropertiesUtil(props);
         assertNull(util.getStringProperty(correct));
     }
+
+    private class ErrorPropertySource implements PropertySource {
+        public boolean exceptionThrown = false;
+
+        @Override
+        public int getPriority() {
+            return Integer.MIN_VALUE;
+        }
+
+        @Override
+        public String getProperty(String key) {
+            exceptionThrown = true;
+            throw new InstantiationError("Test");
+        }
+
+        @Override
+        public boolean containsProperty(String key) {
+            exceptionThrown = true;
+            throw new InstantiationError("Test");
+        }
+    }
 }
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index cf4e011ab5..dcb1a4fbad 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -199,6 +199,13 @@ public class PropertiesUtil implements PropertyEnvironment 
{
         }
     }
 
+    @Override
+    public void removePropertySource(final PropertySource propertySource) {
+        if (environment != null) {
+            environment.removePropertySource(propertySource);
+        }
+    }
+
     /**
      * Returns {@code true} if the specified property is defined, regardless 
of its value (it may not have a value).
      *
@@ -683,6 +690,11 @@ public class PropertiesUtil implements PropertyEnvironment 
{
             sources.add(propertySource);
         }
 
+        @Override
+        public void removePropertySource(final PropertySource propertySource) {
+            sources.remove(propertySource);
+        }
+
         private void reload() {
             literal.clear();
             sources.forEach((s) -> {
@@ -700,14 +712,14 @@ public class PropertiesUtil implements 
PropertyEnvironment {
                     sources.forEach(source -> {
                         if (source instanceof ContextAwarePropertySource) {
                             final ContextAwarePropertySource src = 
Cast.cast(source);
-                            if (src.containsProperty(contextName, contextKey)) 
{
+                            if (sourceContainsProperty(src, contextName, 
contextKey)) {
                                 literal.putIfAbsent(key, 
src.getProperty(contextName, contextKey));
                             }
                         }
                     });
                 }
                 sources.forEach(source -> {
-                    if (source.containsProperty(contextKey)) {
+                    if (sourceContainsProperty(source, contextKey)) {
                         literal.putIfAbsent(key, 
source.getProperty(contextKey));
                     }
                 });
@@ -727,7 +739,7 @@ public class PropertiesUtil implements PropertyEnvironment {
                 while (source != null) {
                     if (source instanceof ContextAwarePropertySource) {
                         final ContextAwarePropertySource src = 
Cast.cast(source);
-                        result = src.getProperty(contextName, contextKey);
+                        result = sourceGetProperty(src, contextName, 
contextKey);
                     }
                     if (result != null) {
                         return result;
@@ -737,7 +749,7 @@ public class PropertiesUtil implements PropertyEnvironment {
             }
             PropertySource source = sources.first();
             while (source != null) {
-                result = source.getProperty(contextKey);
+                result = sourceGetProperty(source, contextKey);
                 if (result != null) {
                     return result;
                 }
@@ -746,6 +758,22 @@ public class PropertiesUtil implements PropertyEnvironment 
{
             return result;
         }
 
+        private String sourceGetProperty(ContextAwarePropertySource source, 
String contextName, String key) {
+            try {
+                return source.getProperty(contextName, key);
+            } catch (Throwable ex) {
+                return null;
+            }
+        }
+
+        private String sourceGetProperty(PropertySource source, String key) {
+            try {
+                return source.getProperty(key);
+            } catch (Throwable ex) {
+                return null;
+            }
+        }
+
         @Override
         public boolean hasProperty(final String key) {
             if (literal.containsKey(key)) {
@@ -758,7 +786,7 @@ public class PropertiesUtil implements PropertyEnvironment {
                 while (source != null) {
                     if (source instanceof ContextAwarePropertySource) {
                         final ContextAwarePropertySource src = 
Cast.cast(source);
-                        if (src.containsProperty(contextName, contextKey)) {
+                        if (sourceContainsProperty(src, contextName, 
contextKey)) {
                             return true;
                         }
                     }
@@ -769,9 +797,9 @@ public class PropertiesUtil implements PropertyEnvironment {
             while (source != null) {
                 if (source instanceof ContextAwarePropertySource) {
                     final ContextAwarePropertySource src = Cast.cast(source);
-                    if (src.containsProperty(contextName, contextKey)
+                    if (sourceContainsProperty(src, contextName, contextKey)
                             || 
(!contextName.equals(PropertySource.SYSTEM_CONTEXT)
-                                    && 
src.containsProperty(PropertySource.SYSTEM_CONTEXT, contextKey))) {
+                                    && sourceContainsProperty(src, 
PropertySource.SYSTEM_CONTEXT, contextKey))) {
                         return true;
                     }
                 } else {
@@ -784,6 +812,22 @@ public class PropertiesUtil implements PropertyEnvironment 
{
             return false;
         }
 
+        private boolean sourceContainsProperty(ContextAwarePropertySource 
source, String contextName, String key) {
+            try {
+                return source.containsProperty(contextName, key);
+            } catch (Throwable ex) {
+                return false;
+            }
+        }
+
+        private boolean sourceContainsProperty(PropertySource source, String 
key) {
+            try {
+                return source.containsProperty(key);
+            } catch (Throwable ex) {
+                return false;
+            }
+        }
+
         private String getContextKey(final String key) {
             String keyToCheck = key;
             if (keyToCheck.startsWith(PropertySource.PREFIX)) {
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyEnvironment.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyEnvironment.java
index 3947e7ab62..701bcf6955 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyEnvironment.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyEnvironment.java
@@ -28,6 +28,12 @@ public interface PropertyEnvironment {
      */
     void addPropertySource(PropertySource propertySource);
 
+    /**
+     * Allows a PropertySource that was added to be removed.
+     * @param propertySource the PropertySource to remove.
+     */
+    void removePropertySource(PropertySource propertySource);
+
     /**
      * Returns {@code true} if the specified property is defined, regardless 
of its value (it may not have a value).
      *
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LoggerContextTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LoggerContextTest.java
new file mode 100644
index 0000000000..4b2f417de1
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LoggerContextTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.impl.Log4jContextFactory;
+import org.apache.logging.log4j.core.impl.internal.InternalLoggerContext;
+import org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry;
+import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
+import org.apache.logging.log4j.spi.LoggerContextFactory;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Validate Logging after Shutdown.
+ */
+public class LoggerContextTest {
+
+    @Test
+    public void shutdownTest() {
+        LoggerContextFactory contextFactory = LogManager.getFactory();
+        assertTrue(contextFactory instanceof Log4jContextFactory);
+        Log4jContextFactory factory = (Log4jContextFactory) contextFactory;
+        ShutdownCallbackRegistry registry = 
factory.getShutdownCallbackRegistry();
+        assertTrue(registry instanceof DefaultShutdownCallbackRegistry);
+        ((DefaultShutdownCallbackRegistry) registry).start();
+        ((DefaultShutdownCallbackRegistry) registry).stop();
+        LoggerContext loggerContext = 
factory.getContext(LoggerContextTest.class.getName(), null, null, false);
+        assertTrue(loggerContext instanceof InternalLoggerContext);
+    }
+}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/MissingRootLoggerTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/MissingRootLoggerTest.java
index de0ce39370..b1d5778e97 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/MissingRootLoggerTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/MissingRootLoggerTest.java
@@ -21,6 +21,7 @@ import static org.hamcrest.MatcherAssert.*;
 import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.startsWith;
 import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.Map;
@@ -48,7 +49,7 @@ public class MissingRootLoggerTest {
         assertNotNull(map, "Appenders not null");
         assertThat("There should only be two appenders", map, hasSize(2));
         assertThat(map, hasKey("List"));
-        assertThat(map, hasKey("DefaultConsole-2"));
+        assertThat(map, hasKey(startsWith("DefaultConsole-")));
 
         final Map<String, LoggerConfig> loggerMap = config.getLoggers();
         assertNotNull(loggerMap, "loggerMap not null");
@@ -67,7 +68,8 @@ public class MissingRootLoggerTest {
         final Map<String, Appender> rootAppenders = root.getAppenders();
         assertThat("The root logger should only have one appender", 
rootAppenders, hasSize(1));
         // root only has Console appender!
-        assertThat("The root appender should be a ConsoleAppender", 
rootAppenders, hasKey("DefaultConsole-2"));
+        assertThat(
+                "The root appender should be a ConsoleAppender", 
rootAppenders, hasKey(startsWith("DefaultConsole-")));
         assertEquals(Level.ERROR, root.getLevel());
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
index d7a0c532ce..1ab8eae227 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
@@ -66,6 +66,17 @@ public class Logger extends AbstractLogger implements 
Supplier<LoggerConfig> {
         privateConfig = new PrivateConfig(context.getConfiguration(), this);
     }
 
+    /**
+     * This is used to construct an InternalLoggerContext, which makes 
SimpleLoggerContext conmpatible with core.
+     * @param context the InternalLoggerContext.
+     * @param name the Logger name.
+     */
+    protected Logger(final LoggerContext context, final String name) {
+        super(name);
+        this.context = context;
+        privateConfig = null;
+    }
+
     /**
      * This method is only used for 1.x compatibility. Returns the parent of 
this Logger. If it doesn't already exist
      * return a temporary Logger.
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index c0da220b40..7a70e0a61c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -99,6 +99,15 @@ public class LoggerContext extends AbstractLifeCycle
 
     private final Lock configLock = new ReentrantLock();
 
+    /**
+     * Constructor used to create an InternalLoggerContext.
+     */
+    protected LoggerContext() {
+        setStarted();
+        instanceFactory = null;
+        this.nullConfiguration = null;
+    }
+
     /**
      * Constructor taking only a name.
      *
@@ -428,6 +437,7 @@ public class LoggerContext extends AbstractLifeCycle
             }
 
             this.setStopping();
+            String name = getName();
             try {
                 Server.unregisterLoggerContext(getName()); // LOG4J2-406, 
LOG4J2-500
             } catch (final LinkageError | Exception e) {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
index 257a61a5d6..0898b7a98f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
@@ -21,12 +21,15 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LoggerContext;
 import 
org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
 import org.apache.logging.log4j.core.impl.Log4jPropertyKey;
+import org.apache.logging.log4j.core.util.AuthorizationProvider;
 import org.apache.logging.log4j.plugins.Namespace;
 import org.apache.logging.log4j.plugins.di.ConfigurableInstanceFactory;
 import org.apache.logging.log4j.plugins.di.Key;
 import org.apache.logging.log4j.plugins.model.PluginNamespace;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.LoaderUtil;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.PropertyEnvironment;
 import org.apache.logging.log4j.util.PropertyKey;
 
 /**
@@ -118,6 +121,15 @@ public abstract class ConfigurationFactory extends 
ConfigurationBuilderFactory {
         return true;
     }
 
+    /**
+     * Required for Spring Boot.
+     * @param props PropertiesUtil.
+     * @return the AuthorizationProvider, if any.
+     */
+    public static AuthorizationProvider authorizationProvider(final 
PropertiesUtil props) {
+        return 
AuthorizationProvider.getAuthorizationProvider((PropertyEnvironment) props);
+    }
+
     public abstract Configuration getConfiguration(final LoggerContext 
loggerContext, ConfigurationSource source);
 
     /**
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
index 59e2de4ac6..e805c843f0 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
@@ -30,6 +30,7 @@ import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
+import org.apache.logging.log4j.core.impl.internal.InternalLoggerContext;
 import org.apache.logging.log4j.core.selector.ContextSelector;
 import org.apache.logging.log4j.core.util.Cancellable;
 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
@@ -54,6 +55,8 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
     private final ContextSelector selector;
     private final ShutdownCallbackRegistry shutdownCallbackRegistry;
 
+    private final LoggerContext internalContext = new InternalLoggerContext();
+
     /**
      * Initializes the ContextSelector from system property {@link 
Log4jPropertyKey#CONTEXT_SELECTOR_CLASS_NAME}.
      */
@@ -146,8 +149,12 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
         if (externalContext != null && ctx.getExternalContext() == null) {
             ctx.setExternalContext(externalContext);
         }
-        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
-            startContext(ctx, classLoader);
+        try {
+            if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+                startContext(ctx, classLoader);
+            }
+        } catch (IllegalStateException ex) {
+            return internalContext;
         }
         return ctx;
     }
@@ -223,23 +230,27 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
         if (externalContext != null && ctx.getExternalContext() == null) {
             ctx.setExternalContext(externalContext);
         }
-        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
-            ContextAnchor.THREAD_CONTEXT.set(ctx);
-            boolean setProperties = false;
-            try {
-                if (ctx.getProperties() == null) {
-                    final PropertiesUtil props = 
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
-                    ctx.setProperties(props);
-                    PropertiesUtil.setThreadProperties(props);
-                    setProperties = true;
-                }
-                ctx.start(configuration);
-            } finally {
-                if (setProperties) {
-                    PropertiesUtil.clearThreadProperties();
+        try {
+            if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+                ContextAnchor.THREAD_CONTEXT.set(ctx);
+                boolean setProperties = false;
+                try {
+                    if (ctx.getProperties() == null) {
+                        final PropertiesUtil props = 
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
+                        ctx.setProperties(props);
+                        PropertiesUtil.setThreadProperties(props);
+                        setProperties = true;
+                    }
+                    ctx.start(configuration);
+                } finally {
+                    if (setProperties) {
+                        PropertiesUtil.clearThreadProperties();
+                    }
+                    ContextAnchor.THREAD_CONTEXT.remove();
                 }
-                ContextAnchor.THREAD_CONTEXT.remove();
             }
+        } catch (IllegalStateException ex) {
+            return internalContext;
         }
         return ctx;
     }
@@ -271,29 +282,34 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
         if (name != null) {
             ctx.setName(name);
         }
-        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
-            if (configLocation != null || name != null) {
-                ContextAnchor.THREAD_CONTEXT.set(ctx);
-                boolean setProperties = false;
-                try {
-                    if (ctx.getProperties() == null) {
-                        final PropertiesUtil props = 
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
-                        ctx.setProperties(props);
-                        PropertiesUtil.setThreadProperties(props);
-                        setProperties = true;
-                    }
-                    final Configuration config = ctx.getConfiguration(name, 
configLocation);
-                    LOGGER.debug("Starting {} from configuration at {}", ctx, 
configLocation);
-                    ctx.start(config);
-                } finally {
-                    if (setProperties) {
-                        PropertiesUtil.clearThreadProperties();
+        try {
+            if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+                if (configLocation != null || name != null) {
+                    ContextAnchor.THREAD_CONTEXT.set(ctx);
+                    boolean setProperties = false;
+                    try {
+                        if (ctx.getProperties() == null) {
+                            final PropertiesUtil props =
+                                    
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
+                            ctx.setProperties(props);
+                            PropertiesUtil.setThreadProperties(props);
+                            setProperties = true;
+                        }
+                        final Configuration config = 
ctx.getConfiguration(name, configLocation);
+                        LOGGER.debug("Starting {} from configuration at {}", 
ctx, configLocation);
+                        ctx.start(config);
+                    } finally {
+                        if (setProperties) {
+                            PropertiesUtil.clearThreadProperties();
+                        }
+                        ContextAnchor.THREAD_CONTEXT.remove();
                     }
-                    ContextAnchor.THREAD_CONTEXT.remove();
+                } else {
+                    startContext(ctx, classLoader);
                 }
-            } else {
-                startContext(ctx, classLoader);
             }
+        } catch (IllegalStateException ex) {
+            return internalContext;
         }
         return ctx;
     }
@@ -311,29 +327,34 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
         if (name != null) {
             ctx.setName(name);
         }
-        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
-            if (configLocation != null || name != null) {
-                boolean setProperties = false;
-                try {
-                    if (ctx.getProperties() == null) {
-                        final PropertiesUtil props = 
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
-                        ctx.setProperties(props);
-                        PropertiesUtil.setThreadProperties(props);
-                        setProperties = true;
-                    }
-                    ContextAnchor.THREAD_CONTEXT.set(ctx);
-                    final Configuration config = ctx.getConfiguration(name, 
configLocation);
-                    LOGGER.debug("Starting {} from configuration at {}", ctx, 
configLocation);
-                    ctx.start(config);
-                } finally {
-                    if (setProperties) {
-                        PropertiesUtil.clearThreadProperties();
+        try {
+            if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+                if (configLocation != null || name != null) {
+                    boolean setProperties = false;
+                    try {
+                        if (ctx.getProperties() == null) {
+                            final PropertiesUtil props =
+                                    
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
+                            ctx.setProperties(props);
+                            PropertiesUtil.setThreadProperties(props);
+                            setProperties = true;
+                        }
+                        ContextAnchor.THREAD_CONTEXT.set(ctx);
+                        final Configuration config = 
ctx.getConfiguration(name, configLocation);
+                        LOGGER.debug("Starting {} from configuration at {}", 
ctx, configLocation);
+                        ctx.start(config);
+                    } finally {
+                        if (setProperties) {
+                            PropertiesUtil.clearThreadProperties();
+                        }
+                        ContextAnchor.THREAD_CONTEXT.remove();
                     }
-                    ContextAnchor.THREAD_CONTEXT.remove();
+                } else {
+                    startContext(ctx, classLoader);
                 }
-            } else {
-                startContext(ctx, classLoader);
             }
+        } catch (IllegalStateException ex) {
+            return internalContext;
         }
         return ctx;
     }
@@ -355,52 +376,58 @@ public class Log4jContextFactory implements 
LoggerContextFactory, ShutdownCallba
         if (name != null) {
             ctx.setName(name);
         }
-        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
-            if ((configLocations != null && !configLocations.isEmpty())) {
-                ContextAnchor.THREAD_CONTEXT.set(ctx);
-                boolean setProperties = false;
-                try {
-                    final List<AbstractConfiguration> configurations = new 
ArrayList<>(configLocations.size());
-                    if (ctx.getProperties() == null) {
-                        final PropertiesUtil props = 
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
-                        ctx.setProperties(props);
-                        PropertiesUtil.setThreadProperties(props);
-                        setProperties = true;
-                    }
-                    for (final URI configLocation : configLocations) {
-                        final Configuration currentReadConfiguration = 
ctx.getConfiguration(name, configLocation);
-                        if (currentReadConfiguration != null) {
-                            if (currentReadConfiguration instanceof 
DefaultConfiguration) {
-                                LOGGER.warn("Unable to locate configuration 
{}, ignoring", configLocation.toString());
-                            } else if (currentReadConfiguration instanceof 
AbstractConfiguration) {
-                                configurations.add((AbstractConfiguration) 
currentReadConfiguration);
+        try {
+            if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+                if ((configLocations != null && !configLocations.isEmpty())) {
+                    ContextAnchor.THREAD_CONTEXT.set(ctx);
+                    boolean setProperties = false;
+                    try {
+                        final List<AbstractConfiguration> configurations = new 
ArrayList<>(configLocations.size());
+                        if (ctx.getProperties() == null) {
+                            final PropertiesUtil props =
+                                    
PropertiesUtil.getContextProperties(classLoader, ctx.getName());
+                            ctx.setProperties(props);
+                            PropertiesUtil.setThreadProperties(props);
+                            setProperties = true;
+                        }
+                        for (final URI configLocation : configLocations) {
+                            final Configuration currentReadConfiguration = 
ctx.getConfiguration(name, configLocation);
+                            if (currentReadConfiguration != null) {
+                                if (currentReadConfiguration instanceof 
DefaultConfiguration) {
+                                    LOGGER.warn(
+                                            "Unable to locate configuration 
{}, ignoring", configLocation.toString());
+                                } else if (currentReadConfiguration instanceof 
AbstractConfiguration) {
+                                    configurations.add((AbstractConfiguration) 
currentReadConfiguration);
+                                } else {
+                                    LOGGER.error(
+                                            "Found configuration {}, which is 
not an AbstractConfiguration and can't be handled by CompositeConfiguration",
+                                            configLocation);
+                                }
                             } else {
-                                LOGGER.error(
-                                        "Found configuration {}, which is not 
an AbstractConfiguration and can't be handled by CompositeConfiguration",
-                                        configLocation);
+                                LOGGER.info("Unable to access configuration 
{}, ignoring", configLocation.toString());
                             }
+                        }
+                        if (configurations.isEmpty()) {
+                            LOGGER.error("No configurations could be created 
for {}", configLocations.toString());
+                        } else if (configurations.size() == 1) {
+                            ctx.start(configurations.get(0));
                         } else {
-                            LOGGER.info("Unable to access configuration {}, 
ignoring", configLocation.toString());
+                            final CompositeConfiguration 
compositeConfiguration =
+                                    new CompositeConfiguration(configurations);
+                            ctx.start(compositeConfiguration);
                         }
+                    } finally {
+                        if (setProperties) {
+                            PropertiesUtil.clearThreadProperties();
+                        }
+                        ContextAnchor.THREAD_CONTEXT.remove();
                     }
-                    if (configurations.isEmpty()) {
-                        LOGGER.error("No configurations could be created for 
{}", configLocations.toString());
-                    } else if (configurations.size() == 1) {
-                        ctx.start(configurations.get(0));
-                    } else {
-                        final CompositeConfiguration compositeConfiguration =
-                                new CompositeConfiguration(configurations);
-                        ctx.start(compositeConfiguration);
-                    }
-                } finally {
-                    if (setProperties) {
-                        PropertiesUtil.clearThreadProperties();
-                    }
-                    ContextAnchor.THREAD_CONTEXT.remove();
+                } else {
+                    startContext(ctx, classLoader);
                 }
-            } else {
-                startContext(ctx, classLoader);
             }
+        } catch (IllegalStateException ex) {
+            return internalContext;
         }
         return ctx;
     }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/InternalLoggerContext.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/InternalLoggerContext.java
new file mode 100644
index 0000000000..9f7f247721
--- /dev/null
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/InternalLoggerContext.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core.impl.internal;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogBuilder;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.simple.SimpleLoggerContext;
+import org.apache.logging.log4j.spi.ExtendedLogger;
+
+/**
+ * Creates a SimpleLoggerContext compatible with log4j-core. This class is 
internal to Log4j.
+ */
+public class InternalLoggerContext extends LoggerContext {
+
+    private final SimpleLoggerContext simpleLoggerContext = new 
SimpleLoggerContext();
+
+    private static final LoggerConfig LOGGER_CONFIG = new 
LoggerConfig.RootLogger();
+
+    public InternalLoggerContext() {
+        super();
+        setStarted();
+    }
+
+    @Override
+    protected Logger newInstance(final LoggerContext ctx, final String name, 
final MessageFactory messageFactory) {
+        return new InternalLogger(this, name);
+    }
+
+    @Override
+    public boolean stop(final long timeout, final TimeUnit timeUnit) {
+        return false;
+    }
+
+    private class InternalLogger extends Logger {
+        private final ExtendedLogger logger;
+        private final InternalLoggerContext loggerContext;
+
+        public InternalLogger(InternalLoggerContext loggerContext, String 
name) {
+            super(loggerContext, name);
+            this.loggerContext = loggerContext;
+            this.logger = simpleLoggerContext.getLogger(name);
+        }
+
+        @Override
+        public Logger getParent() {
+            return null;
+        }
+
+        @Override
+        public LoggerContext getContext() {
+            return loggerContext;
+        }
+
+        @Override
+        public void setLevel(final Level level) {}
+
+        @Override
+        public LoggerConfig get() {
+            return LOGGER_CONFIG;
+        }
+
+        @Override
+        protected boolean requiresLocation() {
+            return false;
+        }
+
+        @Override
+        public void logMessage(String fqcn, Level level, Marker marker, 
Message message, Throwable t) {}
+
+        @Override
+        protected void log(
+                Level level,
+                Marker marker,
+                String fqcn,
+                StackTraceElement location,
+                Message message,
+                Throwable throwable) {
+            logger.log(level, marker, message, throwable);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message, 
Throwable t) {
+            return logger.isEnabled(level, marker, message, t);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message) {
+            return logger.isEnabled(level, marker, message);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message, 
Object... params) {
+            return logger.isEnabled(level, marker, message, params);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message, 
Object p0) {
+            return logger.isEnabled(level, marker, message, p0);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message, 
Object p0, Object p1) {
+            return logger.isEnabled(level, marker, message, p0, p1);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, String message, 
Object p0, Object p1, Object p2) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level, Marker marker, String message, Object p0, Object 
p1, Object p2, Object p3) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level, Marker marker, String message, Object p0, Object 
p1, Object p2, Object p3, Object p4) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level,
+                Marker marker,
+                String message,
+                Object p0,
+                Object p1,
+                Object p2,
+                Object p3,
+                Object p4,
+                Object p5) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4, p5);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level,
+                Marker marker,
+                String message,
+                Object p0,
+                Object p1,
+                Object p2,
+                Object p3,
+                Object p4,
+                Object p5,
+                Object p6) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4, p5, p6);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level,
+                Marker marker,
+                String message,
+                Object p0,
+                Object p1,
+                Object p2,
+                Object p3,
+                Object p4,
+                Object p5,
+                Object p6,
+                Object p7) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4, p5, p6, p7);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level,
+                Marker marker,
+                String message,
+                Object p0,
+                Object p1,
+                Object p2,
+                Object p3,
+                Object p4,
+                Object p5,
+                Object p6,
+                Object p7,
+                Object p8) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4, p5, p6, p7, p8);
+        }
+
+        @Override
+        public boolean isEnabled(
+                Level level,
+                Marker marker,
+                String message,
+                Object p0,
+                Object p1,
+                Object p2,
+                Object p3,
+                Object p4,
+                Object p5,
+                Object p6,
+                Object p7,
+                Object p8,
+                Object p9) {
+            return logger.isEnabled(level, marker, message, p0, p1, p2, p3, 
p4, p5, p6, p7, p8, p9);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, CharSequence 
message, Throwable t) {
+            return logger.isEnabled(level, marker, message, t);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, Object message, 
Throwable t) {
+            return logger.isEnabled(level, marker, message, t);
+        }
+
+        @Override
+        public boolean isEnabled(Level level, Marker marker, Message message, 
Throwable t) {
+            return logger.isEnabled(level, marker, message, t);
+        }
+
+        @Override
+        public void addAppender(Appender appender) {}
+
+        @Override
+        public void removeAppender(Appender appender) {}
+
+        @Override
+        public Map<String, Appender> getAppenders() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public Iterator<Filter> getFilters() {
+            return Collections.emptyIterator();
+        }
+
+        @Override
+        public Level getLevel() {
+            return logger.getLevel();
+        }
+
+        @Override
+        public int filterCount() {
+            return 0;
+        }
+
+        @Override
+        public void addFilter(Filter filter) {}
+
+        @Override
+        public boolean isAdditive() {
+            return false;
+        }
+
+        @Override
+        public void setAdditive(boolean additive) {}
+
+        @Override
+        public LogBuilder atLevel(Level level) {
+            return logger.atLevel(level);
+        }
+
+        @Override
+        protected void updateConfiguration(Configuration newConfig) {}
+    }
+}
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
index 1a4a7ed744..e7ee25c3d4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
@@ -238,12 +238,14 @@ public final class Server {
      * @param loggerContextName name of the logger context to unregister
      */
     public static void unregisterLoggerContext(final String loggerContextName) 
{
-        if (isJmxDisabled()) {
-            LOGGER.debug("JMX disabled for Log4j2. Not unregistering MBeans.");
-            return;
+        if (loggerContextName != null) {
+            if (isJmxDisabled()) {
+                LOGGER.debug("JMX disabled for Log4j2. Not unregistering 
MBeans.");
+                return;
+            }
+            final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+            unregisterLoggerContext(loggerContextName, mbs);
         }
-        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-        unregisterLoggerContext(loggerContextName, mbs);
     }
 
     /**
diff --git a/src/changelog/.3.x.x/1799_ignore _propertysource_errors.xml 
b/src/changelog/.3.x.x/1799_ignore _propertysource_errors.xml
new file mode 100644
index 0000000000..5810ca6b6f
--- /dev/null
+++ b/src/changelog/.3.x.x/1799_ignore _propertysource_errors.xml       
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="http://logging.apache.org/log4j/changelog";
+       xsi:schemaLocation="http://logging.apache.org/log4j/changelog 
https://logging.apache.org/log4j/changelog-0.1.2.xsd";
+       type="changed">
+  <issue id="Spring-33450" 
link="https://github.com/spring-projects/spring-boot/issues/33450"/>
+  <issue id="1799" 
link="https://github.com/apache/logging-log4j2/issues/1799"/>
+  <author id="rgoers"/>
+  <description format="asciidoc">Ignore exceptions thrown by PropertySources. 
Eliminate ClassCastException when SimpleLoggerContext is used.</description>
+</entry>


Reply via email to