Add the JAXP static factory methods to the hardened factory classes - #57
Merged
Conversation
Member
Author
|
This PR includes the same changes to the Animal Sniffer plugin that apache/commons-parent#719. I included it here, so we can run the checks without making a new parent release. If other problems arise before |
Base automatically changed from
feature/merge-hardeners-into-factories
to
main
August 28, 2026 10:51
Mirror on each Hardening*Factory the static factory methods its JAXP counterpart offers in JDK 8, omitting only the deprecated XMLInputFactory.newInstance(String, ClassLoader): the explicit factoryClassName/ClassLoader overloads, the SchemaFactory and XPathFactory language/object-model variants, and the StAX newFactory family. Each is a one-liner through the class's hardening recipe. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWJ4LAxx3TX5RwNvwKbAS3
Each factory class gains newDefaultInstance (newDefaultFactory for StAX) without raising the compile baseline: the Java 9 JAXP method is resolved through MethodHandles.publicLookup() and invoked when present; on Java 8 the JDK's built-in implementation is instantiated by class name instead. Where the platform provides neither, for example Android, the lookup miss surfaces as the factory's own configuration error, like any newInstance miss. java.lang.invoke raises the supported Android baseline to API level 26, and the bnd instructions drop the JDK-internal package inferred from the reflective StAX fallback. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWJ4LAxx3TX5RwNvwKbAS3
DocumentBuilderFactory and SAXParserFactory gain the newNSInstance, newNSInstance(String, ClassLoader) and newDefaultNSInstance mirrors, resolved through MethodHandles.publicLookup() like the Java 9 methods. Where the platform predates them, the fallback enables namespace awareness on the corresponding newInstance lookup, the behavior the JAXP methods are specified to have, so the non-default variants work on every supported platform including Android; newDefaultNSInstance inherits the newDefaultInstance fallback chain. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWJ4LAxx3TX5RwNvwKbAS3
The JDK implements the newNSInstance family by enabling namespace awareness on the result of the plain lookup; do the same with a private makeNSAware helper instead of resolving the platform methods through MethodHandles, and route the internal namespace-aware parser construction in newHardenedReader, hardenSourceToDom and HardeningXPath.parse through the public newNSInstance() methods. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErRKq7RUeQ9LGrSboSUyYm
…niffer javac records the ad-hoc call-site descriptor for invokeExact, which no signature database lists, so the JDK 8 check flags a false positive on every MethodHandle lookup call site. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErRKq7RUeQ9LGrSboSUyYm
Describe on the site and in the package Javadoc the static factory methods mirrored from JAXP (the JDK 8 overloads, Java 9 newDefaultInstance and Java 13 newNSInstance families), all usable on Java 8, with newDefaultInstance as an opt-out of JAXP pluggability. Assisted-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErRKq7RUeQ9LGrSboSUyYm
garydgregory
force-pushed
the
feature/jaxp-factory-methods
branch
from
August 28, 2026 10:51
64c1c91 to
a45add7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
Stacked on #56.
Mirror on each
Hardening*Factorythe static factory methods its JAXP counterpart offers, so the hardened classes are a drop-in replacement at every construction site:factoryClassName/ClassLoaderoverloads, theSchemaFactoryandXPathFactorylanguage/object-model variants, and the StAXnewFactoryfamily (omitting only the deprecatedXMLInputFactory.newInstance(String, ClassLoader)).newDefaultInstance(): resolved through aMethodHandleat runtime, falling back to instantiating the JDK's built-in implementation by class name on Java 8. This way we backport thenewDefaultInstance()to Java 8. Calling the new methods on Java 9+ is necessary, because the classes are not exported through JPMS.newNSInstance()family: implemented the way the JDK does — namespace awareness enabled on the non-NS counterpart through a privatemakeNSAwarehelper. Calling the Java 13 methods directly is not necessary: they are mere decorators.The internal namespace-aware parser construction (
newHardenedReader,hardenSourceToDom,HardeningXPath.parse) now reusesnewNSInstance()instead of hand-rolling the same recipe.I bumped the Android requirement to API 26 (2017), since previous versions don't handle
MethodHandle.invokeExact().🤖 Generated with Claude Code