diff --git a/src/main/resources/META-INF/jax-ws-catalog.xml b/src/main/resources/META-INF/jax-ws-catalog.xml
new file mode 100644
index 0000000..9a15209
--- /dev/null
+++ b/src/main/resources/META-INF/jax-ws-catalog.xml
@@ -0,0 +1,30 @@
+
+
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+
+ See
+ http://www.w3.org/XML/1998/namespace.html and
+
+ http://www.w3.org/TR/REC-xml for information
+ about this namespace.
+
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+
+ See further below in this document for more information about how to refer to this schema document from your own
+ XSD schema documents and about the
+ namespace-versioning policy governing this schema document.
+
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+
+ See BCP 47 at
+ http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+ and the IANA language subtag registry at
+
+ http://www.iana.org/assignments/language-subtag-registry
+ for further information.
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.
+ See http://www.w3.org/TR/xmlbase/
+ for information about this attribute.
+
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.
+ See http://www.w3.org/TR/xml-id/
+ for information about this attribute.
+
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+
+ or
+
+ Subsequently, qualified reference to any of the attributes or the
+ group defined below will have the desired effect, e.g.
+
+ will define a type which will schema-validate an instance element
+ with any of those attributes.
+
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+
+ http://www.w3.org/2009/01/xml.xsd.
+
+ At the date of issue it can also be found at
+
+ http://www.w3.org/2001/xml.xsd.
+
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at
+ http://www.w3.org/2001/xml.xsd
+
+ will change accordingly; the version at
+
+ http://www.w3.org/2009/01/xml.xsd
+
+ will not change.
+
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+ About the XML namespace
+
+ lang (as an attribute name)
+ Notes
+ space (as an attribute name)
+ base (as an attribute name)
+ id (as an attribute name)
+ Father (in any context at all)
+
+
+
+ About this schema document
+
+ xml:base,
+ xml:lang, xml:space or
+ xml:id attributes on elements they define.
+
+ <schema . . .>
+ . . .
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+
+
+ <type . . .>
+ . . .
+ <attributeGroup ref="xml:specialAttrs"/>
+
+ Versioning policy for this schema document
+
Without this mapping the WSDL loader fetches dsp8033 / dsp8034 / xml.xsd / + * ws-addr.xsd from schemas.dmtf.org / www.w3.org over the network. On offline + * or restricted-egress hosts that fetch blocks for ~75 s (OS TCP timeout) and + * the connection attempt fails with + * {@code WSDLException(PARSER_ERROR) ... Caused by: ConnectException}. + */ +class CatalogResolutionTest { + + @Test + void catalogResolvesWsdlImportUrlsToClasspathResources() throws Exception { + // Dedicated Bus so the test neither leaks CXF resources nor mutates the + // JVM-wide default Bus shared with other tests. + final Bus bus = BusFactory.newInstance().createBus(); + try { + final OASISCatalogManager catalog = OASISCatalogManager.getCatalogManager(bus); + assertNotNull(catalog, "CXF OASISCatalogManager must be available"); + + assertResolvesToClasspath(catalog, "http://schemas.dmtf.org/wbem/wsman/1/dsp8033_1.0.xsd", "dsp8033_1.0.xsd"); + assertResolvesToClasspath(catalog, "http://schemas.dmtf.org/wbem/wsman/1/dsp8034_1.0.xsd", "dsp8034_1.0.xsd"); + assertResolvesToClasspath(catalog, "http://www.w3.org/2001/xml.xsd", "xml.xsd"); + assertResolvesToClasspath(catalog, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "ws-addr.xsd"); + } finally { + bus.shutdown(true); + } + } + + private static void assertResolvesToClasspath( + final OASISCatalogManager catalog, + final String systemId, + final String expectedSuffix + ) throws Exception { + final String resolved = catalog.resolveSystem(systemId); + assertNotNull(resolved, "catalog did not resolve " + systemId); + // Must NOT be a network URL — otherwise CXF will still hit the network at runtime. + assertFalse( + resolved.startsWith("http://") || resolved.startsWith("https://"), + "catalog returned a network URL for " + systemId + " -> " + resolved + ); + assertTrue(resolved.endsWith(expectedSuffix), "resolved URI does not end with " + expectedSuffix + ": " + resolved); + // The mapping must point at a resource that actually exists and is readable, + // not just a well-formed URI. + try (InputStream stream = new URI(resolved).toURL().openStream()) { + assertTrue(stream.read() != -1, "resolved URI is empty: " + resolved); + } + } +}