Repository: cxf Updated Branches: refs/heads/master 2cfa9011a -> 992e3d604
[CXF-6264] Prototyping Swagger to UserModel converters Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/992e3d60 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/992e3d60 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/992e3d60 Branch: refs/heads/master Commit: 992e3d604089e02863a24112f2cbd1db4cf09591 Parents: 2cfa901 Author: Sergey Beryozkin <[email protected]> Authored: Mon Feb 23 15:54:34 2015 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Mon Feb 23 15:54:34 2015 +0000 ---------------------------------------------------------------------- .../apache/cxf/jaxrs/model/UserResource.java | 9 +- rt/rs/description/pom.xml | 12 + .../apache/cxf/jaxrs/swagger/SwaggerUtils.java | 233 +++++++++++++++++++ .../cxf/jaxrs/model/wadl/BookChapters.java | 37 +++ .../apache/cxf/jaxrs/model/wadl/Chapter.java | 58 +++++ .../jaxrs/model/wadl/WadlGeneratorJsonTest.java | 137 +++++++++++ .../cxf/jaxrs/swagger/SwaggerUtilsTest.java | 70 ++++++ .../description/src/test/resources/json.schema | 27 +++ .../src/test/resources/swagger12.json | 27 +++ .../src/test/resources/swagger20.json | 31 +++ rt/rs/extensions/providers/pom.xml | 6 - .../json/JsonMapObjectReaderWriter.java | 2 +- .../jaxrs/provider/ProviderFactoryAllTest.java | 6 +- .../jaxrs/provider/json/WadlGeneratorTest.java | 138 ----------- .../apache/cxf/jaxrs/resources/BookStore.java | 37 --- .../org/apache/cxf/jaxrs/resources/Chapter.java | 59 ----- .../providers/src/test/resources/json.schema | 27 --- ...AXRSClientServerUserResourceDefaultTest.java | 6 +- .../cxf/tools/wadlto/jaxrs/SourceGenerator.java | 2 +- 19 files changed, 646 insertions(+), 278 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/UserResource.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/UserResource.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/UserResource.java index c8d1ec3..39e2417 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/UserResource.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/UserResource.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.helpers.CastUtils; public class UserResource { @@ -59,13 +60,13 @@ public class UserResource { } public void setConsumes(String types) { - if (!"".equals(types)) { + if (!StringUtils.isEmpty(types)) { consumesTypes = types; } } public void setProduces(String types) { - if (!"".equals(types)) { + if (!StringUtils.isEmpty(types)) { producesTypes = types; } } @@ -75,7 +76,7 @@ public class UserResource { } public void setName(String name) { - if (!"".equals(name)) { + if (!StringUtils.isEmpty(name)) { className = name; } } @@ -85,7 +86,7 @@ public class UserResource { } public void setPath(String path) { - if (!"".equals(path)) { + if (!StringUtils.isEmpty(path)) { pathValue = path; } } http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/description/pom.xml b/rt/rs/description/pom.xml index 4d40eab..49bf4d8 100644 --- a/rt/rs/description/pom.xml +++ b/rt/rs/description/pom.xml @@ -66,6 +66,18 @@ </exclusions> </dependency> <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-extension-providers</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.codehaus.jettison</groupId> + <artifactId>jettison</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUtils.java b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUtils.java new file mode 100644 index 0000000..7532361 --- /dev/null +++ b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/SwaggerUtils.java @@ -0,0 +1,233 @@ +/** + * 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.swagger; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.apache.cxf.Bus; +import org.apache.cxf.BusFactory; +import org.apache.cxf.common.classloader.ClassLoaderUtils; +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.jaxrs.model.Parameter; +import org.apache.cxf.jaxrs.model.ParameterType; +import org.apache.cxf.jaxrs.model.UserOperation; +import org.apache.cxf.jaxrs.model.UserResource; +import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter; +import org.apache.cxf.jaxrs.utils.ResourceUtils; + +public final class SwaggerUtils { + private static final Logger LOG = LogUtils.getL7dLogger(ResourceUtils.class); + private static final Map<String, String> SWAGGER_TYPE_MAP; + static { + SWAGGER_TYPE_MAP = new HashMap<String, String>(); + SWAGGER_TYPE_MAP.put("string", "String"); + SWAGGER_TYPE_MAP.put("integer", "long"); + SWAGGER_TYPE_MAP.put("float", "float"); + SWAGGER_TYPE_MAP.put("double", "double"); + SWAGGER_TYPE_MAP.put("int", "int"); + SWAGGER_TYPE_MAP.put("long", "long"); + SWAGGER_TYPE_MAP.put("byte", "byte"); + SWAGGER_TYPE_MAP.put("boolean", "boolean"); + SWAGGER_TYPE_MAP.put("date", "java.util.Date"); + SWAGGER_TYPE_MAP.put("dateTime", "java.util.Date"); + SWAGGER_TYPE_MAP.put("File", "java.io.InputStream"); + SWAGGER_TYPE_MAP.put("file", "java.io.InputStream"); + } + private SwaggerUtils() { + + } + public static UserResource getUserResource(String loc) { + return getUserResource(loc, BusFactory.getThreadDefaultBus()); + } + public static UserResource getUserResource(String loc, Bus bus) { + try { + InputStream is = ResourceUtils.getResourceStream(loc, bus); + if (is == null) { + return null; + } + return getUserResourceFromJson(IOUtils.readStringFromStream(is)); + } catch (Exception ex) { + LOG.warning("Problem with processing a user model at " + loc); + } + return null; + } + public static List<UserResource> getUserResourcesFromResourceObjects(List<String> jsonObjects) { + List<UserResource> resources = new ArrayList<UserResource>(); + for (String json : jsonObjects) { + resources.add(getUserResourceFromJson(json)); + } + return resources; + } + public static UserResource getUserResourceFromJson(String json) { + JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter(); + Map<String, Object> map = reader.fromJson(json); + + if (map.containsKey("swaggerVersion")) { + return getUserResourceFromSwagger12(map); + } else { + return getUserResourceFromSwagger20(map); + } + + } + private static UserResource getUserResourceFromSwagger20(Map<String, Object> map) { + UserResource ur = new UserResource(); + String relativePath = (String)map.get("basePath"); + ur.setPath(relativePath == null ? "/" : relativePath); + + List<String> resourceProduces = CastUtils.cast((List<?>)map.get("produces")); + ur.setProduces(listToString(resourceProduces)); + + List<String> resourceConsumes = CastUtils.cast((List<?>)map.get("consumes")); + ur.setConsumes(listToString(resourceConsumes)); + + List<UserOperation> userOps = new LinkedList<UserOperation>(); + Map<String, Map<String, Object>> paths = CastUtils.cast((Map<?, ?>)map.get("paths")); + for (Map.Entry<String, Map<String, Object>> pathEntry : paths.entrySet()) { + + String operPath = pathEntry.getKey(); + + Map<String, Object> operations = pathEntry.getValue(); + for (Map.Entry<String, Object> operEntry : operations.entrySet()) { + UserOperation userOp = new UserOperation(); + userOp.setVerb(operEntry.getKey().toUpperCase()); + userOp.setPath(operPath); + + Map<String, Object> oper = CastUtils.cast((Map<?, ?>)operEntry.getValue()); + + userOp.setName((String)oper.get("operationId")); + List<String> opProduces = CastUtils.cast((List<?>)oper.get("produces")); + userOp.setProduces(listToString(opProduces)); + + List<String> opConsumes = CastUtils.cast((List<?>)oper.get("consumes")); + userOp.setConsumes(listToString(opConsumes)); + + List<Parameter> userOpParams = new LinkedList<Parameter>(); + List<Map<String, Object>> params = CastUtils.cast((List<?>)oper.get("parameters")); + for (Map<String, Object> param : params) { + String name = (String)param.get("name"); + //"query", "header", "path", "formData" or "body" + String paramType = (String)param.get("in"); + ParameterType pType = "body".equals(paramType) ? ParameterType.REQUEST_BODY + : "formData".equals(paramType) + ? ParameterType.FORM : ParameterType.valueOf(paramType.toUpperCase()); + Parameter userParam = new Parameter(pType, name); + + setJavaType(userParam, (String)param.get("type")); + + userOpParams.add(userParam); + } + if (!userOpParams.isEmpty()) { + userOp.setParameters(userOpParams); + } + userOps.add(userOp); + } + } + ur.setOperations(userOps); + return ur; + } + private static UserResource getUserResourceFromSwagger12(Map<String, Object> map) { + UserResource ur = new UserResource(); + String relativePath = (String)map.get("resourcePath"); + ur.setPath(relativePath == null ? "/" : relativePath); + + List<String> resourceProduces = CastUtils.cast((List<?>)map.get("produces")); + ur.setProduces(listToString(resourceProduces)); + + List<String> resourceConsumes = CastUtils.cast((List<?>)map.get("consumes")); + ur.setConsumes(listToString(resourceConsumes)); + + List<UserOperation> userOps = new LinkedList<UserOperation>(); + List<Map<String, Object>> apis = CastUtils.cast((List<?>)map.get("apis")); + for (Map<String, Object> api : apis) { + String operPath = (String)api.get("path"); + if (relativePath != null && operPath.startsWith(relativePath) + && operPath.length() > relativePath.length()) { + // relative resource and operation paths overlap in Swagger 1.2 + operPath = operPath.substring(relativePath.length()); + } + + List<Map<String, Object>> operations = CastUtils.cast((List<?>)api.get("operations")); + for (Map<String, Object> oper : operations) { + UserOperation userOp = new UserOperation(); + userOp.setPath(operPath); + userOp.setName((String)oper.get("nickname")); + userOp.setVerb((String)oper.get("method")); + + List<String> opProduces = CastUtils.cast((List<?>)oper.get("produces")); + userOp.setProduces(listToString(opProduces)); + + List<String> opConsumes = CastUtils.cast((List<?>)oper.get("consumes")); + userOp.setConsumes(listToString(opConsumes)); + + List<Parameter> userOpParams = new LinkedList<Parameter>(); + List<Map<String, Object>> params = CastUtils.cast((List<?>)oper.get("parameters")); + for (Map<String, Object> param : params) { + String name = (String)param.get("name"); + //"path", "query", "body", "header", "form" + String paramType = (String)param.get("paramType"); + ParameterType pType = "body".equals(paramType) + ? ParameterType.REQUEST_BODY : ParameterType.valueOf(paramType.toUpperCase()); + Parameter userParam = new Parameter(pType, name); + setJavaType(userParam, (String)param.get("type")); + + userOpParams.add(userParam); + } + if (!userOpParams.isEmpty()) { + userOp.setParameters(userOpParams); + } + userOps.add(userOp); + } + } + ur.setOperations(userOps); + return ur; + } + private static void setJavaType(Parameter userParam, String typeName) { + String javaTypeName = SWAGGER_TYPE_MAP.get(typeName); + if (javaTypeName != null) { + try { + userParam.setJavaType(ClassLoaderUtils.loadClass(javaTypeName, SwaggerUtils.class)); + } catch (Throwable t) { + // ignore - can be a reference to a JSON model class, etc + } + } + + } + private static String listToString(List<String> list) { + if (list != null) { + StringBuilder sb = new StringBuilder(); + for (String s : list) { + if (sb.length() > 0) { + sb.append(','); + } + sb.append(s); + } + return sb.toString(); + } else { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookChapters.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookChapters.java b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookChapters.java new file mode 100644 index 0000000..c4f67a9 --- /dev/null +++ b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/BookChapters.java @@ -0,0 +1,37 @@ +/** + * 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.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +@Path("/bookstore/{id}") +@Consumes({"application/xml", "application/json" }) +@Produces({"application/xml", "application/json" }) +public class BookChapters { + + @GET + @Path("chapter") + public Chapter getChapter() { + return new Chapter(1); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/Chapter.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/Chapter.java b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/Chapter.java new file mode 100644 index 0000000..15b7197 --- /dev/null +++ b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/Chapter.java @@ -0,0 +1,58 @@ +/** + * 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.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.apache.cxf.jaxrs.ext.xml.XMLName; + +@XmlRootElement(name = "thechapter", namespace = "http://superbooks") +@XmlType(name = "chapter", namespace = "http://superbooks") +@Description("Chapter subresource") +@XMLName(value = "{http://books}thesuperchapter") +public class Chapter { + + private int id; + public Chapter() { + } + public Chapter(int id) { + this.id = id; + } + + @GET + @Path("/id") + @Produces({"application/xml", "application/json" }) + @Description("Get the chapter") + public Chapter getIt() { + return this; + } + + public void setId(int ident) { + id = ident; + } + + public int getId() { + return id; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorJsonTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorJsonTest.java b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorJsonTest.java new file mode 100644 index 0000000..cf36806 --- /dev/null +++ b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/model/wadl/WadlGeneratorJsonTest.java @@ -0,0 +1,137 @@ +/** + * 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.io.ByteArrayOutputStream; +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.w3c.dom.Document; + +import org.apache.cxf.endpoint.Endpoint; +import org.apache.cxf.endpoint.EndpointImpl; +import org.apache.cxf.jaxrs.JAXRSServiceImpl; +import org.apache.cxf.jaxrs.impl.ContainerRequestContextImpl; +import org.apache.cxf.jaxrs.impl.MetadataMap; +import org.apache.cxf.jaxrs.model.ClassResourceInfo; +import org.apache.cxf.jaxrs.provider.json.JSONProvider; +import org.apache.cxf.jaxrs.utils.ResourceUtils; +import org.apache.cxf.message.Exchange; +import org.apache.cxf.message.ExchangeImpl; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.service.Service; +import org.apache.cxf.service.model.BindingInfo; +import org.apache.cxf.service.model.EndpointInfo; +import org.apache.cxf.transport.servlet.ServletDestination; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class WadlGeneratorJsonTest extends Assert { + + private IMocksControl control; + + @Before + public void setUp() { + control = EasyMock.createNiceControl(); + control.makeThreadSafe(true); + } + + @Test + public void testWadlInJsonFormat() throws Exception { + ClassResourceInfo cri = + ResourceUtils.createClassResourceInfo(BookChapters.class, BookChapters.class, true, true); + final Message m = mockMessage("http://localhost:8080/baz", "/bookstore/1", WadlGenerator.WADL_QUERY, cri); + Map<String, List<String>> headers = new HashMap<String, List<String>>(); + headers.put("Accept", Collections.singletonList("application/json")); + m.put(Message.PROTOCOL_HEADERS, headers); + + WadlGenerator wg = new WadlGenerator() { + public void filter(ContainerRequestContext context) { + super.doFilter(context, m); + } + }; + wg.setUseJaxbContextForQnames(false); + wg.setIgnoreMessageWriters(false); + wg.setExternalLinks(Collections.singletonList("json.schema")); + + Response r = handleRequest(wg, m); + assertEquals("application/json", + r.getMetadata().getFirst("Content-Type").toString()); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + new JSONProvider<Document>().writeTo( + (Document)r.getEntity(), Document.class, Document.class, + new Annotation[]{}, MediaType.APPLICATION_JSON_TYPE, + new MetadataMap<String, Object>(), os); + String s = os.toString(); + String expected1 = + "{\"application\":{\"grammars\":{\"include\":{\"@href\":\"http://localhost:8080/baz" + + "/json.schema\"}},\"resources\":{\"@base\":\"http://localhost:8080/baz\"," + + "\"resource\":{\"@path\":\"/bookstore/{id}\""; + assertTrue(s.startsWith(expected1)); + String expected2 = + "\"response\":{\"representation\":[{\"@mediaType\":\"application/xml\"}," + + "{\"@element\":\"Chapter\",\"@mediaType\":\"application/json\"}]}"; + assertTrue(s.contains(expected2)); + } + private Response handleRequest(WadlGenerator wg, Message m) { + wg.filter(new ContainerRequestContextImpl(m, true, false)); + return m.getExchange().get(Response.class); + } + private Message mockMessage(String baseAddress, String pathInfo, String query, + ClassResourceInfo cri) throws Exception { + Message m = new MessageImpl(); + Exchange e = new ExchangeImpl(); + e.put(Service.class, new JAXRSServiceImpl(Collections.singletonList(cri))); + m.setExchange(e); + control.reset(); + ServletDestination d = control.createMock(ServletDestination.class); + EndpointInfo epr = new EndpointInfo(); + epr.setAddress(baseAddress); + d.getEndpointInfo(); + EasyMock.expectLastCall().andReturn(epr).anyTimes(); + + Endpoint endpoint = new EndpointImpl(null, null, epr); + e.put(Endpoint.class, endpoint); + + e.setDestination(d); + BindingInfo bi = control.createMock(BindingInfo.class); + epr.setBinding(bi); + bi.getProperties(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()).anyTimes(); + m.put(Message.REQUEST_URI, pathInfo); + m.put(Message.QUERY_STRING, query); + m.put(Message.HTTP_REQUEST_METHOD, "GET"); + control.replay(); + return m; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/swagger/SwaggerUtilsTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/swagger/SwaggerUtilsTest.java b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/swagger/SwaggerUtilsTest.java new file mode 100644 index 0000000..e9434e1 --- /dev/null +++ b/rt/rs/description/src/test/java/org/apache/cxf/jaxrs/swagger/SwaggerUtilsTest.java @@ -0,0 +1,70 @@ +/** + * 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.swagger; + +import org.apache.cxf.jaxrs.model.Parameter; +import org.apache.cxf.jaxrs.model.ParameterType; +import org.apache.cxf.jaxrs.model.UserOperation; +import org.apache.cxf.jaxrs.model.UserResource; + +import org.junit.Assert; +import org.junit.Test; + +public class SwaggerUtilsTest extends Assert { + + @Test + public void testConvertSwagger12ToUserResource() { + UserResource ur = SwaggerUtils.getUserResource("/swagger12.json"); + assertNotNull(ur); + assertEquals("/hello", ur.getPath()); + assertEquals(1, ur.getOperations().size()); + UserOperation op = ur.getOperations().get(0); + assertEquals("helloSubject", op.getName()); + assertEquals("/{subject}", op.getPath()); + assertEquals("GET", op.getVerb()); + assertEquals(1, op.getParameters().size()); + Parameter param = op.getParameters().get(0); + assertEquals("subject", param.getName()); + assertEquals(ParameterType.PATH, param.getType()); + assertEquals(String.class, param.getJavaType()); + } + @Test + public void testConvertSwagger20ToUserResource() { + UserResource ur = SwaggerUtils.getUserResource("/swagger20.json"); + assertNotNull(ur); + assertEquals("/base", ur.getPath()); + assertEquals(1, ur.getOperations().size()); + UserOperation op = ur.getOperations().get(0); + assertEquals("postOp", op.getName()); + assertEquals("/somepath", op.getPath()); + assertEquals("POST", op.getVerb()); + assertEquals("application/x-www-form-urlencoded", op.getConsumes()); + assertEquals("application/json", op.getProduces()); + + assertEquals(2, op.getParameters().size()); + Parameter param1 = op.getParameters().get(0); + assertEquals("userName", param1.getName()); + assertEquals(ParameterType.FORM, param1.getType()); + assertEquals(String.class, param1.getJavaType()); + Parameter param2 = op.getParameters().get(1); + assertEquals("password", param2.getName()); + assertEquals(ParameterType.FORM, param2.getType()); + assertEquals(String.class, param2.getJavaType()); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/resources/json.schema ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/resources/json.schema b/rt/rs/description/src/test/resources/json.schema new file mode 100644 index 0000000..7199661 --- /dev/null +++ b/rt/rs/description/src/test/resources/json.schema @@ -0,0 +1,27 @@ +{ + "name":"Book", + "properties":{ + "id":{ + "type":"number", + "description":"Product identifier", + "required":true + }, + "name":{ + "description":"Name of the product", + "type":"string", + "required":true + }, + "price":{ + "required":true, + "type": "number", + "minimum":0, + "required":true + }, + "tags":{ + "type":"array", + "items":{ + "type":"string" + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/resources/swagger12.json ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/resources/swagger12.json b/rt/rs/description/src/test/resources/swagger12.json new file mode 100644 index 0000000..d6b3bab --- /dev/null +++ b/rt/rs/description/src/test/resources/swagger12.json @@ -0,0 +1,27 @@ +{ + "swaggerVersion": "1.2", + "basePath": "http://localhost:8000/greetings", + "resourcePath": "/hello", + "apis": [ + { + "path": "/hello/{subject}", + "operations": [ + { + "method": "GET", + "summary": "Greet our subject with hello!", + "type": "string", + "nickname": "helloSubject", + "parameters": [ + { + "name": "subject", + "description": "The subject to be greeted.", + "required": true, + "type": "string", + "paramType": "path" + } + ] + } + ] + } + ] +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/description/src/test/resources/swagger20.json ---------------------------------------------------------------------- diff --git a/rt/rs/description/src/test/resources/swagger20.json b/rt/rs/description/src/test/resources/swagger20.json new file mode 100644 index 0000000..44e7a32 --- /dev/null +++ b/rt/rs/description/src/test/resources/swagger20.json @@ -0,0 +1,31 @@ +{ + "swagger": "2.0", + "basePath": "/base", + "paths": + { + "/somepath": + { + "post": { + "operationId": "postOp", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "formData", + "name": "userName", + "type": "string" + }, + { + "in": "formData", + "name": "password", + "type": "string" + } + ] + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/pom.xml ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/pom.xml b/rt/rs/extensions/providers/pom.xml index 1d67039..1323bcb 100644 --- a/rt/rs/extensions/providers/pom.xml +++ b/rt/rs/extensions/providers/pom.xml @@ -131,12 +131,6 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-service-description</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <scope>provided</scope> http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/json/JsonMapObjectReaderWriter.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/json/JsonMapObjectReaderWriter.java b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/json/JsonMapObjectReaderWriter.java index 20e0777..c10eaeb 100644 --- a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/json/JsonMapObjectReaderWriter.java +++ b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/json/JsonMapObjectReaderWriter.java @@ -225,7 +225,7 @@ public class JsonMapObjectReaderWriter { int nextOpenIndex = json.indexOf(openChar, from + 1); int closingIndex = json.indexOf(closeChar, from + 1); while (nextOpenIndex != -1 && nextOpenIndex < closingIndex) { - nextOpenIndex = json.indexOf(openChar, closingIndex + 1); + nextOpenIndex = json.indexOf(openChar, nextOpenIndex + 1); closingIndex = json.indexOf(closeChar, closingIndex + 1); } return closingIndex; http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryAllTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryAllTest.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryAllTest.java index d513d3c..9b78eb6 100644 --- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryAllTest.java +++ b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryAllTest.java @@ -26,7 +26,7 @@ import javax.ws.rs.ext.MessageBodyWriter; import org.apache.cxf.jaxrs.provider.atom.AtomPojoProvider; import org.apache.cxf.jaxrs.provider.json.JSONProvider; import org.apache.cxf.jaxrs.resources.Book; -import org.apache.cxf.jaxrs.resources.Chapter; +import org.apache.cxf.jaxrs.resources.TagVO; import org.apache.cxf.message.MessageImpl; import org.junit.Assert; @@ -51,8 +51,8 @@ public class ProviderFactoryAllTest extends Assert { new MessageImpl()); assertSame(feedReader, provider); - MessageBodyReader<?> entryReader = pf.createMessageBodyReader(Chapter.class, - Chapter.class, null, + MessageBodyReader<?> entryReader = pf.createMessageBodyReader(TagVO.class, + TagVO.class, null, MediaType.valueOf("application/atom+xml;type=entry"), new MessageImpl()); assertSame(entryReader, provider); http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/WadlGeneratorTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/WadlGeneratorTest.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/WadlGeneratorTest.java deleted file mode 100644 index 7d37f39..0000000 --- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/json/WadlGeneratorTest.java +++ /dev/null @@ -1,138 +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 - * - * 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.provider.json; - -import java.io.ByteArrayOutputStream; -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.w3c.dom.Document; - -import org.apache.cxf.endpoint.Endpoint; -import org.apache.cxf.endpoint.EndpointImpl; -import org.apache.cxf.jaxrs.JAXRSServiceImpl; -import org.apache.cxf.jaxrs.impl.ContainerRequestContextImpl; -import org.apache.cxf.jaxrs.impl.MetadataMap; -import org.apache.cxf.jaxrs.model.ClassResourceInfo; -import org.apache.cxf.jaxrs.model.wadl.WadlGenerator; -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.ExchangeImpl; -import org.apache.cxf.message.Message; -import org.apache.cxf.message.MessageImpl; -import org.apache.cxf.service.Service; -import org.apache.cxf.service.model.BindingInfo; -import org.apache.cxf.service.model.EndpointInfo; -import org.apache.cxf.transport.servlet.ServletDestination; -import org.easymock.EasyMock; -import org.easymock.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 testWadlInJsonFormat() throws Exception { - ClassResourceInfo cri = - ResourceUtils.createClassResourceInfo(BookStore.class, BookStore.class, true, true); - final Message m = mockMessage("http://localhost:8080/baz", "/bookstore/1", WadlGenerator.WADL_QUERY, cri); - Map<String, List<String>> headers = new HashMap<String, List<String>>(); - headers.put("Accept", Collections.singletonList("application/json")); - m.put(Message.PROTOCOL_HEADERS, headers); - - WadlGenerator wg = new WadlGenerator() { - public void filter(ContainerRequestContext context) { - super.doFilter(context, m); - } - }; - wg.setUseJaxbContextForQnames(false); - wg.setIgnoreMessageWriters(false); - wg.setExternalLinks(Collections.singletonList("json.schema")); - - Response r = handleRequest(wg, m); - assertEquals("application/json", - r.getMetadata().getFirst("Content-Type").toString()); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - new JSONProvider<Document>().writeTo( - (Document)r.getEntity(), Document.class, Document.class, - new Annotation[]{}, MediaType.APPLICATION_JSON_TYPE, - new MetadataMap<String, Object>(), os); - String s = os.toString(); - String expected1 = - "{\"application\":{\"grammars\":{\"include\":{\"@href\":\"http://localhost:8080/baz" - + "/json.schema\"}},\"resources\":{\"@base\":\"http://localhost:8080/baz\"," - + "\"resource\":{\"@path\":\"/bookstore/{id}\""; - assertTrue(s.startsWith(expected1)); - String expected2 = - "\"response\":{\"representation\":[{\"@mediaType\":\"application/xml\"}," - + "{\"@element\":\"Chapter\",\"@mediaType\":\"application/json\"}]}"; - assertTrue(s.contains(expected2)); - } - private Response handleRequest(WadlGenerator wg, Message m) { - wg.filter(new ContainerRequestContextImpl(m, true, false)); - return m.getExchange().get(Response.class); - } - private Message mockMessage(String baseAddress, String pathInfo, String query, - ClassResourceInfo cri) throws Exception { - Message m = new MessageImpl(); - Exchange e = new ExchangeImpl(); - e.put(Service.class, new JAXRSServiceImpl(Collections.singletonList(cri))); - m.setExchange(e); - control.reset(); - ServletDestination d = control.createMock(ServletDestination.class); - EndpointInfo epr = new EndpointInfo(); - epr.setAddress(baseAddress); - d.getEndpointInfo(); - EasyMock.expectLastCall().andReturn(epr).anyTimes(); - - Endpoint endpoint = new EndpointImpl(null, null, epr); - e.put(Endpoint.class, endpoint); - - e.setDestination(d); - BindingInfo bi = control.createMock(BindingInfo.class); - epr.setBinding(bi); - bi.getProperties(); - EasyMock.expectLastCall().andReturn(Collections.emptyMap()).anyTimes(); - m.put(Message.REQUEST_URI, pathInfo); - m.put(Message.QUERY_STRING, query); - m.put(Message.HTTP_REQUEST_METHOD, "GET"); - control.replay(); - return m; - } -} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/BookStore.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/BookStore.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/BookStore.java deleted file mode 100644 index a5bdd95..0000000 --- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/BookStore.java +++ /dev/null @@ -1,37 +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 - * - * 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.resources; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; - -@Path("/bookstore/{id}") -@Consumes({"application/xml", "application/json" }) -@Produces({"application/xml", "application/json" }) -public class BookStore { - - @GET - @Path("chapter") - public Chapter getChapter() { - return new Chapter(1); - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/Chapter.java ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/Chapter.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/Chapter.java deleted file mode 100644 index 58290a2..0000000 --- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/resources/Chapter.java +++ /dev/null @@ -1,59 +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 - * - * 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.resources; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -import org.apache.cxf.jaxrs.ext.xml.XMLName; -import org.apache.cxf.jaxrs.model.wadl.Description; - -@XmlRootElement(name = "thechapter", namespace = "http://superbooks") -@XmlType(name = "chapter", namespace = "http://superbooks") -@Description("Chapter subresource") -@XMLName(value = "{http://books}thesuperchapter") -public class Chapter { - - private int id; - public Chapter() { - } - public Chapter(int id) { - this.id = id; - } - - @GET - @Path("/id") - @Produces({"application/xml", "application/json" }) - @Description("Get the chapter") - public Chapter getIt() { - return this; - } - - public void setId(int ident) { - id = ident; - } - - public int getId() { - return id; - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/rt/rs/extensions/providers/src/test/resources/json.schema ---------------------------------------------------------------------- diff --git a/rt/rs/extensions/providers/src/test/resources/json.schema b/rt/rs/extensions/providers/src/test/resources/json.schema deleted file mode 100644 index 7199661..0000000 --- a/rt/rs/extensions/providers/src/test/resources/json.schema +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name":"Book", - "properties":{ - "id":{ - "type":"number", - "description":"Product identifier", - "required":true - }, - "name":{ - "description":"Name of the product", - "type":"string", - "required":true - }, - "price":{ - "required":true, - "type": "number", - "minimum":0, - "required":true - }, - "tags":{ - "type":"array", - "items":{ - "type":"string" - } - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerUserResourceDefaultTest.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerUserResourceDefaultTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerUserResourceDefaultTest.java index 8801b93..c56ee4b 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerUserResourceDefaultTest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerUserResourceDefaultTest.java @@ -86,7 +86,9 @@ public class JAXRSClientServerUserResourceDefaultTest extends AbstractBusClientS op.setPath("/books/{id}"); op.setName("getBook"); op.setVerb("GET"); - op.setParameters(Collections.singletonList(new Parameter(ParameterType.PATH, "id"))); + Parameter param = new Parameter(ParameterType.PATH, "id"); + param.setJavaType(Long.class); + op.setParameters(Collections.singletonList(param)); UserOperation op2 = new UserOperation(); op2.setPath("echobook"); @@ -226,7 +228,7 @@ public class JAXRSClientServerUserResourceDefaultTest extends AbstractBusClientS List<Object> params = CastUtils.cast((List<?>)request); String path = mc.getUriInfo().getPath(); if ("default/books/999".equals(path)) { - Long bookId = Long.valueOf(params.get(0).toString()); + Long bookId = (Long)params.get(0); Book book = new Book("CXF in Action", bookId); Response r = Response.ok(book, mc.getHttpHeaders().getAcceptableMediaTypes().get(0)).build(); http://git-wip-us.apache.org/repos/asf/cxf/blob/992e3d60/tools/wadlto/jaxrs/src/main/java/org/apache/cxf/tools/wadlto/jaxrs/SourceGenerator.java ---------------------------------------------------------------------- diff --git a/tools/wadlto/jaxrs/src/main/java/org/apache/cxf/tools/wadlto/jaxrs/SourceGenerator.java b/tools/wadlto/jaxrs/src/main/java/org/apache/cxf/tools/wadlto/jaxrs/SourceGenerator.java index a584ec1..44aeda4 100644 --- a/tools/wadlto/jaxrs/src/main/java/org/apache/cxf/tools/wadlto/jaxrs/SourceGenerator.java +++ b/tools/wadlto/jaxrs/src/main/java/org/apache/cxf/tools/wadlto/jaxrs/SourceGenerator.java @@ -169,7 +169,7 @@ public class SourceGenerator { XSD_SPECIFIC_TYPE_MAP.put("string", "String"); XSD_SPECIFIC_TYPE_MAP.put("integer", "long"); XSD_SPECIFIC_TYPE_MAP.put("float", "float"); - XSD_SPECIFIC_TYPE_MAP.put("doable", "doable"); + XSD_SPECIFIC_TYPE_MAP.put("double", "double"); XSD_SPECIFIC_TYPE_MAP.put("int", "int"); XSD_SPECIFIC_TYPE_MAP.put("long", "long"); XSD_SPECIFIC_TYPE_MAP.put("byte", "byte");
