Repository: cxf Updated Branches: refs/heads/3.0.x-fixes 78650303e -> 3dd409f04
More modifications to WADLGenerator to support optional stylesheet transformations Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/3dd409f0 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3dd409f0 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3dd409f0 Branch: refs/heads/3.0.x-fixes Commit: 3dd409f04e96c293827468730e636e09bdcee904 Parents: 7865030 Author: Sergey Beryozkin <[email protected]> Authored: Wed Feb 4 12:06:58 2015 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Wed Feb 4 12:13:16 2015 +0000 ---------------------------------------------------------------------- .../cxf/jaxrs/model/wadl/WadlGenerator.java | 108 +++++++++++++------ .../jaxrs/JAXRSClientServerSpringBookTest.java | 36 ++++++- .../src/test/resources/jaxrs/WEB-INF/beans.xml | 3 + .../jaxrs/WEB-INF/templates/wadlTemplate.xsl | 25 +++++ 4 files changed, 135 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/3dd409f0/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java index 491c0c5..00a9a70 100644 --- a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java +++ b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java @@ -72,13 +72,17 @@ import javax.xml.namespace.QName; import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; @@ -129,6 +133,7 @@ public class WadlGenerator implements ContainerRequestFilter { public static final String WADL_NS = "http://wadl.dev.java.net/2009/02"; private static final Logger LOG = LogUtils.getL7dLogger(WadlGenerator.class); + private static final String XLS_NS = "http://www.w3.org/1999/XSL/Transform"; private static final String JAXB_DEFAULT_NAMESPACE = "##default"; private static final String JAXB_DEFAULT_NAME = "##default"; private static final String CLASSPATH_PREFIX = "classpath:"; @@ -195,12 +200,13 @@ public class WadlGenerator implements ContainerRequestFilter { UriInfo ui = context.getUriInfo(); if (!ui.getQueryParameters().containsKey(WADL_QUERY)) { - if (!docLocationMap.isEmpty()) { + if (stylesheetReference != null || !docLocationMap.isEmpty()) { String path = ui.getPath(false); if (path.startsWith("/") && path.length() > 0) { path = path.substring(1); } - if (docLocationMap.containsKey(path)) { + if (stylesheetReference != null && path.endsWith(".xsl") + || docLocationMap.containsKey(path)) { context.abortWith(getExistingResource(m, ui, path)); } } @@ -233,6 +239,14 @@ public class WadlGenerator implements ContainerRequestFilter { context.abortWith(r); } + private String getStylesheetInstructionData(Message m, UriInfo ui) { + String theStylesheetReference = stylesheetReference; + if (!keepRelativeDocLinks) { + theStylesheetReference = UriBuilder.fromUri(getBaseURI(m, ui)) + .path(theStylesheetReference).build().toString(); + } + return "type=\"text/xsl\" href=\"" + theStylesheetReference + "\""; + } public StringBuilder generateWADL(String baseURI, List<ClassResourceInfo> cris, boolean isJson, @@ -240,7 +254,7 @@ public class WadlGenerator implements ContainerRequestFilter { UriInfo ui) { StringBuilder sbMain = new StringBuilder(); if (!isJson && stylesheetReference != null) { - sbMain.append("<?xml-stylesheet type=\"text/xsl\" href=\"" + stylesheetReference + "\"?>"); + sbMain.append("<?xml-stylesheet " + getStylesheetInstructionData(m, ui) + "?>"); } sbMain.append("<application"); if (!isJson) { @@ -1090,7 +1104,8 @@ public class WadlGenerator implements ContainerRequestFilter { try { InputStream is = ResourceUtils.getResourceStream(loc, (Bus)ep.get(Bus.class.getName())); if (is != null) { - Element appEl = StaxUtils.read(is).getDocumentElement(); + Document wadlDoc = StaxUtils.read(is); + Element appEl = wadlDoc.getDocumentElement(); List<Element> grammarEls = DOMUtils.getChildrenWithName(appEl, WadlGenerator.WADL_NS, "grammars"); @@ -1111,8 +1126,7 @@ public class WadlGenerator implements ContainerRequestFilter { WadlGenerator.WADL_NS, "resource"); handleExistingDocRefs(resourceEls, "type", loc, "", m, ui); - - return Response.ok().type(mt).entity(new DOMSource(appEl)).build(); + return finalizeExistingWadlResponse(wadlDoc, m, ui, mt); } } @@ -1123,48 +1137,76 @@ public class WadlGenerator implements ContainerRequestFilter { } return null; } + private Response finalizeExistingWadlResponse(Document wadlDoc, Message m, UriInfo ui, MediaType mt) + throws Exception { + if (stylesheetReference != null) { + ProcessingInstruction pi = wadlDoc.createProcessingInstruction("xml-stylesheet", + getStylesheetInstructionData(m, ui)); + wadlDoc.insertBefore(pi, wadlDoc.getDocumentElement()); + String wadlDocString = copyDOMToString(wadlDoc); + return Response.ok().type(mt).entity(wadlDocString).build(); + } else { + return Response.ok().type(mt).entity(new DOMSource(wadlDoc)).build(); + } + } + private static String copyDOMToString(Document wadlDoc) throws Exception { + DOMSource domSource = new DOMSource(wadlDoc); + // temporary workaround + StringWriter stringWriter = new StringWriter(); + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + transformer.transform(domSource, new StreamResult(stringWriter)); + return stringWriter.toString(); + } // TODO: deal with caching later on public Response getExistingResource(Message m, UriInfo ui, String href) { - String loc = docLocationMap.get(href); - Endpoint ep = m.getExchange().get(Endpoint.class); - if (ep != null && loc != null) { - try { + try { + String loc = docLocationMap.get(href); + if (loc != null) { int fragmentIndex = loc.lastIndexOf("#"); if (fragmentIndex != -1) { loc = loc.substring(0, fragmentIndex); } - InputStream is = ResourceUtils.getResourceStream(loc, (Bus)ep.get(Bus.class.getName())); + InputStream is = ResourceUtils.getResourceStream(loc, m.getExchange().getBus()); if (is != null) { Element docEl = StaxUtils.read(is).getDocumentElement(); - if (fragmentIndex != -1) { - List<Element> grammarEls = DOMUtils.getChildrenWithName(docEl, WadlGenerator.WADL_NS, - "grammars"); - if (grammarEls.size() == 1) { - handleExistingDocRefs(DOMUtils.getChildrenWithName(grammarEls.get(0), - WadlGenerator.WADL_NS, - "include"), "href", loc, href, - m, ui); - } + if (href.endsWith(".xsl")) { + List<Element> xslImports = DOMUtils.getChildrenWithName(docEl, XLS_NS, "import"); + handleExistingDocRefs(xslImports, "href", loc, href, m, ui); + List<Element> xslIncludes = DOMUtils.getChildrenWithName(docEl, XLS_NS, "import"); + handleExistingDocRefs(xslIncludes, "href", loc, href, m, ui); } else { - handleExistingDocRefs(DOMUtils.getChildrenWithName(docEl, - Constants.URI_2001_SCHEMA_XSD, - "import"), "schemaLocation", loc, - href, m, ui); - handleExistingDocRefs(DOMUtils.getChildrenWithName(docEl, - Constants.URI_2001_SCHEMA_XSD, - "include"), "schemaLocation", loc, - href, m, ui); + if (fragmentIndex != -1) { + List<Element> grammarEls = DOMUtils.getChildrenWithName(docEl, WADL_NS, "grammars"); + if (grammarEls.size() == 1) { + handleExistingDocRefs(DOMUtils.getChildrenWithName(grammarEls.get(0), WADL_NS, + "include"), "href", loc, href, + m, ui); + } + } else { + handleExistingDocRefs(DOMUtils.getChildrenWithName(docEl, + Constants.URI_2001_SCHEMA_XSD, + "import"), "schemaLocation", loc, + href, m, ui); + handleExistingDocRefs(DOMUtils.getChildrenWithName(docEl, + Constants.URI_2001_SCHEMA_XSD, + "include"), "schemaLocation", loc, + href, m, ui); + } } - + return Response.ok().type(MediaType.APPLICATION_XML_TYPE).entity(new DOMSource(docEl)) .build(); } - } catch (Exception ex) { - throw ExceptionUtils.toBadRequestException(null, null); + } else if (stylesheetReference != null && href.endsWith(".xsl")) { + InputStream is = ResourceUtils.getResourceStream(href, m.getExchange().getBus()); + return Response.ok().type(MediaType.APPLICATION_XML_TYPE).entity(is).build(); } - - } + + } catch (Exception ex) { + throw ExceptionUtils.toBadRequestException(null, null); + } return null; } http://git-wip-us.apache.org/repos/asf/cxf/blob/3dd409f0/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java index 7265127..c4df434 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java @@ -40,6 +40,9 @@ import javax.xml.bind.annotation.XmlRootElement; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.FileRequestEntity; @@ -136,8 +139,9 @@ public class JAXRSClientServerSpringBookTest extends AbstractBusClientServerTest @Test public void testGetWadlFromWadlLocation() throws Exception { String address = "http://localhost:" + PORT + "/the/generated"; - List<Element> resources = - checkWadlResourcesInfo(address, address + "/bookstore", "/schemas/book.xsd", 2); + WebClient client = WebClient.create(address + "/bookstore" + "?_wadl&_type=xml"); + Document doc = StaxUtils.read(new InputStreamReader(client.get(InputStream.class), "UTF-8")); + List<Element> resources = checkWadlResourcesInfo(doc, address, "/schemas/book.xsd", 2); assertEquals("", resources.get(0).getAttribute("type")); String type = resources.get(1).getAttribute("type"); String resourceTypeAddress = address + "/bookstoreImportResourceType.wadl#bookstoreType"; @@ -148,6 +152,26 @@ public class JAXRSClientServerSpringBookTest extends AbstractBusClientServerTest // check resource type resource checkWadlResourcesType(address, resourceTypeAddress, "/schemas/book.xsd"); + + String templateRef = null; + NodeList nd = doc.getChildNodes(); + for (int i = 0; i < nd.getLength(); i++) { + Node n = nd.item(i); + if (n.getNodeType() == Document.PROCESSING_INSTRUCTION_NODE) { + String piData = ((ProcessingInstruction)n).getData(); + int hRefStart = piData.indexOf("href=\""); + if (hRefStart > 0) { + int hRefEnd = piData.indexOf("\"", hRefStart + 6); + templateRef = piData.substring(hRefStart + 6, hRefEnd); + } + } + } + assertNotNull(templateRef); + WebClient client2 = WebClient.create(templateRef); + WebClient.getConfig(client2).getHttpConduit().getClient().setReceiveTimeout(1000000L); + String template = client2.get(String.class); + assertNotNull(template); + assertTrue(template.indexOf("<xsl:stylesheet") != -1); } @Test @@ -277,11 +301,16 @@ public class JAXRSClientServerSpringBookTest extends AbstractBusClientServerTest String schemaRef, int size) throws Exception { WebClient client = WebClient.create(requestURI + "?_wadl&_type=xml"); Document doc = StaxUtils.read(new InputStreamReader(client.get(InputStream.class), "UTF-8")); + return checkWadlResourcesInfo(doc, baseURI, schemaRef, size); + } + private List<Element> checkWadlResourcesInfo(Document doc, String baseURI, String schemaRef, int size) + throws Exception { + Element root = doc.getDocumentElement(); assertEquals(WadlGenerator.WADL_NS, root.getNamespaceURI()); assertEquals("application", root.getLocalName()); List<Element> grammarEls = DOMUtils.getChildrenWithName(root, - WadlGenerator.WADL_NS, "grammars"); + WadlGenerator.WADL_NS, "grammars"); assertEquals(1, grammarEls.size()); List<Element> includeEls = DOMUtils.getChildrenWithName(grammarEls.get(0), WadlGenerator.WADL_NS, "include"); @@ -298,7 +327,6 @@ public class JAXRSClientServerSpringBookTest extends AbstractBusClientServerTest WadlGenerator.WADL_NS, "resource"); assertEquals(size, resourceEls.size()); return resourceEls; - } @Test http://git-wip-us.apache.org/repos/asf/cxf/blob/3dd409f0/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml b/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml index ce1dac2..f1acd6d 100644 --- a/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml +++ b/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml @@ -190,6 +190,9 @@ </jaxrs:serviceBeans> <jaxrs:providers> <ref bean="jaxbProviderForTypes"/> + <bean class="org.apache.cxf.jaxrs.model.wadl.WadlGenerator"> + <property name="stylesheetReference" value="/WEB-INF/templates/wadlTemplate.xsl"/> + </bean> </jaxrs:providers> </jaxrs:server> <jaxrs:server id="bookservice9" address="/thebooks9"> http://git-wip-us.apache.org/repos/asf/cxf/blob/3dd409f0/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/templates/wadlTemplate.xsl ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/templates/wadlTemplate.xsl b/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/templates/wadlTemplate.xsl new file mode 100644 index 0000000..9d2243f --- /dev/null +++ b/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/templates/wadlTemplate.xsl @@ -0,0 +1,25 @@ +<!-- + 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 + + http://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. +--> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:wadl="http://wadl.dev.java.net/2009/02"> + + <xsl:template match="wadl:application"> + <!-- do something --> + </xsl:template> + +</xsl:stylesheet>
