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 ;
33- import java .util .function .BiFunction ;
3431import org .apache .logging .log4j .message .MessageFactory ;
3532import org .apache .logging .log4j .message .ParameterizedMessageFactory ;
36- import org .apache .logging .log4j .status .StatusLogger ;
3733import org .jspecify .annotations .NullMarked ;
3834import org .jspecify .annotations .Nullable ;
3935
4339@ NullMarked
4440public class LoggerRegistry <T extends ExtendedLogger > {
4541
46- private final Map <String , Map <MessageFactory , WeakReference < T >>> loggerRefByMessageFactoryByName = new HashMap <>();
42+ private final Map <String , Map <MessageFactory , T >> loggerByMessageFactoryByName = new HashMap <>();
4743
4844 private final ReadWriteLock lock = new ReentrantReadWriteLock ();
4945
@@ -143,7 +139,7 @@ public LoggerRegistry(@Nullable final MapFactory<T> mapFactory) {
143139 * Use {@link #getLogger(String, MessageFactory)} instead.
144140 */
145141 @ Deprecated
146- public T getLogger (final String name ) {
142+ public @ Nullable T getLogger (final String name ) {
147143 requireNonNull (name , "name" );
148144 return getLogger (name , null );
149145 }
@@ -160,39 +156,29 @@ public T getLogger(final String name) {
160156 * @param messageFactory a message factory
161157 * @return the logger associated with the given name and message factory
162158 */
163- public T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
159+ public @ Nullable T getLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
164160 requireNonNull (name , "name" );
165161 readLock .lock ();
166162 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 );
172164 final MessageFactory effectiveMessageFactory =
173165 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 );
179167 } finally {
180168 readLock .unlock ();
181169 }
182170 }
183171
184172 public Collection <T > getLoggers () {
185- return getLoggers (new ArrayList <T >());
173+ return getLoggers (new ArrayList <>());
186174 }
187175
188176 public Collection <T > getLoggers (final Collection <T > destination ) {
189177 requireNonNull (destination , "destination" );
190178 readLock .lock ();
191179 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 ())
196182 .forEach (destination ::add );
197183 } finally {
198184 readLock .unlock ();
@@ -215,7 +201,7 @@ public Collection<T> getLoggers(final Collection<T> destination) {
215201 @ Deprecated
216202 public boolean hasLogger (final String name ) {
217203 requireNonNull (name , "name" );
218- final T logger = getLogger (name );
204+ final @ Nullable T logger = getLogger (name );
219205 return logger != null ;
220206 }
221207
@@ -234,7 +220,7 @@ public boolean hasLogger(final String name) {
234220 */
235221 public boolean hasLogger (final String name , @ Nullable final MessageFactory messageFactory ) {
236222 requireNonNull (name , "name" );
237- final T logger = getLogger (name , messageFactory );
223+ final @ Nullable T logger = getLogger (name , messageFactory );
238224 return logger != null ;
239225 }
240226
@@ -251,7 +237,7 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
251237 requireNonNull (messageFactoryClass , "messageFactoryClass" );
252238 readLock .lock ();
253239 try {
254- return loggerRefByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
240+ return loggerByMessageFactoryByName .getOrDefault (name , Collections .emptyMap ()).keySet ().stream ()
255241 .anyMatch (messageFactory -> messageFactoryClass .equals (messageFactory .getClass ()));
256242 } finally {
257243 readLock .unlock ();
@@ -262,91 +248,30 @@ public boolean hasLogger(final String name, final Class<? extends MessageFactory
262248 * Registers the provided logger.
263249 * <b>Logger name and message factory parameters are ignored</b>, those will be obtained from the logger instead.
264250 *
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
267253 * @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.
270254 */
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 ) {
274256
275257 // Check arguments
258+ requireNonNull (name , "name" );
276259 requireNonNull (logger , "logger" );
277260
278261 // Insert the logger
279262 writeLock .lock ();
280263 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 );
344269 } finally {
345270 writeLock .unlock ();
346271 }
347272 }
348273
349- private Map <MessageFactory , WeakReference < T > > createLoggerRefByMessageFactoryMap (final String ignored ) {
274+ private Map <MessageFactory , T > createLoggerRefByMessageFactoryMap (final String ignored ) {
350275 return new WeakHashMap <>();
351276 }
352277}
0 commit comments