3939import java .util .concurrent .locks .Lock ;
4040import java .util .concurrent .locks .ReadWriteLock ;
4141import java .util .concurrent .locks .ReentrantReadWriteLock ;
42+ import java .util .regex .Pattern ;
4243import org .apache .logging .log4j .Level ;
4344import org .apache .logging .log4j .Marker ;
4445import org .apache .logging .log4j .message .Message ;
@@ -209,6 +210,44 @@ public class StatusLogger extends AbstractLogger {
209210 */
210211 public static final String PROPERTIES_FILE_NAME = "log4j2.StatusLogger.properties" ;
211212
213+ /**
214+ * Pattern that matches common separators in property names:
215+ * <ul>
216+ * <li>Dots ({@code .}) used in property paths</li>
217+ * <li>Dashes ({@code -}) used in kebab-case</li>
218+ * <li>Underscores ({@code _}) used in environment variables</li>
219+ * </ul>
220+ * <p>
221+ * These are removed during normalization.
222+ * </p>
223+ */
224+ private static final Pattern SEPARATORS = Pattern .compile ("[._-]" );
225+
226+ /**
227+ * Pattern that matches any character not in the ASCII Basic Latin block.
228+ * <p>
229+ * These characters are replaced with dots during normalization to avoid mismatches
230+ * while preserving boundaries, e.g. {@code fooàö} becomes {@code foo..}.
231+ * </p>
232+ */
233+ private static final Pattern NON_ASCII = Pattern .compile ("\\ P{InBasic_Latin}" );
234+
235+ /**
236+ * Pattern that matches the {@code log4j2} prefix at the start of the property name.
237+ * <p>
238+ * This is replaced with {@code log4j} for internal normalization.
239+ * </p>
240+ */
241+ private static final Pattern PREFIX_LOG4J2 = Pattern .compile ("^log4j2" );
242+
243+ /**
244+ * Pattern that matches property names starting with {@code log4j}, case-insensitively.
245+ * <p>
246+ * Used to determine if a given property name is relevant for Log4j configuration.
247+ * </p>
248+ */
249+ private static final Pattern LOG4J_PREFIX = Pattern .compile ("^log4j.*" , Pattern .CASE_INSENSITIVE );
250+
212251 /**
213252 * Holder for user-provided {@link StatusLogger} configurations.
214253 *
@@ -462,7 +501,7 @@ private static Map<String, Object> normalizeProperties(Properties... propertiesL
462501 * @return {@code true}, if the property name is relevant; {@code false}, otherwise
463502 */
464503 private static boolean isRelevantPropertyName (@ Nullable final Object propertyName ) {
465- return propertyName instanceof String && ((String ) propertyName ).matches ("^(?i)log4j.*" );
504+ return propertyName instanceof String && LOG4J_PREFIX . matcher ((String ) propertyName ).matches ();
466505 }
467506
468507 /**
@@ -476,19 +515,17 @@ private static boolean isRelevantPropertyName(@Nullable final Object propertyNam
476515 * @return the normalized property name
477516 */
478517 private static String normalizePropertyName (final String propertyName ) {
479- return propertyName
480- // Remove separators:
481- // - dots (properties)
482- // - dashes (kebab-case)
483- // - underscores (environment variables)
484- .replaceAll ("[._-]" , "" )
485- // Replace all non-ASCII characters.
486- // Don't remove, otherwise `fooàö` would incorrectly match with `foo`.
487- // It is safe to replace them with dots, since we've just removed all dots above.
488- .replaceAll ("\\ P{InBasic_Latin}" , "." )
489- // Lowercase ASCII – this is safe, since we've just removed all non-ASCII
490- .toLowerCase (Locale .US )
491- .replaceAll ("^log4j2" , "log4j" );
518+ if (propertyName == null ) {
519+ return null ;
520+ }
521+
522+ String propertyNameInput = propertyName ;
523+ propertyNameInput = SEPARATORS .matcher (propertyNameInput ).replaceAll ("" );
524+ propertyNameInput = NON_ASCII .matcher (propertyNameInput ).replaceAll ("." );
525+ propertyNameInput = propertyNameInput .toLowerCase (Locale .US );
526+ propertyNameInput = PREFIX_LOG4J2 .matcher (propertyNameInput ).replaceFirst ("log4j" );
527+
528+ return propertyNameInput ;
492529 }
493530 }
494531
0 commit comments