Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ public interface LoggerContext {
/**
* Gets the anchor for some other context, such as a ClassLoader or ServletContext.
* @return The external context.
* @deprecated Use {@link #getObject(String)} instead.
* @since 2.27.0
*/
@Deprecated
Object getExternalContext();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.logging.log4j.core;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.withSettings;
Expand Down Expand Up @@ -101,4 +102,23 @@ void start_should_fallback_on_reconfigure_if_context_already_started(final TestI
assertThat(loggerContext.getConfiguration()).isSameAs(configuration);
}
}

@Test
public void testLegacyExternalContextCompatibility() {
LoggerContext ctx = new LoggerContext("TestContext");
String legacyValue = "Spring-Boot-Flag";
ctx.setExternalContext(legacyValue);
assertEquals(legacyValue, ctx.getExternalContext());
assertEquals(legacyValue, ctx.getObject("__EXTERNAL_CONTEXT_KEY__"));
}

@Test
public void testCollisionPrevention() {
LoggerContext ctx = new LoggerContext("CollisionTest");
ctx.setExternalContext("Spring-Flag");
String mockServletContext = "MockServletContext";
ctx.putObject("org.apache.logging.log4j.web.servletContext", mockServletContext);
assertEquals("Spring-Flag", ctx.getExternalContext());
assertEquals(mockServletContext, ctx.getObject("org.apache.logging.log4j.web.servletContext"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ public LoggerContext(final String name) {
*
* @param name The context name.
* @param externalContext The external context.
* @deprecated Use {@link #LoggerContext(String)} and {@link #putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public LoggerContext(final String name, final Object externalContext) {
this(name, externalContext, (URI) null);
}
Expand All @@ -163,11 +166,14 @@ public LoggerContext(final String name, final Object externalContext) {
* @param name The context name.
* @param externalContext The external context.
* @param configLocn The location of the configuration as a URI.
* @deprecated Use {@link #LoggerContext(String)} and {@link #putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public LoggerContext(final String name, final Object externalContext, final URI configLocn) {
this.contextName = name;
if (externalContext != null) {
externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
this.putObject(EXTERNAL_CONTEXT_KEY, externalContext);
}
this.configLocation = configLocn;
}
Expand Down Expand Up @@ -531,7 +537,10 @@ public boolean removeObject(final String key, final Object value) {
* Sets the external context.
*
* @param context The external context.
* @deprecated Use {@link #putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public void setExternalContext(final Object context) {
if (context != null) {
this.externalMap.put(EXTERNAL_CONTEXT_KEY, context);
Expand All @@ -544,8 +553,11 @@ public void setExternalContext(final Object context) {
* Returns the external context.
*
* @return The external context.
* @deprecated Use {@link #getObject(String)} instead.
* @since 2.27.0
*/
@Override
@Deprecated
public Object getExternalContext() {
return this.externalMap.get(EXTERNAL_CONTEXT_KEY);
}
Expand Down Expand Up @@ -766,7 +778,7 @@ public void setConfigLocation(final URI configLocation) {
* Reconfigures the context.
*/
private void reconfigure(final URI configURI) {
final Object externalContext = externalMap.get(EXTERNAL_CONTEXT_KEY);
final Object externalContext = getExternalContext();
final ClassLoader cl = externalContext instanceof ClassLoader ? (ClassLoader) externalContext : null;
LOGGER.debug(
"Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ private void initializeShutdownCallbackRegistry() {
* for the caller if a more appropriate Context can be determined.
* @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
* @return The LoggerContext.
* @deprecated Use {@link org.apache.logging.log4j.spi.LoggerContext#putObject(String, Object)} instead.
* @since 2.27.0
*/
@Override
@Deprecated
public LoggerContext getContext(
final String fqcn, final ClassLoader loader, final Object externalContext, final boolean currentContext) {
final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
Expand All @@ -171,7 +174,10 @@ public LoggerContext getContext(
* for the caller if a more appropriate Context can be determined.
* @param source The configuration source.
* @return The LoggerContext.
* @deprecated Use {@link org.apache.logging.log4j.spi.LoggerContext#putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public LoggerContext getContext(
final String fqcn,
final ClassLoader loader,
Expand Down Expand Up @@ -205,7 +211,10 @@ public LoggerContext getContext(
* for the caller if a more appropriate Context can be determined.
* @param configuration The Configuration.
* @return The LoggerContext.
* @deprecated Use {@link org.apache.logging.log4j.spi.LoggerContext#putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public LoggerContext getContext(
final String fqcn,
final ClassLoader loader,
Expand Down Expand Up @@ -236,8 +245,11 @@ public LoggerContext getContext(
* for the caller if a more appropriate Context can be determined.
* @param configLocation The location of the configuration for the LoggerContext (or null).
* @return The LoggerContext.
* @deprecated Use {@link org.apache.logging.log4j.spi.LoggerContext#putObject(String, Object)} instead.
* @since 2.27.0
*/
@Override
@Deprecated
public LoggerContext getContext(
final String fqcn,
final ClassLoader loader,
Expand Down Expand Up @@ -293,18 +305,31 @@ public LoggerContext getContext(
return ctx;
}

/**
* Loads the LoggerContext using the ContextSelector.
* @param fqcn The fully qualified class name of the caller.
* @param loader The ClassLoader to use or null.
* @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
* @param currentContext If true returns the current Context, if false returns the Context appropriate
* for the caller if a more appropriate Context can be determined.
* @param configLocations The locations of the configuration for the LoggerContext (or null).
* @return The LoggerContext.
* @deprecated Use {@link org.apache.logging.log4j.spi.LoggerContext#putObject(String, Object)} instead.
* @since 2.27.0
*/
@Deprecated
public LoggerContext getContext(
final String fqcn,
final ClassLoader loader,
final Object externalContext,
final boolean currentContext,
final List<URI> configLocations,
final String name) {
final LoggerContext ctx =
selector.getContext(fqcn, loader, currentContext, null /*this probably needs to change*/);
final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
if (externalContext != null && ctx.getExternalContext() == null) {
ctx.setExternalContext(externalContext);
}

if (name != null) {
ctx.setName(name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@
import javax.servlet.ServletContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.AbstractLifeCycle;
import org.apache.logging.log4j.core.LifeCycle;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.async.AsyncLoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
import org.apache.logging.log4j.core.impl.ContextAnchor;
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
import org.apache.logging.log4j.core.lookup.ConfigurationStrSubstitutor;
Expand All @@ -53,6 +58,8 @@ final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWe

private static final String WEB_INF = "/WEB-INF/";

private static final String SERVLET_CONTEXT_KEY = "org.apache.logging.log4j.web.servletContext";

static {
if (Loader.isClassAvailable("org.apache.logging.log4j.core.web.JNDIContextFilter")) {
throw new IllegalStateException("You are using Log4j 2 in a web application with the old, extinct "
Expand Down Expand Up @@ -133,8 +140,8 @@ private void initializeJndi(final String location) {
final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
if (selector instanceof NamedContextSelector) {
this.namedContextSelector = (NamedContextSelector) selector;
context = this.namedContextSelector.locateContext(
this.name, WebLoggerContextUtils.createExternalEntry(this.servletContext), configLocation);
context = this.namedContextSelector.locateContext(this.name, null, configLocation);
context.putObject(SERVLET_CONTEXT_KEY, this.servletContext);
ContextAnchor.THREAD_CONTEXT.set(context);
if (context.isInitialized()) {
context.start();
Expand Down Expand Up @@ -168,13 +175,49 @@ private void initializeNonJndi(final String location) {
LOGGER.error("No Log4j context configuration provided. This is very unusual.");
this.name = new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(new Date());
}

if (location != null && location.contains(",")) {
final List<URI> uris = getConfigURIs(location);
this.loggerContext = Configurator.initialize(
this.name,
this.getClassLoader(),
uris,
WebLoggerContextUtils.createExternalEntry(this.servletContext));
final LoggerContextFactory factory = LogManager.getFactory();
if (factory instanceof Log4jContextFactory) {
final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
this.loggerContext = selector.getContext(
Log4jWebInitializerImpl.class.getName(), this.getClassLoader(), false, null);
if (this.loggerContext != null) {
this.loggerContext.putObject(SERVLET_CONTEXT_KEY, this.servletContext);
if (this.name != null) {
this.loggerContext.setName(this.name);
}
if (this.loggerContext.getState() == LifeCycle.State.INITIALIZED) {
ContextAnchor.THREAD_CONTEXT.set(this.loggerContext);
try {
final List<AbstractConfiguration> configurations = new ArrayList<>(uris.size());
for (final URI configLocation : uris) {
final Configuration config = ConfigurationFactory.getInstance()
.getConfiguration(this.loggerContext, this.name, configLocation);
if (config instanceof AbstractConfiguration) {
configurations.add((AbstractConfiguration) config);
}
}
if (configurations.size() == 1) {
this.loggerContext.start(configurations.get(0));
} else if (configurations.size() > 1) {
this.loggerContext.start(new CompositeConfiguration(configurations));
} else {
this.loggerContext.start();
}
} finally {
ContextAnchor.THREAD_CONTEXT.remove();
}
}
}
} else {
this.loggerContext =
Configurator.initialize(this.name, this.getClassLoader(), uris, this.servletContext);
if (this.loggerContext != null) {
this.loggerContext.putObject(SERVLET_CONTEXT_KEY, this.servletContext);
}
}
return;
}

Expand Down Expand Up @@ -275,7 +318,7 @@ public synchronized boolean stop(final long timeout, final TimeUnit timeUnit) {
this.namedContextSelector.removeContext(this.name);
}
this.loggerContext.stop(timeout, timeUnit);
this.loggerContext.setExternalContext(null);
this.loggerContext.removeObject(SERVLET_CONTEXT_KEY);
this.loggerContext = null;
}
this.setStopped();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public final class WebLoggerContextUtils {
private WebLoggerContextUtils() {}

private static final Lock WEB_SUPPORT_LOOKUP = new ReentrantLock();
private static final String SERVLET_CONTEXT = "__SERVLET_CONTEXT__";

private static final String SERVLET_CONTEXT = "org.apache.logging.log4j.web.servletContext";
/**
* Finds the main {@link org.apache.logging.log4j.core.LoggerContext} configured for the given ServletContext.
*
Expand Down Expand Up @@ -110,18 +109,29 @@ public static Runnable wrapExecutionContext(final ServletContext servletContext,
};
}

/**
* @deprecated Use {@link #setServletContext(LoggerContext, ServletContext)} instead.
* @since 2.27.0
*/
@Deprecated
public static Map.Entry<String, Object> createExternalEntry(final ServletContext servletContext) {
return new AbstractMap.SimpleEntry<>(SERVLET_CONTEXT, servletContext);
}

public static void setServletContext(LoggerContext lc, ServletContext servletContext) {
/**
* Sets the ServletContext for the given LoggerContext.
*
* @param lc the LoggerContext
* @param servletContext the ServletContext
*/
public static void setServletContext(final LoggerContext lc, final ServletContext servletContext) {
if (lc != null) {
lc.putObject(SERVLET_CONTEXT, servletContext);
}
}

/**
* Gets the current {@link ServletContext} if it has already been assigned to a LoggerContext's external context.
* Gets the current {@link ServletContext} if it has already been assigned to a LoggerContext.
*
* @return the current ServletContext attached to a LoggerContext or {@code null} if none could be found
* @since 2.1
Expand All @@ -132,10 +142,20 @@ public static ServletContext getServletContext() {
lc = LogManager.getContext(false);
}

final Object obj = lc != null ? lc.getObject(SERVLET_CONTEXT) : null;
if (lc == null) {
return null;
}

final Object obj = lc.getObject(SERVLET_CONTEXT);
if (obj instanceof ServletContext) {
return (ServletContext) obj;
}

final Object legacy = lc.getExternalContext();
if (legacy instanceof ServletContext) {
return (ServletContext) legacy;
}

return null;
}
}
Loading