This is an automated email from the ASF dual-hosted git repository. ppkarwasz pushed a commit to branch feature/jaxp-factory-methods in repository https://gitbox.apache.org/repos/asf/commons-xml.git
commit 032c62f635c37f93edddd10a46b39b79b5eeec8d Author: Piotr P. Karwasz <[email protected]> AuthorDate: Fri Aug 28 08:41:11 2026 +0200 Emulate the Java 13 NSInstance methods and reuse them internally 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 <[email protected]> Claude-Session: https://claude.ai/code/session_01ErRKq7RUeQ9LGrSboSUyYm --- .../xml/HardeningDocumentBuilderFactory.java | 88 +++++---------------- .../commons/xml/HardeningSAXParserFactory.java | 91 +++++----------------- .../commons/xml/HardeningTransformerFactory.java | 3 +- .../org/apache/commons/xml/HardeningXPath.java | 3 +- 4 files changed, 44 insertions(+), 141 deletions(-) diff --git a/src/main/java/org/apache/commons/xml/HardeningDocumentBuilderFactory.java b/src/main/java/org/apache/commons/xml/HardeningDocumentBuilderFactory.java index aee284c..1c16de6 100644 --- a/src/main/java/org/apache/commons/xml/HardeningDocumentBuilderFactory.java +++ b/src/main/java/org/apache/commons/xml/HardeningDocumentBuilderFactory.java @@ -56,13 +56,6 @@ public final class HardeningDocumentBuilderFactory { private static final MethodHandle NEW_DEFAULT_INSTANCE = findStatic("newDefaultInstance", MethodType.methodType(DocumentBuilderFactory.class)); - private static final MethodHandle NEW_DEFAULT_NS_INSTANCE = findStatic("newDefaultNSInstance", MethodType.methodType(DocumentBuilderFactory.class)); - - private static final MethodHandle NEW_NS_INSTANCE = findStatic("newNSInstance", MethodType.methodType(DocumentBuilderFactory.class)); - - private static final MethodHandle NEW_NS_INSTANCE_BY_CLASS_NAME = findStatic("newNSInstance", - MethodType.methodType(DocumentBuilderFactory.class, String.class, ClassLoader.class)); - private static MethodHandle findStatic(final String name, final MethodType type) { try { return MethodHandles.publicLookup().findStatic(DocumentBuilderFactory.class, name, type); @@ -104,6 +97,17 @@ static DocumentBuilderFactory harden(final DocumentBuilderFactory factory) { return new Wrapper(factory); } + /** + * Enables namespace awareness on the given factory; the {@code NSInstance} counterpart of each factory method routes its result through here. + * + * @param factory the factory to configure; never {@code null}. + * @return The given factory, namespace-aware. + */ + private static DocumentBuilderFactory makeNSAware(final DocumentBuilderFactory factory) { + factory.setNamespaceAware(true); + return factory; + } + /** * Returns a new, hardened {@link DocumentBuilderFactory} of the system-default implementation. * <p> @@ -135,11 +139,8 @@ public static DocumentBuilderFactory newDefaultInstance() { } /** - * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory} of the system-default implementation. - * <p> - * Obtained as by {@code DocumentBuilderFactory.newDefaultNSInstance()} where the platform provides it (Java 13 or later), and by enabling namespace - * awareness on {@link #newDefaultInstance()} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory} of the system-default implementation, enabling namespace awareness on + * {@link #newDefaultInstance()}, the behavior {@code DocumentBuilderFactory.newDefaultNSInstance()} (Java 13 or later) is specified to have. * * @return A hardened, namespace-aware factory. * @throws IllegalStateException Thrown if a required hardening setting cannot be applied to the underlying implementation. @@ -147,21 +148,7 @@ public static DocumentBuilderFactory newDefaultInstance() { * (for example Android). */ public static DocumentBuilderFactory newDefaultNSInstance() { - if (NEW_DEFAULT_NS_INSTANCE != null) { - final DocumentBuilderFactory factory; - try { - factory = (DocumentBuilderFactory) NEW_DEFAULT_NS_INSTANCE.invokeExact(); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final DocumentBuilderFactory factory = newDefaultInstance(); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newDefaultInstance()); } /** @@ -194,11 +181,8 @@ public static DocumentBuilderFactory newInstance(final String factoryClassName, } /** - * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory}. - * <p> - * Obtained as by {@code DocumentBuilderFactory.newNSInstance()} where the platform provides it (Java 13 or later), and by enabling namespace awareness on - * {@link #newInstance()} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory}, enabling namespace awareness on {@link #newInstance()}, the behavior + * {@code DocumentBuilderFactory.newNSInstance()} (Java 13 or later) is specified to have. * * @return A hardened, namespace-aware factory. * @throws IllegalStateException Thrown if a required hardening setting cannot be applied to the underlying implementation. @@ -206,29 +190,13 @@ public static DocumentBuilderFactory newInstance(final String factoryClassName, * implementation is not available or cannot be instantiated. */ public static DocumentBuilderFactory newNSInstance() { - if (NEW_NS_INSTANCE != null) { - final DocumentBuilderFactory factory; - try { - factory = (DocumentBuilderFactory) NEW_NS_INSTANCE.invokeExact(); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final DocumentBuilderFactory factory = newInstance(); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newInstance()); } /** - * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory} of the given implementation class. - * <p> - * Obtained as by {@code DocumentBuilderFactory.newNSInstance(String, ClassLoader)} where the platform provides it (Java 13 or later), and by enabling - * namespace awareness on {@link #newInstance(String, ClassLoader)} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link DocumentBuilderFactory} of the given implementation class, enabling namespace awareness on + * {@link #newInstance(String, ClassLoader)}, the behavior {@code DocumentBuilderFactory.newNSInstance(String, ClassLoader)} (Java 13 or later) is specified + * to have. * * @param factoryClassName The fully qualified class name of the {@link DocumentBuilderFactory} implementation. * @param classLoader The class loader used to load the factory class; {@code null} means the current thread's context class loader. @@ -237,21 +205,7 @@ public static DocumentBuilderFactory newNSInstance() { * @throws FactoryConfigurationError Thrown if {@code factoryClassName} is {@code null} or the factory class cannot be loaded or instantiated. */ public static DocumentBuilderFactory newNSInstance(final String factoryClassName, final ClassLoader classLoader) { - if (NEW_NS_INSTANCE_BY_CLASS_NAME != null) { - final DocumentBuilderFactory factory; - try { - factory = (DocumentBuilderFactory) NEW_NS_INSTANCE_BY_CLASS_NAME.invokeExact(factoryClassName, classLoader); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final DocumentBuilderFactory factory = newInstance(factoryClassName, classLoader); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newInstance(factoryClassName, classLoader)); } /** diff --git a/src/main/java/org/apache/commons/xml/HardeningSAXParserFactory.java b/src/main/java/org/apache/commons/xml/HardeningSAXParserFactory.java index 36d4585..9101acd 100644 --- a/src/main/java/org/apache/commons/xml/HardeningSAXParserFactory.java +++ b/src/main/java/org/apache/commons/xml/HardeningSAXParserFactory.java @@ -66,13 +66,6 @@ public final class HardeningSAXParserFactory { private static final MethodHandle NEW_DEFAULT_INSTANCE = findStatic("newDefaultInstance", MethodType.methodType(SAXParserFactory.class)); - private static final MethodHandle NEW_DEFAULT_NS_INSTANCE = findStatic("newDefaultNSInstance", MethodType.methodType(SAXParserFactory.class)); - - private static final MethodHandle NEW_NS_INSTANCE = findStatic("newNSInstance", MethodType.methodType(SAXParserFactory.class)); - - private static final MethodHandle NEW_NS_INSTANCE_BY_CLASS_NAME = findStatic("newNSInstance", - MethodType.methodType(SAXParserFactory.class, String.class, ClassLoader.class)); - private static MethodHandle findStatic(final String name, final MethodType type) { try { return MethodHandles.publicLookup().findStatic(SAXParserFactory.class, name, type); @@ -161,6 +154,17 @@ static XMLReader harden(final XMLReader reader) { return new HardeningXMLReader(reader); } + /** + * Enables namespace awareness on the given factory; the {@code NSInstance} counterpart of each factory method routes its result through here. + * + * @param factory the factory to configure; never {@code null}. + * @return The given factory, namespace-aware. + */ + private static SAXParserFactory makeNSAware(final SAXParserFactory factory) { + factory.setNamespaceAware(true); + return factory; + } + /** * Returns a new, hardened {@link SAXParserFactory} of the system-default implementation. * <p> @@ -192,11 +196,8 @@ public static SAXParserFactory newDefaultInstance() { } /** - * Returns a new, hardened, namespace-aware {@link SAXParserFactory} of the system-default implementation. - * <p> - * Obtained as by {@code SAXParserFactory.newDefaultNSInstance()} where the platform provides it (Java 13 or later), and by enabling namespace awareness on - * {@link #newDefaultInstance()} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link SAXParserFactory} of the system-default implementation, enabling namespace awareness on + * {@link #newDefaultInstance()}, the behavior {@code SAXParserFactory.newDefaultNSInstance()} (Java 13 or later) is specified to have. * * @return A hardened, namespace-aware factory. * @throws IllegalStateException Thrown if a required hardening setting cannot be applied to the underlying implementation. @@ -204,21 +205,7 @@ public static SAXParserFactory newDefaultInstance() { * (for example Android). */ public static SAXParserFactory newDefaultNSInstance() { - if (NEW_DEFAULT_NS_INSTANCE != null) { - final SAXParserFactory factory; - try { - factory = (SAXParserFactory) NEW_DEFAULT_NS_INSTANCE.invokeExact(); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final SAXParserFactory factory = newDefaultInstance(); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newDefaultInstance()); } /** @@ -231,9 +218,7 @@ public static SAXParserFactory newDefaultNSInstance() { */ static XMLReader newHardenedReader() throws TransformerConfigurationException { try { - final SAXParserFactory factory = harden(SAXParserFactory.newInstance()); - factory.setNamespaceAware(true); - return factory.newSAXParser().getXMLReader(); + return newNSInstance().newSAXParser().getXMLReader(); } catch (final ParserConfigurationException | SAXException e) { throw new TransformerConfigurationException("Failed to obtain a hardened XMLReader for source parsing", e); } @@ -265,11 +250,8 @@ public static SAXParserFactory newInstance(final String factoryClassName, final } /** - * Returns a new, hardened, namespace-aware {@link SAXParserFactory}. - * <p> - * Obtained as by {@code SAXParserFactory.newNSInstance()} where the platform provides it (Java 13 or later), and by enabling namespace awareness on - * {@link #newInstance()} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link SAXParserFactory}, enabling namespace awareness on {@link #newInstance()}, the behavior + * {@code SAXParserFactory.newNSInstance()} (Java 13 or later) is specified to have. * * @return A hardened, namespace-aware factory. * @throws IllegalStateException Thrown if a required hardening setting cannot be applied to the underlying implementation. @@ -277,29 +259,12 @@ public static SAXParserFactory newInstance(final String factoryClassName, final * error} or if the implementation is not available or cannot be instantiated. */ public static SAXParserFactory newNSInstance() { - if (NEW_NS_INSTANCE != null) { - final SAXParserFactory factory; - try { - factory = (SAXParserFactory) NEW_NS_INSTANCE.invokeExact(); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final SAXParserFactory factory = newInstance(); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newInstance()); } /** - * Returns a new, hardened, namespace-aware {@link SAXParserFactory} of the given implementation class. - * <p> - * Obtained as by {@code SAXParserFactory.newNSInstance(String, ClassLoader)} where the platform provides it (Java 13 or later), and by enabling namespace - * awareness on {@link #newInstance(String, ClassLoader)} otherwise, the behavior the JAXP method is specified to have. - * </p> + * Returns a new, hardened, namespace-aware {@link SAXParserFactory} of the given implementation class, enabling namespace awareness on + * {@link #newInstance(String, ClassLoader)}, the behavior {@code SAXParserFactory.newNSInstance(String, ClassLoader)} (Java 13 or later) is specified to have. * * @param factoryClassName The fully qualified class name of the {@link SAXParserFactory} implementation. * @param classLoader The class loader used to load the factory class; {@code null} means the current thread's context class loader. @@ -308,21 +273,7 @@ public static SAXParserFactory newNSInstance() { * @throws FactoryConfigurationError Thrown if {@code factoryClassName} is {@code null} or the factory class cannot be loaded or instantiated. */ public static SAXParserFactory newNSInstance(final String factoryClassName, final ClassLoader classLoader) { - if (NEW_NS_INSTANCE_BY_CLASS_NAME != null) { - final SAXParserFactory factory; - try { - factory = (SAXParserFactory) NEW_NS_INSTANCE_BY_CLASS_NAME.invokeExact(factoryClassName, classLoader); - } catch (final FactoryConfigurationError e) { - throw e; - } catch (final Throwable e) { - // Unreachable: the looked-up method declares no other exceptions. - throw new IllegalStateException(e); - } - return harden(factory); - } - final SAXParserFactory factory = newInstance(factoryClassName, classLoader); - factory.setNamespaceAware(true); - return factory; + return makeNSAware(newInstance(factoryClassName, classLoader)); } private static void setFeature(final SAXParserFactory factory, final String feature, final boolean value) { diff --git a/src/main/java/org/apache/commons/xml/HardeningTransformerFactory.java b/src/main/java/org/apache/commons/xml/HardeningTransformerFactory.java index a0ff62f..7f030c5 100644 --- a/src/main/java/org/apache/commons/xml/HardeningTransformerFactory.java +++ b/src/main/java/org/apache/commons/xml/HardeningTransformerFactory.java @@ -244,8 +244,7 @@ private static Source hardenSourceToDom(final Source source) throws TransformerC final InputSource inputSource = SAXSource.sourceToInputSource(source); if (inputSource != null) { try { - final DocumentBuilderFactory factory = HardeningDocumentBuilderFactory.harden(DocumentBuilderFactory.newInstance()); - factory.setNamespaceAware(true); + final DocumentBuilderFactory factory = HardeningDocumentBuilderFactory.newNSInstance(); final Document document = factory.newDocumentBuilder().parse(inputSource); return new DOMSource(document, inputSource.getSystemId()); } catch (final ParserConfigurationException | SAXException | IOException e) { diff --git a/src/main/java/org/apache/commons/xml/HardeningXPath.java b/src/main/java/org/apache/commons/xml/HardeningXPath.java index abac0b7..c843fea 100644 --- a/src/main/java/org/apache/commons/xml/HardeningXPath.java +++ b/src/main/java/org/apache/commons/xml/HardeningXPath.java @@ -66,8 +66,7 @@ final class HardeningXPath implements XPath { static Document parse(final InputSource source) throws XPathExpressionException { Objects.requireNonNull(source, "source"); try { - final DocumentBuilderFactory factory = HardeningDocumentBuilderFactory.harden(DocumentBuilderFactory.newInstance()); - factory.setNamespaceAware(true); + final DocumentBuilderFactory factory = HardeningDocumentBuilderFactory.newNSInstance(); return factory.newDocumentBuilder().parse(source); } catch (final ParserConfigurationException | SAXException | IOException e) { throw new XPathExpressionException(e);
