18
18
19
19
import static java .util .Objects .requireNonNull ;
20
20
21
- import java .lang .ref .WeakReference ;
22
21
import java .util .ArrayList ;
23
22
import java .util .Collection ;
24
23
import java .util .Collections ;
25
24
import java .util .HashMap ;
26
25
import java .util .Map ;
27
- import java .util .Objects ;
28
26
import java .util .WeakHashMap ;
29
27
import java .util .concurrent .ConcurrentHashMap ;
30
28
import java .util .concurrent .locks .Lock ;
31
29
import java .util .concurrent .locks .ReadWriteLock ;
32
30
import java .util .concurrent .locks .ReentrantReadWriteLock ;
31
+ import org .apache .logging .log4j .Logger ;
33
32
import org .apache .logging .log4j .message .MessageFactory ;
34
33
import org .apache .logging .log4j .message .ParameterizedMessageFactory ;
34
+ import org .jspecify .annotations .Nullable ;
35
35
36
36
/**
37
37
* Convenience class to be used as an {@link ExtendedLogger} registry by {@code LoggerContext} implementations.
38
38
*/
39
39
public class LoggerRegistry <T extends ExtendedLogger > {
40
40
41
- private final Map <String , Map <MessageFactory , WeakReference < T >>> loggerRefByMessageFactoryByName = new HashMap <>();
41
+ private final Map <String , Map <MessageFactory , T >> loggerByMessageFactoryByName = new HashMap <>();
42
42
43
43
private final ReadWriteLock lock = new ReentrantReadWriteLock ();
44
44
@@ -127,7 +127,7 @@ public LoggerRegistry(final MapFactory<T> mapFactory) {
127
127
* @param name a logger name
128
128
* @return the logger associated with the name
129
129
*/
130
- public T getLogger (final String name ) {
130
+ public @ Nullable T getLogger (final String name ) {
131
131
requireNonNull (name , "name" );
132
132
return getLogger (name , null );
133
133
}
@@ -144,39 +144,29 @@ public T getLogger(final String name) {
144
144
* @param messageFactory a message factory
145
145
* @return the logger associated with the given name and message factory
146
146
*/
147
- public T getLogger (final String name , final MessageFactory messageFactory ) {
147
+ public @ Nullable T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
148
148
requireNonNull (name , "name" );
149
149
readLock .lock ();
150
150
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 );
156
152
final MessageFactory effectiveMessageFactory =
157
153
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 );
163
155
} finally {
164
156
readLock .unlock ();
165
157
}
166
158
}
167
159
168
160
public Collection <T > getLoggers () {
169
- return getLoggers (new ArrayList <T >());
161
+ return getLoggers (new ArrayList <>());
170
162
}
171
163
172
164
public Collection <T > getLoggers (final Collection <T > destination ) {
173
165
requireNonNull (destination , "destination" );
174
166
readLock .lock ();
175
167
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 ())
180
170
.forEach (destination ::add );
181
171
} finally {
182
172
readLock .unlock ();
@@ -196,7 +186,7 @@ public Collection<T> getLoggers(final Collection<T> destination) {
196
186
*/
197
187
public boolean hasLogger (final String name ) {
198
188
requireNonNull (name , "name" );
199
- final T logger = getLogger (name );
189
+ final @ Nullable T logger = getLogger (name );
200
190
return logger != null ;
201
191
}
202
192
@@ -215,7 +205,7 @@ public boolean hasLogger(final String name) {
215
205
*/
216
206
public boolean hasLogger (final String name , final MessageFactory messageFactory ) {
217
207
requireNonNull (name , "name" );
218
- final T logger = getLogger (name , messageFactory );
208
+ final @ Nullable T logger = getLogger (name , messageFactory );
219
209
return logger != null ;
220
210
}
221
211
@@ -232,7 +222,7 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
232
222
requireNonNull (messageFactoryClass , "messageFactoryClass" );
233
223
readLock .lock ();
234
224
try {
235
- return loggerRefByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
225
+ return loggerByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
236
226
.anyMatch (messageFactory -> messageFactoryClass .equals (messageFactory .getClass ()));
237
227
} finally {
238
228
readLock .unlock ();
@@ -241,34 +231,42 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
241
231
242
232
/**
243
233
* 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>
245
238
*
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
248
241
* @param logger a logger instance
249
242
*/
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 ) {
251
244
252
245
// Check arguments
246
+ requireNonNull (name , "name" );
253
247
requireNonNull (logger , "logger" );
254
248
255
249
// Insert the logger
256
250
writeLock .lock ();
257
251
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 );
265
263
}
266
264
} finally {
267
265
writeLock .unlock ();
268
266
}
269
267
}
270
268
271
- private Map <MessageFactory , WeakReference < T > > createLoggerRefByMessageFactoryMap (final String ignored ) {
269
+ private Map <MessageFactory , T > createLoggerRefByMessageFactoryMap (final String ignored ) {
272
270
return new WeakHashMap <>();
273
271
}
274
272
}
0 commit comments