1818
1919import static java .util .Objects .requireNonNull ;
2020
21- import java .lang .ref .WeakReference ;
2221import java .util .ArrayList ;
2322import java .util .Collection ;
2423import java .util .Collections ;
2524import java .util .HashMap ;
2625import java .util .Map ;
27- import java .util .Objects ;
2826import java .util .WeakHashMap ;
2927import java .util .concurrent .ConcurrentHashMap ;
3028import java .util .concurrent .locks .Lock ;
3129import java .util .concurrent .locks .ReadWriteLock ;
3230import java .util .concurrent .locks .ReentrantReadWriteLock ;
31+ import org .apache .logging .log4j .Logger ;
3332import org .apache .logging .log4j .message .MessageFactory ;
3433import org .apache .logging .log4j .message .ParameterizedMessageFactory ;
34+ import org .jspecify .annotations .Nullable ;
3535
3636/**
3737 * Convenience class to be used as an {@link ExtendedLogger} registry by {@code LoggerContext} implementations.
3838 */
3939public class LoggerRegistry <T extends ExtendedLogger > {
4040
41- private final Map <String , Map <MessageFactory , WeakReference < T >>> loggerRefByMessageFactoryByName = new HashMap <>();
41+ private final Map <String , Map <MessageFactory , T >> loggerByMessageFactoryByName = new HashMap <>();
4242
4343 private final ReadWriteLock lock = new ReentrantReadWriteLock ();
4444
@@ -127,7 +127,7 @@ public LoggerRegistry(final MapFactory<T> mapFactory) {
127127 * @param name a logger name
128128 * @return the logger associated with the name
129129 */
130- public T getLogger (final String name ) {
130+ public @ Nullable T getLogger (final String name ) {
131131 requireNonNull (name , "name" );
132132 return getLogger (name , null );
133133 }
@@ -144,39 +144,29 @@ public T getLogger(final String name) {
144144 * @param messageFactory a message factory
145145 * @return the logger associated with the given name and message factory
146146 */
147- public T getLogger (final String name , final MessageFactory messageFactory ) {
147+ public @ Nullable T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
148148 requireNonNull (name , "name" );
149149 readLock .lock ();
150150 try {
151- final Map <MessageFactory , WeakReference <T >> loggerRefByMessageFactory =
152- loggerRefByMessageFactoryByName .get (name );
153- if (loggerRefByMessageFactory == null ) {
154- return null ;
155- }
151+ final @ Nullable Map <MessageFactory , T > loggerByMessageFactory = loggerByMessageFactoryByName .get (name );
156152 final MessageFactory effectiveMessageFactory =
157153 messageFactory != null ? messageFactory : ParameterizedMessageFactory .INSTANCE ;
158- final WeakReference <T > loggerRef = loggerRefByMessageFactory .get (effectiveMessageFactory );
159- if (loggerRef == null ) {
160- return null ;
161- }
162- return loggerRef .get ();
154+ return loggerByMessageFactory == null ? null : loggerByMessageFactory .get (effectiveMessageFactory );
163155 } finally {
164156 readLock .unlock ();
165157 }
166158 }
167159
168160 public Collection <T > getLoggers () {
169- return getLoggers (new ArrayList <T >());
161+ return getLoggers (new ArrayList <>());
170162 }
171163
172164 public Collection <T > getLoggers (final Collection <T > destination ) {
173165 requireNonNull (destination , "destination" );
174166 readLock .lock ();
175167 try {
176- loggerRefByMessageFactoryByName .values ().stream ()
177- .flatMap (loggerRefByMessageFactory ->
178- loggerRefByMessageFactory .values ().stream ().map (WeakReference ::get ))
179- .filter (Objects ::nonNull )
168+ loggerByMessageFactoryByName .values ().stream ()
169+ .flatMap (loggerByMessageFactory -> loggerByMessageFactory .values ().stream ())
180170 .forEach (destination ::add );
181171 } finally {
182172 readLock .unlock ();
@@ -196,7 +186,7 @@ public Collection<T> getLoggers(final Collection<T> destination) {
196186 */
197187 public boolean hasLogger (final String name ) {
198188 requireNonNull (name , "name" );
199- final T logger = getLogger (name );
189+ final @ Nullable T logger = getLogger (name );
200190 return logger != null ;
201191 }
202192
@@ -215,7 +205,7 @@ public boolean hasLogger(final String name) {
215205 */
216206 public boolean hasLogger (final String name , final MessageFactory messageFactory ) {
217207 requireNonNull (name , "name" );
218- final T logger = getLogger (name , messageFactory );
208+ final @ Nullable T logger = getLogger (name , messageFactory );
219209 return logger != null ;
220210 }
221211
@@ -232,7 +222,7 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
232222 requireNonNull (messageFactoryClass , "messageFactoryClass" );
233223 readLock .lock ();
234224 try {
235- return loggerRefByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
225+ return loggerByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
236226 .anyMatch (messageFactory -> messageFactoryClass .equals (messageFactory .getClass ()));
237227 } finally {
238228 readLock .unlock ();
@@ -241,34 +231,42 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
241231
242232 /**
243233 * Registers the provided logger.
244- * <b>Logger name and message factory parameters are ignored</b>, those will be obtained from the logger instead.
234+ * <p>
235+ * The logger will be registered using the keys provided by the {@code name} and {@code messageFactory} parameters
236+ * and the values of {@link Logger#getName()} and {@link Logger#getMessageFactory()}.
237+ * </p>
245238 *
246- * @param name ignored – kept for backward compatibility
247- * @param messageFactory ignored – kept for backward compatibility
239+ * @param name a logger name
240+ * @param messageFactory a message factory
248241 * @param logger a logger instance
249242 */
250- public void putIfAbsent (final String name , final MessageFactory messageFactory , final T logger ) {
243+ public void putIfAbsent (final String name , @ Nullable final MessageFactory messageFactory , final T logger ) {
251244
252245 // Check arguments
246+ requireNonNull (name , "name" );
253247 requireNonNull (logger , "logger" );
254248
255249 // Insert the logger
256250 writeLock .lock ();
257251 try {
258- final Map <MessageFactory , WeakReference <T >> loggerRefByMessageFactory =
259- loggerRefByMessageFactoryByName .computeIfAbsent (
260- logger .getName (), this ::createLoggerRefByMessageFactoryMap );
261- final MessageFactory loggerMessageFactory = logger .getMessageFactory ();
262- final WeakReference <T > loggerRef = loggerRefByMessageFactory .get (loggerMessageFactory );
263- if (loggerRef == null || loggerRef .get () == null ) {
264- loggerRefByMessageFactory .put (loggerMessageFactory , new WeakReference <>(logger ));
252+ final MessageFactory effectiveMessageFactory =
253+ messageFactory != null ? messageFactory : ParameterizedMessageFactory .INSTANCE ;
254+ // Register using the keys provided by the caller
255+ loggerByMessageFactoryByName
256+ .computeIfAbsent (name , this ::createLoggerRefByMessageFactoryMap )
257+ .putIfAbsent (effectiveMessageFactory , logger );
258+ // Also register using the values extracted from `logger`
259+ if (!name .equals (logger .getName ()) || !effectiveMessageFactory .equals (logger .getMessageFactory ())) {
260+ loggerByMessageFactoryByName
261+ .computeIfAbsent (logger .getName (), this ::createLoggerRefByMessageFactoryMap )
262+ .putIfAbsent (logger .getMessageFactory (), logger );
265263 }
266264 } finally {
267265 writeLock .unlock ();
268266 }
269267 }
270268
271- private Map <MessageFactory , WeakReference < T > > createLoggerRefByMessageFactoryMap (final String ignored ) {
269+ private Map <MessageFactory , T > createLoggerRefByMessageFactoryMap (final String ignored ) {
272270 return new WeakHashMap <>();
273271 }
274272}
0 commit comments