You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2009/06/12 18:35:32 UTC
svn commit: r784184 - in /cxf/trunk/rt/frontend/jaxrs/src:
main/java/org/apache/cxf/jaxrs/impl/
main/java/org/apache/cxf/jaxrs/model/wadl/
test/java/org/apache/cxf/jaxrs/model/wadl/
test/java/org/apache/cxf/jaxrs/resources/
Author: sergeyb
Date: Fri Jun 12 16:35:32 2009
New Revision: 784184
URL: http://svn.apache.org/viewvc?rev=784184&view=rev
Log:
CXF-1695 : prototyping initial WADL support, a lot more to be done
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java (with props)
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java (with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/Book.java
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java?rev=784184&r1=784183&r2=784184&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java Fri Jun 12 16:35:32 2009
@@ -47,6 +47,15 @@
private Message message;
private OperationResourceInfoStack stack;
+ @SuppressWarnings("unchecked")
+ public UriInfoImpl(Message m) {
+ this.message = m;
+ this.templateParams = (MultivaluedMap<String, String>)m.get(URITemplate.TEMPLATE_PARAMETERS);
+ if (m != null) {
+ this.stack = m.get(OperationResourceInfoStack.class);
+ }
+ }
+
public UriInfoImpl(Message m, MultivaluedMap<String, String> templateParams) {
this.message = m;
this.templateParams = templateParams;
Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java?rev=784184&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java Fri Jun 12 16:35:32 2009
@@ -0,0 +1,210 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.jaxrs.model.wadl;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.ext.RequestHandler;
+import org.apache.cxf.jaxrs.impl.UriInfoImpl;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.model.Parameter;
+import org.apache.cxf.jaxrs.model.ParameterType;
+import org.apache.cxf.message.Message;
+
+// TODO :
+// 1. extract JavaDocs and put them into XML comments
+// 2. if _type = html -> convert the XML buil here using MH's stylesheet
+// 3. generate grammars
+
+public class WadlGenerator implements RequestHandler {
+
+ public static final String WADL_QUERY = "_wadl";
+ public static final MediaType WADL_TYPE = MediaType.valueOf("application/vnd.sun.wadl+xml");
+ public static final String WADL_NS = "http://research.sun.com/wadl/2006/10";
+
+ public Response handleRequest(Message m, ClassResourceInfo resource) {
+
+ UriInfo ui = new UriInfoImpl(m);
+ if (!ui.getQueryParameters().containsKey(WADL_QUERY)) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("<application xmlns=\"").append(WADL_NS).append("\">");
+
+ sb.append("<resources base=\"").append(ui.getBaseUri().toString()).append("\">");
+ handleResource(sb, resource, resource.getURITemplate().getValue(),
+ resource.getURITemplate().getVariables());
+ sb.append("</resources>");
+ sb.append("</application>");
+
+ return Response.ok().type(WADL_TYPE).entity(sb.toString()).build();
+ }
+
+ private void handleResource(StringBuilder sb, ClassResourceInfo cri, String path,
+ List<String> templateVars) {
+ sb.append("<resource path=\"").append(path).append("\">");
+ handleTemplateParams(sb, templateVars);
+
+ List<OperationResourceInfo> sortedOps = sortOperationsByPath(
+ cri.getMethodDispatcher().getOperationResourceInfos());
+ List<OperationResourceInfo> opsWithSamePath = new LinkedList<OperationResourceInfo>();
+ for (int i = 0; i < sortedOps.size(); i++) {
+
+ if (sortedOps.get(i).getHttpMethod() == null) {
+ Class<?> cls = sortedOps.get(i).getMethodToInvoke().getReturnType();
+ ClassResourceInfo subcri = cri.findResource(cls, cls);
+ if (subcri != null) {
+ handleResource(sb, subcri, sortedOps.get(i).getURITemplate().getValue(),
+ sortedOps.get(i).getURITemplate().getVariables());
+ opsWithSamePath.clear();
+ continue;
+ } else {
+ handleDynamicSubresource(sb, sortedOps.get(i));
+ }
+ }
+ if (opsWithSamePath.size() == 0) {
+ opsWithSamePath.add(sortedOps.get(i));
+ } else if (i > 0 && sortedOps.get(i - 1).getURITemplate().getValue()
+ .equals(sortedOps.get(i).getURITemplate().getValue())) {
+ opsWithSamePath.add(sortedOps.get(i));
+ } else {
+ handleOperation(sb, opsWithSamePath);
+ opsWithSamePath.clear();
+ opsWithSamePath.add(sortedOps.get(i));
+ }
+ }
+ handleOperation(sb, opsWithSamePath);
+ sb.append("</resource>");
+ }
+
+ private void handleOperation(StringBuilder sb, List<OperationResourceInfo> oris) {
+ if (oris.size() == 0) {
+ return;
+ }
+ String path = oris.get(0).getURITemplate().getValue();
+ boolean isSlash = "/".equals(path);
+ if (!isSlash) {
+ sb.append("<resource path=\"").append(path).append("\">");
+ }
+ for (OperationResourceInfo ori : oris) {
+ handleTemplateParams(sb, ori.getURITemplate().getVariables());
+ handleMatrixParams(sb, ori);
+ }
+ for (OperationResourceInfo ori : oris) {
+ sb.append("<method name=\"").append(ori.getHttpMethod()).append("\">");
+ if (ori.getMethodToInvoke().getParameterTypes().length != 0) {
+ sb.append("<request>");
+ for (Parameter p : ori.getParameters()) {
+ handleParameter(sb, ori, p);
+ }
+ sb.append("</request>");
+ }
+ if (Void.class != ori.getMethodToInvoke().getReturnType()) {
+ sb.append("<response>");
+ handleRepresentation(sb, ori);
+ sb.append("</response>");
+ }
+ sb.append("</method>");
+ }
+ if (!isSlash) {
+ sb.append("</resource>");
+ }
+ }
+
+ private void handleDynamicSubresource(StringBuilder sb, OperationResourceInfo ori) {
+
+ sb.append("<!-- Dynamic subresource -->");
+ sb.append("<resource path=\"").append(ori.getURITemplate().getValue()).append("\">");
+ if (ori.getMethodToInvoke().getParameterTypes().length != 0) {
+ sb.append("<request>");
+ for (Parameter p : ori.getParameters()) {
+ handleParameter(sb, ori, p);
+ }
+ sb.append("</request>");
+ }
+ sb.append("</resource>");
+ }
+
+
+ private void handleParameter(StringBuilder sb, OperationResourceInfo ori, Parameter pm) {
+ if (pm.getType() == ParameterType.REQUEST_BODY) {
+ handleRepresentation(sb, ori);
+ return;
+ }
+ if (pm.getType() == ParameterType.PATH || pm.getType() == ParameterType.MATRIX) {
+ return;
+ }
+ if (pm.getType() == ParameterType.HEADER || pm.getType() == ParameterType.QUERY) {
+ writeParam(sb, pm.getName(), pm.getType().toString().toLowerCase(), pm.getDefaultValue());
+ }
+
+ }
+
+ private void handleMatrixParams(StringBuilder sb, OperationResourceInfo ori) {
+ for (Parameter pm : ori.getParameters()) {
+ if (pm.getType() == ParameterType.MATRIX) {
+ writeParam(sb, pm.getName(), "matrix", pm.getDefaultValue());
+ }
+ }
+ }
+
+ private void writeParam(StringBuilder sb, String name, String style, String dValue) {
+ sb.append("<param name=\"").append(name).append("\" ");
+ sb.append("style=\"").append(style).append("\"");
+ if (dValue != null) {
+ sb.append(" default=\"").append(dValue).append("\"");
+ }
+ sb.append("/>");
+ }
+
+ private void handleTemplateParams(StringBuilder sb, List<String> vars) {
+ for (String var : vars) {
+ writeParam(sb, var, "template", null);
+ }
+ }
+
+ private void handleRepresentation(StringBuilder sb, OperationResourceInfo ori) {
+ sb.append("<representation>");
+ sb.append("</representation>");
+ }
+
+ private List<OperationResourceInfo> sortOperationsByPath(Set<OperationResourceInfo> ops) {
+ List<OperationResourceInfo> opsWithSamePath = new LinkedList<OperationResourceInfo>(ops);
+ Collections.sort(opsWithSamePath, new Comparator<OperationResourceInfo>() {
+
+ public int compare(OperationResourceInfo op1, OperationResourceInfo op2) {
+ String path1 = op1.getURITemplate().getValue();
+ String path2 = op2.getURITemplate().getValue();
+ return path1.compareTo(path2);
+ }
+
+ });
+ return opsWithSamePath;
+ }
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/wadl/WadlGenerator.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java?rev=784184&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java Fri Jun 12 16:35:32 2009
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.jaxrs.model.wadl;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.resources.BookStore;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.servlet.ServletDestination;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class WadlGeneratorTest extends Assert {
+
+ private IMocksControl control;
+
+ @Before
+ public void setUp() {
+ control = EasyMock.createNiceControl();
+ control.makeThreadSafe(true);
+ }
+
+ @Test
+ public void testNoWadl() {
+ WadlGenerator wg = new WadlGenerator();
+ assertNull(wg.handleRequest(new MessageImpl(), null));
+ }
+
+ @Test
+ public void testWadl() throws Exception {
+ WadlGenerator wg = new WadlGenerator();
+ Message m = mockMessage("http://localhost:8080/baz", "/bar", WadlGenerator.WADL_QUERY);
+ ClassResourceInfo cri =
+ ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true);
+ Response r = wg.handleRequest(m, cri);
+ assertNotNull(r);
+ assertEquals(WadlGenerator.WADL_TYPE.toString(),
+ r.getMetadata().getFirst(HttpHeaders.CONTENT_TYPE));
+// System.out.println(r.getEntity().toString());
+// File f = new File("test.xml");
+// f.delete();
+// f.createNewFile();
+// System.out.println(f.getAbsolutePath());
+// FileOutputStream fos = new FileOutputStream(f);
+// fos.write(r.getEntity().toString().getBytes());
+// fos.flush();
+// fos.close();
+ }
+
+ private Message mockMessage(String baseAddress, String pathInfo, String query) {
+ Message m = new MessageImpl();
+ control.reset();
+ Exchange e = control.createMock(Exchange.class);
+ m.setExchange(e);
+ ServletDestination d = control.createMock(ServletDestination.class);
+ e.getDestination();
+ EasyMock.expectLastCall().andReturn(d).anyTimes();
+ EndpointInfo epr = new EndpointInfo();
+ epr.setAddress(baseAddress);
+ d.getEndpointInfo();
+ EasyMock.expectLastCall().andReturn(epr).anyTimes();
+ m.put(Message.REQUEST_URI, pathInfo);
+ m.put(Message.QUERY_STRING, query);
+ control.replay();
+ return m;
+ }
+
+}
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/Book.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/Book.java?rev=784184&r1=784183&r2=784184&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/Book.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/Book.java Fri Jun 12 16:35:32 2009
@@ -59,7 +59,7 @@
@Path("chapters/{chapterid}/")
@GET
- public Chapter getChapter(@PathParam("id")int chapterid) {
+ public Chapter getChapter(@PathParam("chapterid") int chapterid) {
return chapters.get(new Long(chapterid));
}