From b9c56ad3203ab9de08335051aa2a0ffde359385f Mon Sep 17 00:00:00 2001 From: Tomas Hofman Date: Wed, 6 May 2015 16:48:18 +0200 Subject: [PATCH 1/2] [CXF-6392] Schema imports are not handled correctly in generated WSDL and XSD files - test case demonstrating incorrect behaviour --- .../cxf/systest/jaxws/OASISCatalogTest.java | 98 +++++++++++++++---- .../resources/META-INF/jax-ws-catalog.xml | 1 + .../wsdl/others/d/d/hello_world_schema4.xsd | 27 +++++ .../wsdl/others/d/hello_world_schema4.xsd | 30 ++++++ .../wsdl/others/hello_world_schema.xsd | 2 +- .../wsdl/others/hello_world_schema2.xsd | 4 + .../wsdl/others/hello_world_schema3.xsd | 27 +++++ 7 files changed, 167 insertions(+), 22 deletions(-) create mode 100644 testutils/src/main/resources/wsdl/others/d/d/hello_world_schema4.xsd create mode 100644 testutils/src/main/resources/wsdl/others/d/hello_world_schema4.xsd create mode 100644 testutils/src/main/resources/wsdl/others/hello_world_schema3.xsd diff --git a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/OASISCatalogTest.java b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/OASISCatalogTest.java index f4553e90eba..32455177fa5 100644 --- a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/OASISCatalogTest.java +++ b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/OASISCatalogTest.java @@ -19,6 +19,7 @@ package org.apache.cxf.systest.jaxws; +import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; @@ -61,27 +62,69 @@ public class OASISCatalogTest extends Assert { public void testWSDLPublishWithCatalogs() throws Exception { Endpoint ep = Endpoint.publish("http://localhost:" + PORT + "/SoapContext/SoapPort", new GreeterImpl()); - try { - URL url = new URL("http://localhost:" + PORT + "/SoapContext/SoapPort?" - + "xsd=hello_world_schema2.xsd"); - assertNotNull(url.getContent()); - String result = IOUtils.toString((InputStream)url.getContent()); - assertTrue(result, result.contains("xsd=hello_world_schema.xsd")); - - - url = new URL("http://localhost:" + PORT + "/SoapContext/SoapPort" - + "?xsd=hello_world_schema.xsd"); - result = IOUtils.toString((InputStream)url.getContent()); - assertTrue(result, result.contains("xsd=hello_world_schema2.xsd")); - - url = new URL("http://localhost:" + PORT + "/SoapContext/SoapPort" - + "?wsdl=testutils/others/hello_world_messages_catalog.wsdl"); - result = IOUtils.toString((InputStream)url.getContent()); - assertTrue(result, result.contains("xsd=hello_world_schema.xsd")); - - } finally { - ep.stop(); - } + + String result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=hello_world_schema2.xsd"); + assertTrue(result, result.contains("xsd=hello_world_schema.xsd")); + assertTrue(result, result.contains("xsd=hello_world_schema3.xsd")); + assertTrue(result, result.contains("xsd=d/hello_world_schema4.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=hello_world_schema3.xsd"); + assertTrue(result.length() > 0); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=d/hello_world_schema4.xsd"); + assertTrue(result, result.contains("xsd=d/d/hello_world_schema4.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort" + + "?xsd=hello_world_schema.xsd"); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/hello_world_schema2.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort" + + "?wsdl=testutils/others/hello_world_messages_catalog.wsdl"); + assertTrue(result, result.contains("xsd=hello_world_schema.xsd")); + + ep.stop(); + } + + /** + * This is test case for https://issues.apache.org/jira/browse/CXF-6234 + * + * It's using paths that will be rewritten by following catalog rule: + * + * <rewriteSystem systemIdStartString="http://apache.org/hello_world/types2/" + * rewritePrefix="/wsdl/others/"/> + * + */ + @Test + public void testWSDLPublishWithCatalogsRewritePaths() { + Endpoint ep = Endpoint.publish("http://localhost:" + PORT + "/SoapContext/SoapPort", + new GreeterImpl()); + + String result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=http://apache.org/hello_world/types2/hello_world_schema2.xsd"); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/hello_world_schema.xsd")); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/hello_world_schema3.xsd")); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/d/hello_world_schema4.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=http://apache.org/hello_world/types2/hello_world_schema.xsd"); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/hello_world_schema2.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=http://apache.org/hello_world/types2/hello_world_schema3.xsd"); + assertTrue(result.length() > 0); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=http://apache.org/hello_world/types2/d/hello_world_schema4.xsd"); + assertTrue(result, result.contains("xsd=http://apache.org/hello_world/types2/d/d/hello_world_schema4.xsd")); + + result = readUrl("http://localhost:" + PORT + "/SoapContext/SoapPort?" + + "xsd=http://apache.org/hello_world/types2/d/d/hello_world_schema4.xsd"); + assertTrue(result.length() > 0); + + ep.stop(); } @Test @@ -170,4 +213,17 @@ public void testWSDLLocatorWithoutCatalog() throws Exception { } } + private String readUrl(String address) { + String content = null; + try { + URL url = new URL(address); + assertNotNull(url.getContent()); + content = IOUtils.toString((InputStream) url.getContent()); + } catch (IOException e) { + e.printStackTrace(System.err); + Assert.fail("Couldn't read URL: " + e.getMessage()); + } + return content; + } + } diff --git a/testutils/src/main/resources/META-INF/jax-ws-catalog.xml b/testutils/src/main/resources/META-INF/jax-ws-catalog.xml index 5b5322c1b91..28d5907b525 100644 --- a/testutils/src/main/resources/META-INF/jax-ws-catalog.xml +++ b/testutils/src/main/resources/META-INF/jax-ws-catalog.xml @@ -18,6 +18,7 @@ under the License. --> + diff --git a/testutils/src/main/resources/wsdl/others/d/d/hello_world_schema4.xsd b/testutils/src/main/resources/wsdl/others/d/d/hello_world_schema4.xsd new file mode 100644 index 00000000000..3868647605e --- /dev/null +++ b/testutils/src/main/resources/wsdl/others/d/d/hello_world_schema4.xsd @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/testutils/src/main/resources/wsdl/others/d/hello_world_schema4.xsd b/testutils/src/main/resources/wsdl/others/d/hello_world_schema4.xsd new file mode 100644 index 00000000000..44852a0d9b1 --- /dev/null +++ b/testutils/src/main/resources/wsdl/others/d/hello_world_schema4.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/testutils/src/main/resources/wsdl/others/hello_world_schema.xsd b/testutils/src/main/resources/wsdl/others/hello_world_schema.xsd index b9480ec6d59..5c0e655ff63 100644 --- a/testutils/src/main/resources/wsdl/others/hello_world_schema.xsd +++ b/testutils/src/main/resources/wsdl/others/hello_world_schema.xsd @@ -24,7 +24,7 @@ elementFormDefault="qualified"> + schemaLocation="http://apache.org/hello_world/types2/hello_world_schema2.xsd"/> diff --git a/testutils/src/main/resources/wsdl/others/hello_world_schema2.xsd b/testutils/src/main/resources/wsdl/others/hello_world_schema2.xsd index 45f9a38089d..c8fa92a3c38 100644 --- a/testutils/src/main/resources/wsdl/others/hello_world_schema2.xsd +++ b/testutils/src/main/resources/wsdl/others/hello_world_schema2.xsd @@ -23,6 +23,10 @@ + + + diff --git a/testutils/src/main/resources/wsdl/others/hello_world_schema3.xsd b/testutils/src/main/resources/wsdl/others/hello_world_schema3.xsd new file mode 100644 index 00000000000..0b779b67336 --- /dev/null +++ b/testutils/src/main/resources/wsdl/others/hello_world_schema3.xsd @@ -0,0 +1,27 @@ + + + + + + + + From 9363620d757ca7869883fc4d2450885abd174b73 Mon Sep 17 00:00:00 2001 From: Tomas Hofman Date: Wed, 6 May 2015 16:48:18 +0200 Subject: [PATCH 2/2] [CXF-6392] Schema imports are not handled correctly in generated WSDL and XSD files - proposed fix --- .../org/apache/cxf/frontend/WSDLGetUtils.java | 118 +++++++++--------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/WSDLGetUtils.java b/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/WSDLGetUtils.java index 8ab1437b2e3..9213e67c4e2 100644 --- a/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/WSDLGetUtils.java +++ b/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/WSDLGetUtils.java @@ -72,7 +72,7 @@ import org.apache.cxf.wsdl11.ServiceWSDLBuilder; /** - * + * */ public class WSDLGetUtils { @@ -83,9 +83,9 @@ public class WSDLGetUtils { private static final String WSDLS_KEY = WSDLGetUtils.class.getName() + ".WSDLs"; private static final String SCHEMAS_KEY = WSDLGetUtils.class.getName() + ".Schemas"; - + private static final Logger LOG = LogUtils.getL7dLogger(WSDLGetInterceptor.class); - + public WSDLGetUtils() { } @@ -96,10 +96,10 @@ public Set getWSDLIds(Message message, EndpointInfo endpointInfo) { Map params = new HashMap(); params.put("wsdl", ""); - getDocument(message, base, - params, ctxUri, + getDocument(message, base, + params, ctxUri, endpointInfo); - + Map mp = CastUtils.cast((Map)endpointInfo.getService() .getProperty(WSDLS_KEY)); return mp.keySet(); @@ -110,19 +110,19 @@ public Map getSchemaLocations(Message message, EndpointInfo endpointInfo) { Map params = new HashMap(); params.put("wsdl", ""); - getDocument(message, base, - params, ctxUri, + getDocument(message, base, + params, ctxUri, endpointInfo); - + Map mp = CastUtils.cast((Map)endpointInfo.getService() .getProperty(SCHEMAS_KEY)); - + Map schemas = new HashMap(); for (Map.Entry ent : mp.entrySet()) { params.clear(); params.put("xsd", ent.getKey()); Document doc = getDocument(message, base, params, ctxUri, endpointInfo); - schemas.put(doc.getDocumentElement().getAttribute("targetNamespace"), + schemas.put(doc.getDocumentElement().getAttribute("targetNamespace"), buildUrl(base, ctxUri, "xsd=" + ent.getKey())); } return schemas; @@ -161,16 +161,25 @@ public Document getDocument(Message message, } return doc; } - - protected String mapUri(String base, Map smp, String loc, String xsd) + + protected String mapUri(Bus bus, String base, Map smp, String loc, String xsd) throws UnsupportedEncodingException { String key = loc; try { boolean absoluteLocUri = new URI(loc).isAbsolute(); - if (!absoluteLocUri && xsd != null) { + if (!absoluteLocUri && xsd != null) { // XSD request + // resolve requested location with relative import path key = new URI(xsd).resolve(loc).toString(); - } - if (!absoluteLocUri && xsd == null) { + + if (!smp.containsKey(URLDecoder.decode(key, "utf-8"))) { + // if the result is not known, check if we can resolve it into something known + String resolved = resolveWithCatalogs(OASISCatalogManager.getCatalogManager(bus), key, base); + if (smp.containsKey(URLDecoder.decode(resolved, "utf-8"))) { + // if it is resolvable, we can use it + return base + "?xsd=" + key.replace(" ", "%20"); + } + } + } else if (!absoluteLocUri && xsd == null) { // WSDL request key = new URI(".").resolve(loc).toString(); } } catch (URISyntaxException e) { @@ -190,6 +199,7 @@ protected void updateDoc(Document doc, Message message, String xsd, String wsdl) { + Bus bus = message.getExchange().getBus(); List elementList = null; try { @@ -197,7 +207,7 @@ protected void updateDoc(Document doc, "http://www.w3.org/2001/XMLSchema", "import"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); - sl = mapUri(base, smp, sl, xsd); + sl = mapUri(bus, base, smp, sl, xsd); if (sl != null) { el.setAttribute("schemaLocation", sl); } @@ -208,7 +218,7 @@ protected void updateDoc(Document doc, "include"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); - sl = mapUri(base, smp, sl, xsd); + sl = mapUri(bus, base, smp, sl, xsd); if (sl != null) { el.setAttribute("schemaLocation", sl); } @@ -218,7 +228,7 @@ protected void updateDoc(Document doc, "redefine"); for (Element el : elementList) { String sl = el.getAttribute("schemaLocation"); - sl = mapUri(base, smp, sl, xsd); + sl = mapUri(bus, base, smp, sl, xsd); if (sl != null) { el.setAttribute("schemaLocation", sl); } @@ -393,7 +403,7 @@ protected void updateDefinition(Bus bus, : CastUtils.cast(types.getExtensibilityElements(), ExtensibilityElement.class)) { if (el instanceof Schema) { Schema see = (Schema)el; - updateSchemaImports(bus, see, see.getDocumentBaseURI(), doneSchemas, base, null); + updateSchemaImports(bus, see, see.getDocumentBaseURI(), doneSchemas, base); } } } @@ -450,8 +460,7 @@ protected void updateSchemaImports(Bus bus, Schema schema, String docBase, Map doneSchemas, - String base, - String parent) { + String base) { OASISCatalogManager catalogs = OASISCatalogManager.getCatalogManager(bus); Collection> imports = CastUtils.cast((Collection)schema.getImports().values()); for (List lst : imports) { @@ -476,36 +485,23 @@ protected void updateSchemaImports(Bus bus, String resolvedSchemaLocation = resolveWithCatalogs(catalogs, start, base); if (resolvedSchemaLocation == null) { resolvedSchemaLocation = resolveWithCatalogs(catalogs, imp.getSchemaLocationURI(), base); - } + } if (resolvedSchemaLocation == null) { try { //check to see if it's already in a URL format. If so, leave it. new URL(start); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, imp) == null) { - try { - //CHECKSTYLE:OFF:NestedIfDepth - if (!(new URI(decodedStart).isAbsolute()) && parent != null) { - resolvedSchemaLocation = new URI(parent).resolve(decodedStart).toString(); - decodedStart = URLDecoder.decode(resolvedSchemaLocation, "utf-8"); - doneSchemas.put(resolvedSchemaLocation, imp); - } - //CHECKSTYLE:ON:NestedIfDepth - } catch (URISyntaxException ex) { - // ignore - } catch (UnsupportedEncodingException ex) { - // ignore - } + putResolvedSchemaLocationIfRelative(doneSchemas, decodedStart, imp); updateSchemaImports(bus, imp.getReferencedSchema(), docBase, - doneSchemas, base, decodedStart); + doneSchemas, base); } } } else { if (doneSchemas.put(decodedStart, imp) == null) { doneSchemas.put(resolvedSchemaLocation, imp); doneSchemas.put(imp.getSchemaLocationURI(), imp); - updateSchemaImports(bus, imp.getReferencedSchema(), docBase, - doneSchemas, base, decodedStart); + updateSchemaImports(bus, imp.getReferencedSchema(), docBase, doneSchemas, base); } } } @@ -538,8 +534,8 @@ protected void updateSchemaImports(Bus bus, new URL(start); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, included) == null) { - updateSchemaImports(bus, included.getReferencedSchema(), - docBase, doneSchemas, base, decodedStart); + putResolvedSchemaLocationIfRelative(doneSchemas, decodedStart, included); + updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base); } } } @@ -547,7 +543,7 @@ protected void updateSchemaImports(Bus bus, || !doneSchemas.containsKey(resolvedSchemaLocation)) { doneSchemas.put(decodedStart, included); doneSchemas.put(resolvedSchemaLocation, included); - updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base, decodedStart); + updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base); } } } @@ -576,21 +572,8 @@ protected void updateSchemaImports(Bus bus, new URL(start); } catch (MalformedURLException e) { if (doneSchemas.put(decodedStart, included) == null) { - try { - //CHECKSTYLE:OFF:NestedIfDepth - if (!(new URI(decodedStart).isAbsolute()) && parent != null) { - resolvedSchemaLocation = new URI(parent).resolve(decodedStart).toString(); - decodedStart = URLDecoder.decode(resolvedSchemaLocation, "utf-8"); - doneSchemas.put(resolvedSchemaLocation, included); - } - //CHECKSTYLE:ON:NestedIfDepth - } catch (URISyntaxException ex) { - // ignore - } catch (UnsupportedEncodingException ex) { - // ignore - } - updateSchemaImports(bus, included.getReferencedSchema(), - docBase, doneSchemas, base, decodedStart); + putResolvedSchemaLocationIfRelative(doneSchemas, decodedStart, included); + updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base); } } } @@ -598,12 +581,31 @@ protected void updateSchemaImports(Bus bus, || !doneSchemas.containsKey(resolvedSchemaLocation)) { doneSchemas.put(decodedStart, included); doneSchemas.put(resolvedSchemaLocation, included); - updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base, decodedStart); + updateSchemaImports(bus, included.getReferencedSchema(), docBase, doneSchemas, base); } } } } + /** + * If given decodedStart is relative path, resolves a real location of given schema and puts it into schema map. + * + * @param doneSchemas schema map + * @param decodedStart path referencing schema + * @param schemaReference referenced schema + */ + private void putResolvedSchemaLocationIfRelative(Map doneSchemas, String decodedStart, + SchemaReference schemaReference) { + try { + if (!(new URI(decodedStart).isAbsolute())) { + String resolved = schemaReference.getReferencedSchema().getDocumentBaseURI(); + doneSchemas.put(resolved, schemaReference); + } + } catch (URISyntaxException ex) { + // ignore + } + } + private String findSchemaLocation(Map doneSchemas, SchemaReference imp, String docBase) {