cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject cxf git commit: [CXF-6633] Optionally enriching Swagger output with JavaDocs content and optimizing a service tree, patch from Francesco Chicchiriccò applied with thanks, This closes #96
Date Fri, 09 Oct 2015 13:24:30 GMT
Repository: cxf
Updated Branches:
  refs/heads/master 22a683b82 -> 08fbde3d6


[CXF-6633] Optionally enriching Swagger output with JavaDocs content and optimizing a service
tree, patch from Francesco Chicchiriccò applied with thanks, This closes #96


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/08fbde3d
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/08fbde3d
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/08fbde3d

Branch: refs/heads/master
Commit: 08fbde3d6175081304f6df79487985f17160481a
Parents: 22a683b
Author: Sergey Beryozkin <sberyozkin@gmail.com>
Authored: Fri Oct 9 14:24:08 2015 +0100
Committer: Sergey Beryozkin <sberyozkin@gmail.com>
Committed: Fri Oct 9 14:24:08 2015 +0100

----------------------------------------------------------------------
 .../cxf/jaxrs/swagger/Swagger2Feature.java      |  60 +++++--
 .../cxf/jaxrs/swagger/Swagger2Serializers.java  | 157 +++++++++++++++++++
 2 files changed, 202 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/08fbde3d/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
----------------------------------------------------------------------
diff --git a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
index 7a68622..f335eec 100644
--- a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
+++ b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Feature.java
@@ -21,6 +21,7 @@ package org.apache.cxf.jaxrs.swagger;
 import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -33,11 +34,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.cxf.BusFactory;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.endpoint.Server;
 import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.doc.DocumentationProvider;
+import org.apache.cxf.jaxrs.model.doc.JavaDocProvider;
 import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
 
@@ -45,40 +49,51 @@ import io.swagger.jaxrs.config.BeanConfig;
 import io.swagger.jaxrs.config.DefaultReaderConfig;
 import io.swagger.jaxrs.config.ReaderConfig;
 import io.swagger.jaxrs.listing.ApiListingResource;
-import io.swagger.jaxrs.listing.SwaggerSerializers;
 
 public class Swagger2Feature extends AbstractSwaggerFeature {
+
     private String host;
+
     private String[] schemes;
+
     private boolean prettyPrint;
 
     private boolean scanAllResources;
+
     private String ignoreRoutes;
 
+    private boolean dynamicBasePath;
+
+    private boolean replaceTags;
+
+    private DocumentationProvider javadocProvider;
+
     @Override
     protected void addSwaggerResource(Server server) {
+        List<ClassResourceInfo> cris = Collections.emptyList();
         if (!runAsFilter) {
-            List<Object> serviceBeans = new ArrayList<Object>();
+            List<Object> serviceBeans = new ArrayList<>();
             ApiListingResource apiListingResource = new ApiListingResource();
             serviceBeans.add(apiListingResource);
-            JAXRSServiceFactoryBean sfb = 
-                (JAXRSServiceFactoryBean)server.getEndpoint().get(JAXRSServiceFactoryBean.class.getName());
+            JAXRSServiceFactoryBean sfb =
+                    (JAXRSServiceFactoryBean) server.getEndpoint().get(JAXRSServiceFactoryBean.class.getName());
             sfb.setResourceClassesFromBeans(serviceBeans);
-            for (ClassResourceInfo cri : sfb.getClassResourceInfo()) {
+            cris = sfb.getClassResourceInfo();
+            for (ClassResourceInfo cri : cris) {
                 if (ApiListingResource.class == cri.getResourceClass()) {
                     InjectionUtils.injectContextProxiesAndApplication(cri, apiListingResource,
null);
                 }
             }
         }
-        List<Object> providers = new ArrayList<Object>();
+        List<Object> providers = new ArrayList<>();
         if (runAsFilter) {
             providers.add(new SwaggerContainerRequestFilter());
         }
-        providers.add(new SwaggerSerializers());
+        providers.add(new Swagger2Serializers(dynamicBasePath, replaceTags, javadocProvider,
cris));
         providers.add(new ReaderConfigFilter());
-        ((ServerProviderFactory)server.getEndpoint().get(
+        ((ServerProviderFactory) server.getEndpoint().get(
                 ServerProviderFactory.class.getName())).setUserProviders(providers);
-        
+
         BeanConfig beanConfig = new BeanConfig();
         beanConfig.setResourcePackage(getResourcePackage());
         beanConfig.setVersion(getVersion());
@@ -99,6 +114,7 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
     public String getHost() {
         return host;
     }
+
     public void setHost(String host) {
         this.host = host;
     }
@@ -135,11 +151,23 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
         this.ignoreRoutes = ignoreRoutes;
     }
 
+    public void setDynamicBasePath(final boolean dynamicBasePath) {
+        this.dynamicBasePath = dynamicBasePath;
+    }
+
+    public void setReplaceTags(final boolean replaceTags) {
+        this.replaceTags = replaceTags;
+    }
+
+    public void setJavaDocPath(final String javaDocPath) throws Exception {
+        this.javadocProvider = new JavaDocProvider(BusFactory.getDefaultBus(), javaDocPath);
+    }
+
     @Override
     protected void setBasePathByAddress(String address) {
         if (!address.startsWith("/")) {
             // get the path part
-            URI u = URI.create(address); 
+            URI u = URI.create(address);
             setBasePath(u.getPath());
             setHost(u.getPort() < 0 ? u.getHost() : u.getHost() + ":" + u.getPort());
         } else {
@@ -147,12 +175,13 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
         }
     }
 
-
     @PreMatching
     private static class SwaggerContainerRequestFilter extends ApiListingResource implements
ContainerRequestFilter {
+
         private static final String APIDOCS_LISTING_PATH_JSON = "swagger.json";
+
         private static final String APIDOCS_LISTING_PATH_YAML = "swagger.yaml";
-        
+
         @Context
         private MessageContext mc;
 
@@ -163,13 +192,14 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
                 Response r = getListingJson(null, mc.getServletConfig(), mc.getHttpHeaders(),
ui);
                 requestContext.abortWith(r);
             } else if (ui.getPath().endsWith(APIDOCS_LISTING_PATH_YAML)) {
-                Response r = getListingYaml(null, mc.getServletConfig(), mc.getHttpHeaders(),
ui); 
+                Response r = getListingYaml(null, mc.getServletConfig(), mc.getHttpHeaders(),
ui);
                 requestContext.abortWith(r);
             }
         }
     }
 
     private class ReaderConfigFilter implements ContainerRequestFilter {
+
         @Context
         private MessageContext mc;
 
@@ -178,7 +208,7 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
             ServletContext servletContext = mc.getServletContext();
             if (servletContext != null && servletContext.getAttribute(ReaderConfig.class.getName())
== null) {
                 if (mc.getServletConfig() != null
-                    && Boolean.valueOf(mc.getServletConfig().getInitParameter("scan.all.resources")))
{
+                        && Boolean.valueOf(mc.getServletConfig().getInitParameter("scan.all.resources")))
{
                     addReaderConfig(mc.getServletConfig().getInitParameter("ignore.routes"));
                 } else if (isScanAllResources()) {
                     addReaderConfig(getIgnoreRoutes());
@@ -190,7 +220,7 @@ public class Swagger2Feature extends AbstractSwaggerFeature {
             DefaultReaderConfig rc = new DefaultReaderConfig();
             rc.setScanAllResources(true);
             if (ignoreRoutesParam != null) {
-                Set<String> routes = new LinkedHashSet<String>();
+                Set<String> routes = new LinkedHashSet<>();
                 for (String route : StringUtils.split(ignoreRoutesParam, ",")) {
                     routes.add(route.trim());
                 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/08fbde3d/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Serializers.java
----------------------------------------------------------------------
diff --git a/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Serializers.java
b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Serializers.java
new file mode 100644
index 0000000..83ef3dc
--- /dev/null
+++ b/rt/rs/description/src/main/java/org/apache/cxf/jaxrs/swagger/Swagger2Serializers.java
@@ -0,0 +1,157 @@
+/**
+ * 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.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.model.doc.DocumentationProvider;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+
+import io.swagger.jaxrs.listing.SwaggerSerializers;
+import io.swagger.models.HttpMethod;
+import io.swagger.models.Operation;
+import io.swagger.models.Path;
+import io.swagger.models.Swagger;
+import io.swagger.models.Tag;
+
+public class Swagger2Serializers extends SwaggerSerializers {
+
+    private final boolean dynamicBasePath;
+
+    private final boolean replaceTags;
+
+    private final DocumentationProvider javadocProvider;
+
+    private final List<ClassResourceInfo> cris;
+
+    public Swagger2Serializers(
+            final boolean dynamicBasePath,
+            final boolean replaceTags,
+            final DocumentationProvider javadocProvider,
+            final List<ClassResourceInfo> cris) {
+
+        super();
+
+        this.dynamicBasePath = dynamicBasePath;
+        this.replaceTags = replaceTags;
+        this.javadocProvider = javadocProvider;
+        this.cris = cris;
+    }
+
+    @Override
+    public void writeTo(
+            final Swagger data,
+            final Class<?> type,
+            final Type genericType,
+            final Annotation[] annotations,
+            final MediaType mediaType,
+            final MultivaluedMap<String, Object> headers,
+            final OutputStream out) throws IOException {
+
+        if (dynamicBasePath) {
+            MessageContext ctx = JAXRSUtils.createContextValue(
+                    JAXRSUtils.getCurrentMessage(), null, MessageContext.class);
+            data.setBasePath(StringUtils.substringBeforeLast(ctx.getHttpServletRequest().getRequestURI(),
"/"));
+        }
+
+        if (replaceTags || javadocProvider != null) {
+            Map<String, ClassResourceInfo> operations = new HashMap<>();
+            Map<Pair<String, String>, OperationResourceInfo> methods = new HashMap<>();
+            for (ClassResourceInfo cri : cris) {
+                for (OperationResourceInfo ori : cri.getMethodDispatcher().getOperationResourceInfos())
{
+                    StringBuilder fullPath = new StringBuilder().
+                            append(cri.getURITemplate().getValue()).
+                            append(ori.getURITemplate().getValue());
+                    if (fullPath.charAt(fullPath.length() - 1) == '/') {
+                        fullPath.setLength(fullPath.length() - 1);
+                    }
+                    // Adapt to Swagger's path expression
+                    if (fullPath.toString().endsWith(":.*}")) {
+                        fullPath.setLength(fullPath.length() - 4);
+                        fullPath.append('}');
+                    }
+
+                    operations.put(fullPath.toString(), cri);
+                    methods.put(ImmutablePair.of(ori.getHttpMethod(), fullPath.toString()),
ori);
+                }
+            }
+
+            if (replaceTags && data.getTags() != null) {
+                data.getTags().clear();
+            }
+            for (final Map.Entry<String, Path> entry : data.getPaths().entrySet())
{
+                Tag tag = null;
+                if (replaceTags && operations.containsKey(entry.getKey())) {
+                    ClassResourceInfo cri = operations.get(entry.getKey());
+
+                    tag = new Tag();
+                    tag.setName(cri.getURITemplate().getValue());
+                    if (javadocProvider != null) {
+                        tag.setDescription(javadocProvider.getClassDoc(cri));
+                    }
+
+                    data.addTag(tag);
+                }
+
+                for (Map.Entry<HttpMethod, Operation> subentry : entry.getValue().getOperationMap().entrySet())
{
+                    if (replaceTags && tag != null) {
+                        subentry.getValue().setTags(Collections.singletonList(tag.getName()));
+                    }
+
+                    Pair<String, String> key = ImmutablePair.of(subentry.getKey().name(),
entry.getKey());
+                    if (methods.containsKey(key) && javadocProvider != null) {
+                        OperationResourceInfo ori = methods.get(key);
+
+                        subentry.getValue().setSummary(javadocProvider.getMethodDoc(ori));
+                        for (int i = 0; i < subentry.getValue().getParameters().size();
i++) {
+                            subentry.getValue().getParameters().get(i).
+                                    setDescription(javadocProvider.getMethodParameterDoc(ori,
i));
+                        }
+
+                        if (subentry.getValue().getResponses() != null
+                                && !subentry.getValue().getResponses().isEmpty())
{
+
+                            subentry.getValue().getResponses().entrySet().iterator().next().getValue().
+                                    setDescription(javadocProvider.getMethodResponseDoc(ori));
+                        }
+                    }
+                }
+            }
+        }
+
+        super.writeTo(data, type, genericType, annotations, mediaType, headers, out);
+    }
+}


Mime
View raw message