diff --git a/release-notes/CREDITS b/release-notes/CREDITS index d60e231e..fcc836c5 100644 --- a/release-notes/CREDITS +++ b/release-notes/CREDITS @@ -152,3 +152,7 @@ Christian Beikov (@beikov) * Reported #871: `XmlMapper` regression in 3.2.0: `xsi:nil` collection element on unwrapped collection wrongly read as null collection (3.3.0) + +@Sahana2524 + * Fixed #879: Use `Locale.ROOT` for case folding in `CaseInsensitiveNameSet` + (3.3.0) diff --git a/release-notes/VERSION b/release-notes/VERSION index 5a0a8fdf..fc1abdf0 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -9,6 +9,8 @@ Version: 3.x (for earlier see VERSION-2.x) #873: Fix handling of `@JsonApplyView` (fix by @cowtowncoder, w/ Claude code) +#879: Use `Locale.ROOT` for case folding in `CaseInsensitiveNameSet` + (fix by @Sahana2524) 3.2.1 (10-Jul-2026) diff --git a/src/main/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSet.java b/src/main/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSet.java index 5e4329ff..deaf0494 100644 --- a/src/main/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSet.java +++ b/src/main/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSet.java @@ -19,7 +19,7 @@ private CaseInsensitiveNameSet(Set namesToMatch) { public static CaseInsensitiveNameSet construct(Set names0) { Set namesToMatch = new HashSet(names0); for (String name : names0) { - namesToMatch.add(name.toLowerCase()); + namesToMatch.add(name.toLowerCase(Locale.ROOT)); } return new CaseInsensitiveNameSet(namesToMatch); } @@ -30,7 +30,7 @@ public boolean contains(Object key0) { if (_namesToMatch.contains(key)) { return true; } - final String lc = key.toLowerCase(); + final String lc = key.toLowerCase(Locale.ROOT); return (lc != key) && _namesToMatch.contains(lc); } diff --git a/src/test/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSetTest.java b/src/test/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSetTest.java new file mode 100644 index 00000000..0287d1fa --- /dev/null +++ b/src/test/java/tools/jackson/dataformat/xml/util/CaseInsensitiveNameSetTest.java @@ -0,0 +1,42 @@ +package tools.jackson.dataformat.xml.util; + +import java.util.Collections; +import java.util.Locale; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.ResourceLock; +import org.junit.jupiter.api.parallel.Resources; + +import tools.jackson.dataformat.xml.XmlTestUtil; + +import static org.junit.jupiter.api.Assertions.*; + +public class CaseInsensitiveNameSetTest extends XmlTestUtil +{ + // Names with 'I'/'i' fold differently under the Turkish locale + // ("I".toLowerCase() -> dotless "ı"), so a set built with the default + // locale would stop matching them. Matching should not depend on the JVM's + // default locale. + @Test + // Mutates JVM-wide default Locale: needs exclusive access in case tests + // are ever run in parallel + @ResourceLock(Resources.LOCALE) + public void testMatchingIndependentOfDefaultLocale() + { + final Locale orig = Locale.getDefault(); + try { + Locale.setDefault(Locale.forLanguageTag("tr")); + + CaseInsensitiveNameSet set = CaseInsensitiveNameSet.construct( + Collections.singleton("ITEM")); + assertTrue(set.contains("item"), + "case-insensitive match of 'item' against 'ITEM' should hold under any locale"); + + set = CaseInsensitiveNameSet.construct(Collections.singleton("title")); + assertTrue(set.contains("TITLE"), + "case-insensitive match of 'TITLE' against 'title' should hold under any locale"); + } finally { + Locale.setDefault(orig); + } + } +}