Skip to content

Commit

Permalink
Implement MessageFactory-namespaced logger registry (#2936)
Browse files Browse the repository at this point in the history
Co-authored-by: Piotr P. Karwasz <piotr.github@karwasz.org>
  • Loading branch information
vy and ppkarwasz authored Sep 16, 2024
1 parent 1f148a4 commit 724281c
Show file tree
Hide file tree
Showing 22 changed files with 463 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
*/
package org.apache.logging.log4j.message;

import java.util.Objects;
import java.util.ResourceBundle;
import org.jspecify.annotations.Nullable;

/**
* Creates {@link FormattedMessage} instances for {@link MessageFactory2} methods (and {@link MessageFactory} by
Expand All @@ -33,8 +35,11 @@
public class LocalizedMessageFactory extends AbstractMessageFactory {
private static final long serialVersionUID = -1996295808703146741L;

@Nullable
// FIXME: cannot use ResourceBundle name for serialization until Java 8
private final transient ResourceBundle resourceBundle;

@Nullable
private final String baseName;

public LocalizedMessageFactory(final ResourceBundle resourceBundle) {
Expand Down Expand Up @@ -92,4 +97,21 @@ public Message newMessage(final String key, final Object... params) {
}
return new LocalizedMessage(resourceBundle, key, params);
}

@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
final LocalizedMessageFactory that = (LocalizedMessageFactory) object;
return Objects.equals(resourceBundle, that.resourceBundle) && Objects.equals(baseName, that.baseName);
}

@Override
public int hashCode() {
return Objects.hash(resourceBundle, baseName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* Public Message Types used for Log4j 2. Users may implement their own Messages.
*/
@Export
@Version("2.24.0")
@Version("2.25.0")
package org.apache.logging.log4j.message;

import org.osgi.annotation.bundle.Export;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
import java.io.PrintStream;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.message.MessageFactory;
import org.apache.logging.log4j.message.ParameterizedMessageFactory;
import org.apache.logging.log4j.simple.internal.SimpleProvider;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.spi.LoggerContext;
import org.apache.logging.log4j.spi.LoggerRegistry;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.jspecify.annotations.Nullable;

/**
* A simple {@link LoggerContext} implementation.
Expand All @@ -41,6 +42,8 @@ public class SimpleLoggerContext implements LoggerContext {
/** All system properties used by <code>SimpleLog</code> start with this */
protected static final String SYSTEM_PREFIX = "org.apache.logging.log4j.simplelog.";

private static final MessageFactory DEFAULT_MESSAGE_FACTORY = ParameterizedMessageFactory.INSTANCE;

private final PropertiesUtil props;

/** Include the instance name in the log message? */
Expand Down Expand Up @@ -96,14 +99,14 @@ public ExtendedLogger getLogger(final String name) {
}

@Override
public ExtendedLogger getLogger(final String name, final MessageFactory messageFactory) {
// Note: This is the only method where we add entries to the 'loggerRegistry' ivar.
final ExtendedLogger extendedLogger = loggerRegistry.getLogger(name, messageFactory);
if (extendedLogger != null) {
AbstractLogger.checkMessageFactory(extendedLogger, messageFactory);
return extendedLogger;
}
final SimpleLogger simpleLogger = new SimpleLogger(
public ExtendedLogger getLogger(final String name, @Nullable final MessageFactory messageFactory) {
final MessageFactory effectiveMessageFactory =
messageFactory != null ? messageFactory : DEFAULT_MESSAGE_FACTORY;
return loggerRegistry.computeIfAbsent(name, effectiveMessageFactory, this::createLogger);
}

private ExtendedLogger createLogger(final String name, @Nullable final MessageFactory messageFactory) {
return new SimpleLogger(
name,
defaultLevel,
showLogName,
Expand All @@ -114,8 +117,6 @@ public ExtendedLogger getLogger(final String name, final MessageFactory messageF
messageFactory,
props,
stream);
loggerRegistry.putIfAbsent(name, messageFactory, simpleLogger);
return loggerRegistry.getLogger(name, messageFactory);
}

/**
Expand All @@ -131,16 +132,18 @@ public LoggerRegistry<ExtendedLogger> getLoggerRegistry() {

@Override
public boolean hasLogger(final String name) {
return false;
return loggerRegistry.hasLogger(name, DEFAULT_MESSAGE_FACTORY);
}

@Override
public boolean hasLogger(final String name, final Class<? extends MessageFactory> messageFactoryClass) {
return false;
return loggerRegistry.hasLogger(name, messageFactoryClass);
}

@Override
public boolean hasLogger(final String name, final MessageFactory messageFactory) {
return false;
public boolean hasLogger(final String name, @Nullable final MessageFactory messageFactory) {
final MessageFactory effectiveMessageFactory =
messageFactory != null ? messageFactory : DEFAULT_MESSAGE_FACTORY;
return loggerRegistry.hasLogger(name, effectiveMessageFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* Providers are able to be loaded at runtime.
*/
@Export
@Version("2.24.0")
@Version("2.25.0")
package org.apache.logging.log4j.simple;

import org.osgi.annotation.bundle.Export;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,11 @@ private static MessageFactory2 adaptMessageFactory(final MessageFactory result)
*
* @param logger The logger to check
* @param messageFactory The message factory to check.
* @deprecated As of version {@code 2.25.0}, planned to be removed!
* Instead, in {@link LoggerContext#getLogger(String, MessageFactory)} implementations, namespace loggers with message factories.
* If your implementation uses {@link LoggerRegistry}, you are already covered.
*/
@Deprecated
public static void checkMessageFactory(final ExtendedLogger logger, final MessageFactory messageFactory) {
final String name = logger.getName();
final MessageFactory loggerMessageFactory = logger.getMessageFactory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MessageFactory;
import org.jspecify.annotations.Nullable;

/**
* Anchor point for logging implementations.
Expand Down Expand Up @@ -54,7 +55,7 @@ default ExtendedLogger getLogger(Class<?> cls) {
* @return The logger.
* @since 2.14.0
*/
default ExtendedLogger getLogger(Class<?> cls, MessageFactory messageFactory) {
default ExtendedLogger getLogger(Class<?> cls, @Nullable MessageFactory messageFactory) {
final String canonicalName = cls.getCanonicalName();
return getLogger(canonicalName != null ? canonicalName : cls.getName(), messageFactory);
}
Expand All @@ -73,7 +74,7 @@ default ExtendedLogger getLogger(Class<?> cls, MessageFactory messageFactory) {
* the logger but will log a warning if mismatched.
* @return The logger with the specified name.
*/
ExtendedLogger getLogger(String name, MessageFactory messageFactory);
ExtendedLogger getLogger(String name, @Nullable MessageFactory messageFactory);

/**
* Gets the LoggerRegistry.
Expand Down Expand Up @@ -118,7 +119,7 @@ default Object getObject(String key) {
* @return true if the Logger exists, false otherwise.
* @since 2.5
*/
boolean hasLogger(String name, MessageFactory messageFactory);
boolean hasLogger(String name, @Nullable MessageFactory messageFactory);

/**
* Associates an object into the LoggerContext by name for later use.
Expand Down
Loading

0 comments on commit 724281c

Please sign in to comment.