This is an automated email from the ASF dual-hosted git repository. ppkarwasz pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/commons-xml.git
commit 3c596a611a27f01c711c37655b049acebb60738f Author: Piotr P. Karwasz <[email protected]> AuthorDate: Sat Apr 25 11:40:34 2026 +0200 feat: remove ProviderRegistry abstraction --- .../apache/commons/xml/factory/XmlFactories.java | 20 +-- .../xml/factory/internal/CompositeProvider.java | 143 ++++++++++++++++++++ .../xml/factory/internal/ProviderRegistry.java | 111 ---------------- .../factory/UnsupportedXmlImplementationTest.java | 4 +- .../attacks/SaxonXPathExternalCallsTest.java | 6 +- .../factory/internal/CompositeProviderTest.java | 146 +++++++++++++++++++++ .../xml/factory/internal/ProviderRegistryTest.java | 101 -------------- 7 files changed, 300 insertions(+), 231 deletions(-) diff --git a/src/main/java/org/apache/commons/xml/factory/XmlFactories.java b/src/main/java/org/apache/commons/xml/factory/XmlFactories.java index 3733d0c..09b73bf 100644 --- a/src/main/java/org/apache/commons/xml/factory/XmlFactories.java +++ b/src/main/java/org/apache/commons/xml/factory/XmlFactories.java @@ -24,7 +24,7 @@ import javax.xml.validation.SchemaFactory; import javax.xml.xpath.XPathFactory; -import org.apache.commons.xml.factory.internal.ProviderRegistry; +import org.apache.commons.xml.factory.internal.CompositeProvider; import org.apache.commons.xml.factory.spi.XmlProvider; /** @@ -74,8 +74,7 @@ public final class XmlFactories { * apply the hardening settings to it. */ public static DocumentBuilderFactory newDocumentBuilderFactory() { - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(DocumentBuilderFactory.newInstance()); } /** @@ -96,8 +95,7 @@ public static DocumentBuilderFactory newDocumentBuilderFactory() { * apply the hardening settings to it. */ public static SAXParserFactory newSAXParserFactory() { - final SAXParserFactory factory = SAXParserFactory.newInstance(); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(SAXParserFactory.newInstance()); } /** @@ -128,8 +126,7 @@ public static SAXParserFactory newSAXParserFactory() { * apply the hardening settings to it. */ public static SchemaFactory newSchemaFactory() { - final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)); } /** @@ -157,8 +154,7 @@ public static SchemaFactory newSchemaFactory() { * apply the hardening settings to it. */ public static TransformerFactory newTransformerFactory() { - final TransformerFactory factory = TransformerFactory.newInstance(); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(TransformerFactory.newInstance()); } /** @@ -184,8 +180,7 @@ public static TransformerFactory newTransformerFactory() { * apply the hardening settings to it. */ public static XMLInputFactory newXMLInputFactory() { - final XMLInputFactory factory = XMLInputFactory.newInstance(); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(XMLInputFactory.newInstance()); } /** @@ -205,8 +200,7 @@ public static XMLInputFactory newXMLInputFactory() { * apply the hardening settings to it. */ public static XPathFactory newXPathFactory() { - final XPathFactory factory = XPathFactory.newInstance(); - return ProviderRegistry.getInstance().providerFor(factory.getClass()).configure(factory); + return CompositeProvider.getInstance().configure(XPathFactory.newInstance()); } private XmlFactories() { diff --git a/src/main/java/org/apache/commons/xml/factory/internal/CompositeProvider.java b/src/main/java/org/apache/commons/xml/factory/internal/CompositeProvider.java new file mode 100644 index 0000000..f447f79 --- /dev/null +++ b/src/main/java/org/apache/commons/xml/factory/internal/CompositeProvider.java @@ -0,0 +1,143 @@ +/* + * 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 + * + * https://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.commons.xml.factory.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.validation.SchemaFactory; +import javax.xml.xpath.XPathFactory; + +import org.apache.commons.xml.factory.spi.XmlProvider; + +/** + * Internal {@link XmlProvider} that routes each {@code configure} call to the bundled or {@link ServiceLoader}-discovered provider responsible for the concrete + * JAXP factory class. + * + * <h2>Dispatch order</h2> + * + * <p>Providers are consulted in a single fixed list, built once when this class is loaded:</p> + * + * <ol> + * <li>Bundled providers in declared order: {@link StockJdkProvider}, {@link XercesProvider}, {@link WoodstoxProvider}, {@link SaxonProvider}.</li> + * <li>Third-party providers discovered via {@link ServiceLoader}, in the order {@link ServiceLoader} yields them.</li> + * </ol> + * + * <p>Bundled providers come first so that a third-party provider on the classpath cannot intercept hardening of a factory class this library already + * supports.</p> + * + * <p>If no provider matches, {@link HardeningException} is thrown.</p> + * + * <p>Although this class implements {@link XmlProvider}, its {@link #supports(Class)} method returns {@code false}: callers ask the composite to + * {@code configure}, never to advertise support. The interface implementation lets {@link org.apache.commons.xml.factory.XmlFactories} treat hardening + * uniformly without an extra abstraction.</p> + */ +public final class CompositeProvider implements XmlProvider { + + private static final CompositeProvider INSTANCE = new CompositeProvider(defaultProviders()); + + private final List<XmlProvider> providers; + + /** + * Constructs a composite over the supplied provider list. + * + * <p>Package-private for test use; production code should call {@link #getInstance()}.</p> + */ + CompositeProvider(final List<XmlProvider> providers) { + this.providers = Collections.unmodifiableList(new ArrayList<>(providers)); + } + + /** + * Gets the process-wide composite instance. + * + * @return the singleton. + */ + public static CompositeProvider getInstance() { + return INSTANCE; + } + + /** + * Stub implementation: always returns {@code false}. + * + * <p>The {@link XmlProvider} contract requires this method, but the class is internal and nothing in the library invokes it.</p> + * + * @param factoryClass ignored. + * @return {@code false}. + */ + @Override + public boolean supports(final Class<?> factoryClass) { + return false; + } + + @Override + public DocumentBuilderFactory configure(final DocumentBuilderFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + @Override + public SAXParserFactory configure(final SAXParserFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + @Override + public XMLInputFactory configure(final XMLInputFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + @Override + public TransformerFactory configure(final TransformerFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + @Override + public XPathFactory configure(final XPathFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + @Override + public SchemaFactory configure(final SchemaFactory factory) { + return providerFor(factory.getClass()).configure(factory); + } + + private XmlProvider providerFor(final Class<?> factoryClass) { + for (final XmlProvider provider : providers) { + if (provider.supports(factoryClass)) { + return provider; + } + } + throw new HardeningException(String.format( + "No XmlProvider supports JAXP factory class %s. Add a supported JAXP implementation to the classpath, " + + "or register a custom XmlProvider via ServiceLoader.", + factoryClass.getName())); + } + + private static List<XmlProvider> defaultProviders() { + final List<XmlProvider> all = new ArrayList<>(); + all.add(new StockJdkProvider()); + all.add(new XercesProvider()); + all.add(new WoodstoxProvider()); + all.add(new SaxonProvider()); + ServiceLoader.load(XmlProvider.class, CompositeProvider.class.getClassLoader()).forEach(all::add); + return all; + } +} diff --git a/src/main/java/org/apache/commons/xml/factory/internal/ProviderRegistry.java b/src/main/java/org/apache/commons/xml/factory/internal/ProviderRegistry.java deleted file mode 100644 index 5dad3b5..0000000 --- a/src/main/java/org/apache/commons/xml/factory/internal/ProviderRegistry.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 - * - * https://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.commons.xml.factory.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.ServiceLoader; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.apache.commons.xml.factory.spi.XmlProvider; - -/** - * Internal lookup for the {@link XmlProvider} responsible for a given concrete JAXP factory class. - * - * <h2>Dispatch order</h2> - * - * <ol> - * <li>Bundled providers in a fixed order: {@link StockJdkProvider}, {@link XercesProvider}, {@link WoodstoxProvider}, {@link SaxonProvider}.</li> - * <li>Third-party providers discovered via {@link ServiceLoader}, in the order {@link ServiceLoader} yields them.</li> - * <li>If nothing matches, {@link HardeningException}.</li> - * </ol> - * - * <p>Bundled providers are consulted first so that a third-party provider on the classpath cannot intercept hardening of a factory class this library already - * supports.</p> - * - * <p>Lookup results are cached keyed by factory class. The cache is thread-safe and only holds {@link XmlProvider} instances, never the factories - * themselves.</p> - */ -public final class ProviderRegistry { - - private static final ProviderRegistry INSTANCE = new ProviderRegistry(bundledProviders()); - - private final List<XmlProvider> bundled; - - private final ConcurrentMap<Class<?>, XmlProvider> cache = new ConcurrentHashMap<>(); - - /** - * Constructs a registry with the supplied bundled providers. - * - * <p>Package-private for test use; production code should call {@link #getInstance()}.</p> - */ - ProviderRegistry(final List<XmlProvider> bundled) { - this.bundled = Collections.unmodifiableList(new ArrayList<>(bundled)); - } - - /** - * Gets the process-wide registry instance. - * - * @return the singleton. - */ - public static ProviderRegistry getInstance() { - return INSTANCE; - } - - /** - * Looks up the provider responsible for factories of the supplied concrete class. - * - * @param factoryClass the concrete factory class; never {@code null}. - * @return the matching provider. - * @throws HardeningException if no provider matches. - */ - public XmlProvider providerFor(final Class<?> factoryClass) { - Objects.requireNonNull(factoryClass); - return cache.computeIfAbsent(factoryClass, this::lookup); - } - - private XmlProvider lookup(final Class<?> factoryClass) { - for (final XmlProvider provider : bundled) { - if (provider.supports(factoryClass)) { - return provider; - } - } - for (final XmlProvider provider : serviceLoaderProviders()) { - if (provider.supports(factoryClass)) { - return provider; - } - } - throw new HardeningException(String.format( - "No XmlProvider supports JAXP factory class %s. Add a supported JAXP implementation to the classpath, " - + "or register a custom XmlProvider via ServiceLoader.", - factoryClass.getName())); - } - - private static List<XmlProvider> bundledProviders() { - return Arrays.asList(new StockJdkProvider(), new XercesProvider(), new WoodstoxProvider(), new SaxonProvider()); - } - - private static Iterable<XmlProvider> serviceLoaderProviders() { - final ClassLoader loader = ProviderRegistry.class.getClassLoader(); - return ServiceLoader.load(XmlProvider.class, loader); - } - -} diff --git a/src/test/java/org/apache/commons/xml/factory/UnsupportedXmlImplementationTest.java b/src/test/java/org/apache/commons/xml/factory/UnsupportedXmlImplementationTest.java index a22b0c2..2eba600 100644 --- a/src/test/java/org/apache/commons/xml/factory/UnsupportedXmlImplementationTest.java +++ b/src/test/java/org/apache/commons/xml/factory/UnsupportedXmlImplementationTest.java @@ -23,7 +23,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import org.apache.commons.xml.factory.internal.ProviderRegistry; +import org.apache.commons.xml.factory.internal.CompositeProvider; import org.junit.jupiter.api.Test; /** @@ -66,7 +66,7 @@ public boolean getFeature(final String name) { void registryRejectsUnknownFactory() { final IllegalStateException thrown = assertThrows( IllegalStateException.class, - () -> ProviderRegistry.getInstance().providerFor(FakeDocumentBuilderFactory.class)); + () -> CompositeProvider.getInstance().configure(new FakeDocumentBuilderFactory())); assertNotNull(thrown.getMessage()); assertTrue(thrown.getMessage().contains(FakeDocumentBuilderFactory.class.getName()), "Exception message must name the unsupported class: " + thrown.getMessage()); diff --git a/src/test/java/org/apache/commons/xml/factory/attacks/SaxonXPathExternalCallsTest.java b/src/test/java/org/apache/commons/xml/factory/attacks/SaxonXPathExternalCallsTest.java index 113cc37..6df71dd 100644 --- a/src/test/java/org/apache/commons/xml/factory/attacks/SaxonXPathExternalCallsTest.java +++ b/src/test/java/org/apache/commons/xml/factory/attacks/SaxonXPathExternalCallsTest.java @@ -20,8 +20,7 @@ import javax.xml.xpath.XPathFactory; -import org.apache.commons.xml.factory.internal.ProviderRegistry; -import org.apache.commons.xml.factory.spi.XmlProvider; +import org.apache.commons.xml.factory.internal.CompositeProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -81,7 +80,6 @@ private static XPathFactory hardenedSaxonXPathFactory() { } catch (final ReflectiveOperationException e) { throw new AssertionError("Cannot instantiate " + SAXON_XPATH_FACTORY_CLASS, e); } - final XmlProvider provider = ProviderRegistry.getInstance().providerFor(xpf.getClass()); - return provider.configure(xpf); + return CompositeProvider.getInstance().configure(xpf); } } diff --git a/src/test/java/org/apache/commons/xml/factory/internal/CompositeProviderTest.java b/src/test/java/org/apache/commons/xml/factory/internal/CompositeProviderTest.java new file mode 100644 index 0000000..0fe3138 --- /dev/null +++ b/src/test/java/org/apache/commons/xml/factory/internal/CompositeProviderTest.java @@ -0,0 +1,146 @@ +/* + * 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 + * + * https://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.commons.xml.factory.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.xml.factory.spi.XmlProvider; +import org.junit.jupiter.api.Test; + +/** + * Verifies composite dispatch without relying on any bundled provider. + * + * <p>Stub providers are injected through the package-private {@link CompositeProvider#CompositeProvider(java.util.List)} constructor so the tests exercise the + * lookup, dispatch and cache logic in isolation from the ServiceLoader-discovered classpath.</p> + */ +class CompositeProviderTest { + + /** + * Stand-in factory whose concrete class is not matched by any bundled provider on the test classpath. + */ + private static final class FakeFactory extends DocumentBuilderFactory { + + @Override + public DocumentBuilder newDocumentBuilder() { + throw new UnsupportedOperationException(); + } + + @Override + public void setAttribute(final String name, final Object value) { + // no-op + } + + @Override + public Object getAttribute(final String name) { + return null; + } + + @Override + public void setFeature(final String name, final boolean value) { + // no-op + } + + @Override + public boolean getFeature(final String name) { + return false; + } + } + + /** Stub that records every {@code supports} and {@code configure} invocation and claims to support all classes. */ + private static final class CountingMatchAll implements XmlProvider { + + int supportsCount; + + int configureCount; + + @Override + public boolean supports(final Class<?> factoryClass) { + supportsCount++; + return true; + } + + @Override + public DocumentBuilderFactory configure(final DocumentBuilderFactory factory) { + configureCount++; + return factory; + } + } + + /** Stub that matches nothing. */ + private static final class MatchesNone implements XmlProvider { + @Override + public boolean supports(final Class<?> factoryClass) { + return false; + } + } + + @Test + void unknownFactoryClassThrowsHardeningException() { + final CompositeProvider composite = new CompositeProvider(Collections.emptyList()); + final FakeFactory factory = new FakeFactory(); + final HardeningException thrown = assertThrows(HardeningException.class, () -> composite.configure(factory)); + assertTrue(thrown.getMessage().contains(FakeFactory.class.getName()), + "Exception message must name the unsupported class: " + thrown.getMessage()); + } + + @Test + void scansProvidersOnEveryInvocation() { + final CountingMatchAll provider = new CountingMatchAll(); + final CompositeProvider composite = new CompositeProvider(Collections.singletonList(provider)); + final FakeFactory factory = new FakeFactory(); + composite.configure(factory); + composite.configure(factory); + assertEquals(2, provider.supportsCount, "supports() must be invoked once per configure call (no caching)"); + assertEquals(2, provider.configureCount); + } + + @Test + void bundledProvidersAreConsultedInDeclaredOrder() { + final CountingMatchAll winner = new CountingMatchAll(); + final CountingMatchAll shadowed = new CountingMatchAll(); + final CompositeProvider composite = new CompositeProvider(Arrays.asList(winner, shadowed)); + final FakeFactory factory = new FakeFactory(); + assertSame(factory, composite.configure(factory)); + assertEquals(1, winner.configureCount); + assertEquals(0, shadowed.configureCount); + } + + @Test + void nonMatchingBundledProviderFallsThroughToNext() { + final XmlProvider noMatch = new MatchesNone(); + final CountingMatchAll match = new CountingMatchAll(); + final CompositeProvider composite = new CompositeProvider(Arrays.asList(noMatch, match)); + composite.configure(new FakeFactory()); + assertEquals(1, match.configureCount); + } + + @Test + void supportsAlwaysReturnsFalse() { + final CompositeProvider composite = new CompositeProvider(Collections.singletonList(new CountingMatchAll())); + assertFalse(composite.supports(FakeFactory.class)); + } +} diff --git a/src/test/java/org/apache/commons/xml/factory/internal/ProviderRegistryTest.java b/src/test/java/org/apache/commons/xml/factory/internal/ProviderRegistryTest.java deleted file mode 100644 index 318e627..0000000 --- a/src/test/java/org/apache/commons/xml/factory/internal/ProviderRegistryTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 - * - * https://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.commons.xml.factory.internal; - -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.Collections; - -import org.apache.commons.xml.factory.spi.XmlProvider; -import org.junit.jupiter.api.Test; - -/** - * Verifies registry dispatch without relying on any bundled provider. - * - * <p>Stub providers are injected through the package-private {@link ProviderRegistry#ProviderRegistry(java.util.List)} constructor so the tests exercise the - * lookup and cache logic in isolation from the ServiceLoader-discovered classpath.</p> - */ -class ProviderRegistryTest { - - /** Stub that claims to support every non-null factory class. */ - private static final class MatchesAll implements XmlProvider { - @Override - public boolean supports(final Class<?> factoryClass) { - return factoryClass != null; - } - } - - /** Stub that matches nothing. */ - private static final class MatchesNone implements XmlProvider { - @Override - public boolean supports(final Class<?> factoryClass) { - return false; - } - } - - @Test - void providerForNullThrowsNpe() { - final ProviderRegistry registry = new ProviderRegistry(Collections.emptyList()); - assertThrows(NullPointerException.class, () -> registry.providerFor(null)); - } - - @Test - void providerForUnknownClassThrowsHardeningException() { - final ProviderRegistry registry = new ProviderRegistry(Collections.emptyList()); - final HardeningException thrown = assertThrows( - HardeningException.class, - () -> registry.providerFor(String.class)); - assertTrue(thrown.getMessage().contains(String.class.getName()), - "Exception message must name the unsupported class: " + thrown.getMessage()); - } - - @Test - void providerForCachesResolvedProvider() { - final XmlProvider stub = new MatchesAll(); - final ProviderRegistry registry = new ProviderRegistry(Collections.singletonList(stub)); - final XmlProvider first = registry.providerFor(String.class); - final XmlProvider second = registry.providerFor(String.class); - assertSame(first, second); - assertSame(stub, first); - } - - @Test - void bundledProvidersAreConsultedInDeclaredOrder() { - final XmlProvider winner = new MatchesAll(); - final XmlProvider shadowed = new MatchesAll(); - final ProviderRegistry registry = new ProviderRegistry(Arrays.asList(winner, shadowed)); - assertSame(winner, registry.providerFor(String.class)); - } - - @Test - void nonMatchingBundledProviderFallsThroughToNext() { - final XmlProvider noMatch = new MatchesNone(); - final XmlProvider match = new MatchesAll(); - final ProviderRegistry registry = new ProviderRegistry(Arrays.asList(noMatch, match)); - assertSame(match, registry.providerFor(String.class)); - } - - @Test - void emptyBundledListWithNoServiceLoaderProvidersThrows() { - final ProviderRegistry registry = new ProviderRegistry(Collections.emptyList()); - assertThrows(HardeningException.class, - () -> registry.providerFor(Integer.class)); - } -}
