From 4e917ac7b0199650f6d555e697c736abc48e7fab Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 12 Jun 2026 19:31:53 +0100 Subject: [PATCH 1/2] use root locale when doing case insensitive checks --- .../org/apache/xmlbeans/SchemaProperty.java | 2 +- .../org/apache/xmlbeans/SchemaTypeSystem.java | 2 +- .../xmlbeans/XmlDocumentProperties.java | 4 +- .../xmlbeans/impl/schema/StscState.java | 8 ++-- .../xmlbeans/impl/soap/MimeHeaders.java | 20 +++++---- .../org/apache/xmlbeans/impl/soap/Node.java | 2 +- .../apache/xmlbeans/impl/soap/SOAPHeader.java | 2 +- .../apache/xmlbeans/impl/store/CharUtil.java | 2 +- .../apache/xmlbeans/impl/store/DomImpl.java | 8 ++-- .../apache/xmlbeans/impl/store/Locale.java | 3 +- .../org/apache/xmlbeans/impl/store/Xobj.java | 2 +- .../apache/xmlbeans/impl/tool/XMLBean.java | 2 +- .../apache/xmlbeans/impl/util/MathUtil.java | 19 +-------- .../apache/xmlbeans/impl/util/StringUtil.java | 41 +++++++++++++++++++ .../xmlbeans/impl/util/TestStringUtil.java | 38 +++++++++++++++++ .../level2/core/attrgetownerelement01.java | 2 +- test/docs/BuildingAndRunningTests.txt | 2 +- 17 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 src/main/java/org/apache/xmlbeans/impl/util/StringUtil.java create mode 100644 src/test/java/org/apache/xmlbeans/impl/util/TestStringUtil.java diff --git a/src/main/java/org/apache/xmlbeans/SchemaProperty.java b/src/main/java/org/apache/xmlbeans/SchemaProperty.java index 23f0878f0..c6f4adc63 100644 --- a/src/main/java/org/apache/xmlbeans/SchemaProperty.java +++ b/src/main/java/org/apache/xmlbeans/SchemaProperty.java @@ -27,7 +27,7 @@ * can only be defined once, so each attribute obviously is a coherent * group on its own. *

- * A SchemaProperty represents a summary of the the elements with a + * A SchemaProperty represents a summary of the elements with a * given name or the attribute with a given name. It represents the * summary cardinality of the fields, the summary default and fixed * values, and so on. When inferring information about an element diff --git a/src/main/java/org/apache/xmlbeans/SchemaTypeSystem.java b/src/main/java/org/apache/xmlbeans/SchemaTypeSystem.java index 58337f73a..4e1f26e54 100644 --- a/src/main/java/org/apache/xmlbeans/SchemaTypeSystem.java +++ b/src/main/java/org/apache/xmlbeans/SchemaTypeSystem.java @@ -31,7 +31,7 @@ *

* Since every component is defined in a single SchemaTypeSystem, no * SchemaTypeSystem other than {@link XmlBeans#getBuiltinTypeSystem()} - * includes any of the the built-in types. That means + * includes any of the built-in types. That means * you cannot ordinarily load instances using a single * SchemaTypeSystem by itself. Instead, you will want to combine a path of * SchemaTypeSystems together using {@link XmlBeans#typeLoaderUnion} diff --git a/src/main/java/org/apache/xmlbeans/XmlDocumentProperties.java b/src/main/java/org/apache/xmlbeans/XmlDocumentProperties.java index c94e73460..c6e0267db 100644 --- a/src/main/java/org/apache/xmlbeans/XmlDocumentProperties.java +++ b/src/main/java/org/apache/xmlbeans/XmlDocumentProperties.java @@ -15,6 +15,8 @@ package org.apache.xmlbeans; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; + /** * This class is used to attach arbitrary information to an XML * document. It also defines several well-known types of @@ -81,7 +83,7 @@ public abstract class XmlDocumentProperties */ public boolean getStandalone ( ) { Object flag = get( STANDALONE ); - return flag != null && flag.toString().equalsIgnoreCase("true"); + return flag != null && equalsIgnoreCase(flag.toString(), "true"); } /** diff --git a/src/main/java/org/apache/xmlbeans/impl/schema/StscState.java b/src/main/java/org/apache/xmlbeans/impl/schema/StscState.java index eb9ad1003..0651646e1 100644 --- a/src/main/java/org/apache/xmlbeans/impl/schema/StscState.java +++ b/src/main/java/org/apache/xmlbeans/impl/schema/StscState.java @@ -33,6 +33,8 @@ import java.util.*; import java.util.function.Consumer; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; + /** * This class represents the state of the SchemaTypeSystemCompiler as it's * going. @@ -428,14 +430,14 @@ public boolean shouldDownloadURI(String uriString) { try { URI uri = new URI(uriString); - if (uri.getScheme().equalsIgnoreCase("jar") || - uri.getScheme().equalsIgnoreCase("zip")) { + if (equalsIgnoreCase(uri.getScheme(), "jar") || + equalsIgnoreCase(uri.getScheme(), "zip")) { // It may be local or not, depending on the embedded URI String s = uri.getSchemeSpecificPart(); int i = s.lastIndexOf('!'); return shouldDownloadURI(i > 0 ? s.substring(0, i) : s); } - return uri.getScheme().equalsIgnoreCase("file"); + return equalsIgnoreCase(uri.getScheme(), "file"); } catch (Exception e) { return false; } diff --git a/src/main/java/org/apache/xmlbeans/impl/soap/MimeHeaders.java b/src/main/java/org/apache/xmlbeans/impl/soap/MimeHeaders.java index b252b79ea..fc9826cc7 100644 --- a/src/main/java/org/apache/xmlbeans/impl/soap/MimeHeaders.java +++ b/src/main/java/org/apache/xmlbeans/impl/soap/MimeHeaders.java @@ -18,6 +18,8 @@ import java.util.Iterator; import java.util.Vector; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; + /** * A container for {@code MimeHeader} objects, which * represent the MIME headers present in a MIME part of a @@ -48,7 +50,7 @@ private MimeHeader nextMatch() { } for (String name : names) { - if (!mimeheader.getName().equalsIgnoreCase(name)) { + if (!equalsIgnoreCase(mimeheader.getName(), name)) { continue; } @@ -133,13 +135,13 @@ public MimeHeaders() { */ public String[] getHeader(String name) { - Vector vector = new Vector<>(); + Vector vector = new Vector<>(); for (int i = 0; i < headers.size(); i++) { MimeHeader mimeheader = headers.elementAt(i); - if (mimeheader.getName().equalsIgnoreCase(name) - && (mimeheader.getValue() != null)) { + if (equalsIgnoreCase(mimeheader.getName(), name) + && mimeheader.getValue() != null) { vector.addElement(mimeheader.getValue()); } } @@ -184,7 +186,7 @@ public void setHeader(String name, String value) { for (int i = 0; i < headers.size(); i++) { MimeHeader mimeheader = headers.elementAt(i); - if (mimeheader.getName().equalsIgnoreCase(name)) { + if (equalsIgnoreCase(mimeheader.getName(), name)) { if (!flag) { headers.setElementAt(new MimeHeader(mimeheader .getName(), value), i); @@ -228,7 +230,7 @@ public void addHeader(String name, String value) { for (int j = i - 1; j >= 0; j--) { MimeHeader mimeheader = headers.elementAt(j); - if (mimeheader.getName().equalsIgnoreCase(name)) { + if (equalsIgnoreCase(mimeheader.getName(), name)) { headers.insertElementAt(new MimeHeader(name, value), j + 1); return; @@ -240,16 +242,16 @@ public void addHeader(String name, String value) { /** * Remove all {@code MimeHeader} objects whose name - * matches the the given name. + * matches the given name. * @param name a {@code String} with the * name of the header for which to search */ public void removeHeader(String name) { for (int i = 0; i < headers.size(); i++) { - MimeHeader mimeheader = (MimeHeader) headers.elementAt(i); + MimeHeader mimeheader = headers.elementAt(i); - if (mimeheader.getName().equalsIgnoreCase(name)) { + if (equalsIgnoreCase(mimeheader.getName(), name)) { headers.removeElementAt(i--); } } diff --git a/src/main/java/org/apache/xmlbeans/impl/soap/Node.java b/src/main/java/org/apache/xmlbeans/impl/soap/Node.java index 31510478e..96693b8ea 100644 --- a/src/main/java/org/apache/xmlbeans/impl/soap/Node.java +++ b/src/main/java/org/apache/xmlbeans/impl/soap/Node.java @@ -24,7 +24,7 @@ public interface Node extends org.w3c.dom.Node { /** - * Returns the the value of the immediate child of this {@code Node} + * Returns the value of the immediate child of this {@code Node} * object if a child exists and its value is text. * @return a {@code String} with the text of the immediate child of * this {@code Node} object if (1) there is a child and diff --git a/src/main/java/org/apache/xmlbeans/impl/soap/SOAPHeader.java b/src/main/java/org/apache/xmlbeans/impl/soap/SOAPHeader.java index 299ca0a01..3e4e676d3 100644 --- a/src/main/java/org/apache/xmlbeans/impl/soap/SOAPHeader.java +++ b/src/main/java/org/apache/xmlbeans/impl/soap/SOAPHeader.java @@ -95,7 +95,7 @@ SOAPHeaderElement addHeaderElement(Name name) /** * Returns a list of all the {@code SOAPHeaderElement} * objects in this {@code SOAPHeader} object that have - * the the specified actor and detaches them from this {@code + * the specified actor and detaches them from this {@code * SOAPHeader} object. * *

This method allows an actor to process only the parts of diff --git a/src/main/java/org/apache/xmlbeans/impl/store/CharUtil.java b/src/main/java/org/apache/xmlbeans/impl/store/CharUtil.java index e2581880e..cfdb5d3ee 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/CharUtil.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/CharUtil.java @@ -455,7 +455,7 @@ public Object saveChars( int cchMore = cchSave - cchAlloc; if (cchMore > 0) { - // If we're here the the buffer got consumed. So, this time it must allocate a new + // If we're here the buffer got consumed. So, this time it must allocate a new // buffer capable of containing all of the remaining text (no matter how large) and // return the beginning part of it. diff --git a/src/main/java/org/apache/xmlbeans/impl/store/DomImpl.java b/src/main/java/org/apache/xmlbeans/impl/store/DomImpl.java index 74ac69656..e8536e76a 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/DomImpl.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/DomImpl.java @@ -34,6 +34,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; + // DOM Level 3 public final class DomImpl { @@ -598,16 +600,16 @@ public static boolean _domImplementation_hasFeature(Locale l, String feature, St return false; } - if (version != null && version.length() > 0 && + if (version != null && !version.isEmpty() && !version.equals("1.0") && !version.equals("2.0")) { return false; } - if (feature.equalsIgnoreCase("core")) { + if (equalsIgnoreCase(feature, "core")) { return true; } - return feature.equalsIgnoreCase("xml"); + return equalsIgnoreCase(feature, "xml"); } ////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Locale.java b/src/main/java/org/apache/xmlbeans/impl/store/Locale.java index ac61ac2e7..ddb18b7ec 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Locale.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Locale.java @@ -48,6 +48,7 @@ import java.util.Map; import java.util.Objects; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; import static org.apache.xmlbeans.impl.values.TypeStore.*; @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") @@ -2183,7 +2184,7 @@ protected boolean isAttrOfTypeId(QName aqn, QName eqn) { // as most documents are either without schema or based on xml schema // which ID attributes aren't promoted by the SAXParser, the workaround // is to simply accept all "id" attributes - return "id".equalsIgnoreCase(aqn.getLocalPart()); + return equalsIgnoreCase("id", aqn.getLocalPart()); } String pre = aqn.getPrefix(); String lName = aqn.getLocalPart(); diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java b/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java index 55391fe7d..4a58e19a7 100644 --- a/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Xobj.java @@ -1382,7 +1382,7 @@ void disconnectChildrenUsers() { * with a return value of null, which indicates an illegal * state, where there is no mapping for the given prefix. *

- * If the the default namespace is not explicitly mapped in the xml, + * If the default namespace is not explicitly mapped in the xml, * the xml spec says that it should be mapped to the no-namespace. * When the 'defaultAlwaysMapped' parameter is true, the default namepsace * will return the no-namespace even if it is not explicity diff --git a/src/main/java/org/apache/xmlbeans/impl/tool/XMLBean.java b/src/main/java/org/apache/xmlbeans/impl/tool/XMLBean.java index 600f63cf6..6584a46ea 100644 --- a/src/main/java/org/apache/xmlbeans/impl/tool/XMLBean.java +++ b/src/main/java/org/apache/xmlbeans/impl/tool/XMLBean.java @@ -545,7 +545,7 @@ public void setFork(boolean f) { } /** - * Sets the the name of the javac executable. + * Sets the name of the javac executable. * *

Ignored unless fork is true or extJavac has been specified * as the compiler.

diff --git a/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java b/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java index d2240fd16..76776fe00 100644 --- a/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java +++ b/src/main/java/org/apache/xmlbeans/impl/util/MathUtil.java @@ -1,20 +1,3 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -34,7 +17,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more package org.apache.xmlbeans.impl.util; /** - * Utility methods for dealing with conversions + * Internal Use Only. Utility methods for dealing with conversions */ public class MathUtil { private MathUtil() {} diff --git a/src/main/java/org/apache/xmlbeans/impl/util/StringUtil.java b/src/main/java/org/apache/xmlbeans/impl/util/StringUtil.java new file mode 100644 index 000000000..faf9be5c0 --- /dev/null +++ b/src/main/java/org/apache/xmlbeans/impl/util/StringUtil.java @@ -0,0 +1,41 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.xmlbeans.impl.util; + +import java.util.Locale; + +/** + * Internal Use Only. + * @since 5.4.0 + */ +public class StringUtil { + private StringUtil() {} + + /** + * Uses Locale.ROOT. Does null safe checks. + */ + public static boolean equalsIgnoreCase(String s1, String s2) { + if (s1 == null) { + return s2 == null; + } else if (s2 == null) { + return false; + } else if (s1.length() != s2.length()) { + return false; + } + return s1.toLowerCase(Locale.ROOT).equals(s2.toLowerCase(Locale.ROOT)); + } +} diff --git a/src/test/java/org/apache/xmlbeans/impl/util/TestStringUtil.java b/src/test/java/org/apache/xmlbeans/impl/util/TestStringUtil.java new file mode 100644 index 000000000..36b79c943 --- /dev/null +++ b/src/test/java/org/apache/xmlbeans/impl/util/TestStringUtil.java @@ -0,0 +1,38 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.xmlbeans.impl.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class TestStringUtil { + @Test + void equalsIgnoreCase() { + assertTrue(StringUtil.equalsIgnoreCase(null, null), "2 nulls are equal"); + assertFalse(StringUtil.equalsIgnoreCase(null, ""), "null and empty strings are not equal"); + assertFalse(StringUtil.equalsIgnoreCase("", null), "null and empty strings are not equal"); + assertFalse(StringUtil.equalsIgnoreCase("abc", "abcd"), "different lengths do not match"); + assertFalse(StringUtil.equalsIgnoreCase("abcd", "abc"), "different lengths do not match"); + assertTrue(StringUtil.equalsIgnoreCase("abc", "abc"), "abc and abc match"); + assertTrue(StringUtil.equalsIgnoreCase("abc", "Abc"), "abc and Abc match"); + assertFalse(StringUtil.equalsIgnoreCase("İ", "i"), "Turkish dotted İ and i do not match (root locale)"); + assertFalse(StringUtil.equalsIgnoreCase("İ", "I"), "Turkish dotted İ and I do not match (root locale)"); + assertFalse(StringUtil.equalsIgnoreCase("ı", "I"), "Turkish dotless ı and I do not match (root locale)"); + } +} diff --git a/src/test/java/org/w3c/domts/level2/core/attrgetownerelement01.java b/src/test/java/org/w3c/domts/level2/core/attrgetownerelement01.java index e6ba4980c..d62063ab6 100644 --- a/src/test/java/org/w3c/domts/level2/core/attrgetownerelement01.java +++ b/src/test/java/org/w3c/domts/level2/core/attrgetownerelement01.java @@ -33,7 +33,7 @@ /** * The "getOwnerElement()" will return the Element node this attribute is attached to or * null if this attribute is not in use. - * Retreive the default attribute defaultAttr and check its owner element. Verify if the name + * Retrieve the default attribute defaultAttr and check its owner element. Verify if the name * the nodeName of the returned ownerElement is emp:employee. * * @see http://www.w3.org/TR/DOM-Level-2-Core/core#Attr-ownerElement diff --git a/test/docs/BuildingAndRunningTests.txt b/test/docs/BuildingAndRunningTests.txt index 2b60d8b13..5c76c81b7 100755 --- a/test/docs/BuildingAndRunningTests.txt +++ b/test/docs/BuildingAndRunningTests.txt @@ -6,7 +6,7 @@ Requirements: * Ensure JAVA_HOME and ANT_HOME (Requires Ant 1.6 or higher) are set up in your environment -BUILING AND RUNNING CHECKIN TESTS: +BUILDING AND RUNNING CHECKIN TESTS: (NOTE: does not perform a checkin, just runs tests) It is recommended that you call at least clean.tests before a checkintest run. From ddb9b074816c2a01262666e5b6dadcb5ec7e1e70 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 12 Jun 2026 19:36:37 +0100 Subject: [PATCH 2/2] Update NameUtil.java --- src/main/java/org/apache/xmlbeans/impl/common/NameUtil.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/xmlbeans/impl/common/NameUtil.java b/src/main/java/org/apache/xmlbeans/impl/common/NameUtil.java index 4abb73361..57547a2ec 100644 --- a/src/main/java/org/apache/xmlbeans/impl/common/NameUtil.java +++ b/src/main/java/org/apache/xmlbeans/impl/common/NameUtil.java @@ -18,6 +18,8 @@ import javax.xml.namespace.QName; import java.util.*; +import static org.apache.xmlbeans.impl.util.StringUtil.equalsIgnoreCase; + public class NameUtil { // punctuation characters public final static char HYPHEN = '\u002D'; @@ -436,7 +438,7 @@ private static List splitDNS(String dns) { // JAXB draft example implies removal of www if (result.size() >= 3 && - result.get(result.size() - 1).toLowerCase(Locale.ROOT).equals("www")) { + equalsIgnoreCase(result.get(result.size() - 1), "www")) { result.remove(result.size() - 1); } @@ -450,7 +452,7 @@ private static String processFilename(String filename) { if (i > 0 && ( i + 1 + 2 == filename.length() || i + 1 + 3 == filename.length() || - "html".equals(filename.substring(i + 1).toLowerCase(Locale.ROOT)))) { + equalsIgnoreCase("html", filename.substring(i + 1)))) { return filename.substring(0, i); }