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 ;
33
- import java .util .function .BiFunction ;
34
31
import org .apache .logging .log4j .message .MessageFactory ;
35
32
import org .apache .logging .log4j .message .ParameterizedMessageFactory ;
36
- import org .apache .logging .log4j .status .StatusLogger ;
37
33
import org .jspecify .annotations .NullMarked ;
38
34
import org .jspecify .annotations .Nullable ;
39
35
43
39
@ NullMarked
44
40
public class LoggerRegistry <T extends ExtendedLogger > {
45
41
46
- private final Map <String , Map <MessageFactory , WeakReference < T >>> loggerRefByMessageFactoryByName = new HashMap <>();
42
+ private final Map <String , Map <MessageFactory , T >> loggerByMessageFactoryByName = new HashMap <>();
47
43
48
44
private final ReadWriteLock lock = new ReentrantReadWriteLock ();
49
45
@@ -143,7 +139,7 @@ public LoggerRegistry(@Nullable final MapFactory<T> mapFactory) {
143
139
* Use {@link #getLogger(String, MessageFactory)} instead.
144
140
*/
145
141
@ Deprecated
146
- public T getLogger (final String name ) {
142
+ public @ Nullable T getLogger (final String name ) {
147
143
requireNonNull (name , "name" );
148
144
return getLogger (name , null );
149
145
}
@@ -160,39 +156,29 @@ public T getLogger(final String name) {
160
156
* @param messageFactory a message factory
161
157
* @return the logger associated with the given name and message factory
162
158
*/
163
- public T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
159
+ public @ Nullable T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
164
160
requireNonNull (name , "name" );
165
161
readLock .lock ();
166
162
try {
167
- final Map <MessageFactory , WeakReference <T >> loggerRefByMessageFactory =
168
- loggerRefByMessageFactoryByName .get (name );
169
- if (loggerRefByMessageFactory == null ) {
170
- return null ;
171
- }
163
+ final @ Nullable Map <MessageFactory , T > loggerByMessageFactory = loggerByMessageFactoryByName .get (name );
172
164
final MessageFactory effectiveMessageFactory =
173
165
messageFactory != null ? messageFactory : ParameterizedMessageFactory .INSTANCE ;
174
- final WeakReference <T > loggerRef = loggerRefByMessageFactory .get (effectiveMessageFactory );
175
- if (loggerRef == null ) {
176
- return null ;
177
- }
178
- return loggerRef .get ();
166
+ return loggerByMessageFactory == null ? null : loggerByMessageFactory .get (effectiveMessageFactory );
179
167
} finally {
180
168
readLock .unlock ();
181
169
}
182
170
}
183
171
184
172
public Collection <T > getLoggers () {
185
- return getLoggers (new ArrayList <T >());
173
+ return getLoggers (new ArrayList <>());
186
174
}
187
175
188
176
public Collection <T > getLoggers (final Collection <T > destination ) {
189
177
requireNonNull (destination , "destination" );
190
178
readLock .lock ();
191
179
try {
192
- loggerRefByMessageFactoryByName .values ().stream ()
193
- .flatMap (loggerRefByMessageFactory ->
194
- loggerRefByMessageFactory .values ().stream ().map (WeakReference ::get ))
195
- .filter (Objects ::nonNull )
180
+ loggerByMessageFactoryByName .values ().stream ()
181
+ .flatMap (loggerByMessageFactory -> loggerByMessageFactory .values ().stream ())
196
182
.forEach (destination ::add );
197
183
} finally {
198
184
readLock .unlock ();
@@ -215,7 +201,7 @@ public Collection<T> getLoggers(final Collection<T> destination) {
215
201
@ Deprecated
216
202
public boolean hasLogger (final String name ) {
217
203
requireNonNull (name , "name" );
218
- final T logger = getLogger (name );
204
+ final @ Nullable T logger = getLogger (name );
219
205
return logger != null ;
220
206
}
221
207
@@ -234,7 +220,7 @@ public boolean hasLogger(final String name) {
234
220
*/
235
221
public boolean hasLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
236
222
requireNonNull (name , "name" );
237
- final T logger = getLogger (name , messageFactory );
223
+ final @ Nullable T logger = getLogger (name , messageFactory );
238
224
return logger != null ;
239
225
}
240
226
@@ -251,7 +237,7 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
251
237
requireNonNull (messageFactoryClass , "messageFactoryClass" );
252
238
readLock .lock ();
253
239
try {
254
- return loggerRefByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
240
+ return loggerByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
255
241
.anyMatch (messageFactory -> messageFactoryClass .equals (messageFactory .getClass ()));
256
242
} finally {
257
243
readLock .unlock ();
@@ -262,91 +248,30 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
262
248
* Registers the provided logger.
263
249
* <b>Logger name and message factory parameters are ignored</b>, those will be obtained from the logger instead.
264
250
*
265
- * @param name ignored – kept for backward compatibility
266
- * @param messageFactory ignored – kept for backward compatibility
251
+ * @param name a logger name
252
+ * @param messageFactory a message factory
267
253
* @param logger a logger instance
268
- * @deprecated As of version {@code 2.25.0}, planned to be removed!
269
- * Use {@link #computeIfAbsent(String, MessageFactory, BiFunction)} instead.
270
254
*/
271
- @ Deprecated
272
- public void putIfAbsent (
273
- @ Nullable final String name , @ Nullable final MessageFactory messageFactory , final T logger ) {
255
+ public void putIfAbsent (final String name , @ Nullable final MessageFactory messageFactory , final T logger ) {
274
256
275
257
// Check arguments
258
+ requireNonNull (name , "name" );
276
259
requireNonNull (logger , "logger" );
277
260
278
261
// Insert the logger
279
262
writeLock .lock ();
280
263
try {
281
- final String loggerName = logger .getName ();
282
- final Map <MessageFactory , WeakReference <T >> loggerRefByMessageFactory =
283
- loggerRefByMessageFactoryByName .computeIfAbsent (
284
- loggerName , this ::createLoggerRefByMessageFactoryMap );
285
- final MessageFactory loggerMessageFactory = logger .getMessageFactory ();
286
- final WeakReference <T > loggerRef = loggerRefByMessageFactory .get (loggerMessageFactory );
287
- if (loggerRef == null || loggerRef .get () == null ) {
288
- loggerRefByMessageFactory .put (loggerMessageFactory , new WeakReference <>(logger ));
289
- }
290
- } finally {
291
- writeLock .unlock ();
292
- }
293
- }
294
-
295
- public T computeIfAbsent (
296
- final String name ,
297
- final MessageFactory messageFactory ,
298
- final BiFunction <String , MessageFactory , T > loggerSupplier ) {
299
-
300
- // Check arguments
301
- requireNonNull (name , "name" );
302
- requireNonNull (messageFactory , "messageFactory" );
303
- requireNonNull (loggerSupplier , "loggerSupplier" );
304
-
305
- // Read lock fast path: See if logger already exists
306
- T logger = getLogger (name , messageFactory );
307
- if (logger != null ) {
308
- return logger ;
309
- }
310
-
311
- // Write lock slow path: Insert the logger
312
- writeLock .lock ();
313
- try {
314
-
315
- // See if the logger is created by another thread in the meantime
316
- final Map <MessageFactory , WeakReference <T >> loggerRefByMessageFactory =
317
- loggerRefByMessageFactoryByName .computeIfAbsent (name , this ::createLoggerRefByMessageFactoryMap );
318
- final WeakReference <T > loggerRef ;
319
- if ((loggerRef = loggerRefByMessageFactory .get (messageFactory )) != null
320
- && (logger = loggerRef .get ()) != null ) {
321
- return logger ;
322
- }
323
-
324
- // Create the logger
325
- logger = loggerSupplier .apply (name , messageFactory );
326
-
327
- // Report message factory mismatches, if there is any
328
- final MessageFactory loggerMessageFactory = logger .getMessageFactory ();
329
- if (!loggerMessageFactory .equals (messageFactory )) {
330
- StatusLogger .getLogger ()
331
- .error (
332
- "Newly registered logger with name `{}` and message factory `{}`, is requested to be associated with a different message factory: `{}`.\n "
333
- + "Effectively the message factory of the logger will be used and the other one will be ignored.\n "
334
- + "This generally hints a problem at the logger context implementation.\n "
335
- + "Please report this using the Log4j project issue tracker." ,
336
- name ,
337
- loggerMessageFactory ,
338
- messageFactory );
339
- }
340
-
341
- // Insert the logger
342
- loggerRefByMessageFactory .put (loggerMessageFactory , new WeakReference <>(logger ));
343
- return logger ;
264
+ final MessageFactory effectiveMessageFactory =
265
+ messageFactory != null ? messageFactory : ParameterizedMessageFactory .INSTANCE ;
266
+ loggerByMessageFactoryByName
267
+ .computeIfAbsent (name , this ::createLoggerRefByMessageFactoryMap )
268
+ .putIfAbsent (effectiveMessageFactory , logger );
344
269
} finally {
345
270
writeLock .unlock ();
346
271
}
347
272
}
348
273
349
- private Map <MessageFactory , WeakReference < T > > createLoggerRefByMessageFactoryMap (final String ignored ) {
274
+ private Map <MessageFactory , T > createLoggerRefByMessageFactoryMap (final String ignored ) {
350
275
return new WeakHashMap <>();
351
276
}
352
277
}
0 commit comments