cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject [cxf] branch master updated: CXF-7525: Add support for Swagger 2.0 (OpenApi Spec 3.0). Initial integration implementation. Adding configLocation support and property file support (swagger.properties).
Date Thu, 28 Dec 2017 21:03:45 GMT
This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new b386fe5  CXF-7525: Add support for Swagger 2.0 (OpenApi Spec 3.0). Initial integration
implementation. Adding configLocation support and property file support (swagger.properties).
b386fe5 is described below

commit b386fe55ffbd27b4d5fa8d6d5a78ef910cdb01ec
Author: reta <drreta@gmail.com>
AuthorDate: Thu Dec 28 16:02:33 2017 -0500

    CXF-7525: Add support for Swagger 2.0 (OpenApi Spec 3.0). Initial integration implementation.
Adding configLocation support and property file support (swagger.properties).
---
 .../apache/cxf/jaxrs/openapi/OpenApiFeature.java   | 210 ++++++++++++++++-----
 .../cxf/jaxrs/openapi/SwaggerProperties.java       |  69 +++++++
 2 files changed, 233 insertions(+), 46 deletions(-)

diff --git a/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/OpenApiFeature.java
b/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/OpenApiFeature.java
index 7a8384d..622a601 100644
--- a/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/OpenApiFeature.java
+++ b/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/OpenApiFeature.java
@@ -20,6 +20,7 @@ package org.apache.cxf.jaxrs.openapi;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Properties;
@@ -32,6 +33,8 @@ import org.apache.cxf.Bus;
 import org.apache.cxf.annotations.Provider;
 import org.apache.cxf.annotations.Provider.Scope;
 import org.apache.cxf.annotations.Provider.Type;
+import org.apache.cxf.common.util.PropertyUtils;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.endpoint.Server;
 import org.apache.cxf.feature.AbstractFeature;
 import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
@@ -46,13 +49,18 @@ import io.swagger.v3.oas.integration.GenericOpenApiContextBuilder;
 import io.swagger.v3.oas.integration.OpenApiConfigurationException;
 import io.swagger.v3.oas.integration.SwaggerConfiguration;
 import io.swagger.v3.oas.integration.api.OpenAPIConfiguration;
+import io.swagger.v3.oas.integration.api.OpenApiContext;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.info.Contact;
 import io.swagger.v3.oas.models.info.Info;
 import io.swagger.v3.oas.models.info.License;
 
 @Provider(value = Type.Feature, scope = Scope.Server)
-public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport {
+public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, SwaggerProperties
{
+    private static final String DEFAULT_PROPS_LOCATION = "/swagger.properties";
+    private static final String DEFAULT_LICENSE_VALUE = "Apache 2.0 License";
+    private static final String DEFAULT_LICENSE_URL = "http://www.apache.org/licenses/LICENSE-2.0.html";
+    
     private String version;
     private String title;
     private String description;
@@ -78,6 +86,12 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
     private String swaggerUiMavenGroupAndArtifact;
     private Map<String, String> swaggerUiMediaTypes;
 
+    // Allows to pass the configuration location, usually openapi-configuration.json
+    // or openapi-configuration.yml file.
+    private String configLocation;
+    // Allows to pass the properties location, by default swagger.properties
+    private String propertiesLocation = DEFAULT_PROPS_LOCATION;
+
     protected static class DefaultApplication extends Application {
         private final Set<Class<?>> serviceClasses;
         
@@ -100,34 +114,50 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
             .getEndpoint()
             .get(ServerProviderFactory.class.getName());
 
-        final OpenAPI oas = new OpenAPI().info(getInfo());
-        
-        if (isScan()) {
-            resourcePackages = merge(resourcePackages, scanResourcePackages(sfb));
+        final Set<String> packages = new HashSet<>();
+        if (resourcePackages != null) {
+            packages.addAll(resourcePackages);
         }
+
+        Properties swaggerProps = null;
+        GenericOpenApiContextBuilder<?> openApiConfiguration = null; 
+        if (StringUtils.isEmpty(getConfigLocation())) {
+            swaggerProps = getSwaggerProperties(propertiesLocation, bus);
+            
+            if (isScan()) {
+                packages.addAll(scanResourcePackages(sfb));
+            }
         
-        // Read configuration from properties first (openapi-configuration.json)
-        final SwaggerConfiguration config = new SwaggerConfiguration()
-            .openAPI(oas)
-            .prettyPrint(isPrettyPrint())
-            .readAllResources(isReadAllResources())
-            .ignoredRoutes(getIgnoredRoutes())
-            .filterClass(filterClass)
-            .resourceClasses(getResourceClasses())
-            .resourcePackages(resourcePackages);
-
-        final GenericOpenApiContextBuilder<?> openApiConfiguration = new JaxrsOpenApiContextBuilder<>()
-            .application(getApplicationOrDefault(server, factory, sfb, bus))
-            .openApiConfiguration(config);
+            final OpenAPI oas = new OpenAPI().info(getInfo(swaggerProps));
+            final SwaggerConfiguration config = new SwaggerConfiguration()
+                .openAPI(oas)
+                .prettyPrint(getOrFallback(isPrettyPrint(), swaggerProps, PRETTY_PRINT_PROPERTY))
+                .readAllResources(isReadAllResources())
+                .ignoredRoutes(getIgnoredRoutes())
+                .filterClass(getOrFallback(getFilterClass(), swaggerProps, FILTER_CLASS_PROPERTY))
+                .resourceClasses(getResourceClasses())
+                .resourcePackages(getOrFallback(packages, swaggerProps, RESOURCE_PACKAGE_PROPERTY));
+
+            openApiConfiguration = new JaxrsOpenApiContextBuilder<>()
+                .application(getApplicationOrDefault(server, factory, sfb, bus))
+                .openApiConfiguration(config);
+        } else {
+            openApiConfiguration = new JaxrsOpenApiContextBuilder<>()
+                .application(getApplicationOrDefault(server, factory, sfb, bus))
+                .configLocation(getConfigLocation());
+        }
 
         try {
-            openApiConfiguration.buildContext(true);
+            final OpenApiContext context = openApiConfiguration.buildContext(true);
+            final Properties userProperties = getUserProperties(
+                context
+                    .getOpenApiConfiguration()
+                    .getUserDefinedOptions());
+            registerOpenApiResources(sfb, packages, context.getOpenApiConfiguration());
+            registerSwaggerUiResources(sfb, combine(swaggerProps, userProperties), factory,
bus);
         } catch (OpenApiConfigurationException ex) {
             throw new RuntimeException("Unable to initialize OpenAPI context", ex);
         }
-        
-        registerOpenApiResources(sfb, config);
-        registerSwaggerUiResources(sfb, factory, bus);
     }
 
     public boolean isScan() {
@@ -295,19 +325,55 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
     public void setSwaggerUiMediaTypes(Map<String, String> swaggerUiMediaTypes) {
         this.swaggerUiMediaTypes = swaggerUiMediaTypes;
     }
-    
+
+    public String getConfigLocation() {
+        return configLocation;
+    }
+
+    public void setConfigLocation(String configLocation) {
+        this.configLocation = configLocation;
+    }
+
+    public String getPropertiesLocation() {
+        return propertiesLocation;
+    }
+
+    public void setPropertiesLocation(String propertiesLocation) {
+        this.propertiesLocation = propertiesLocation;
+    }
+
     @Override
     public String findSwaggerUiRoot() {
         return SwaggerUi.findSwaggerUiRoot(swaggerUiMavenGroupAndArtifact, swaggerUiVersion);
     }
+    
+    protected Properties getUserProperties(final Map<String, Object> userDefinedOptions)
{
+        final Properties properties = new Properties();
+        
+        if (userDefinedOptions != null) {
+            userDefinedOptions
+                .entrySet()
+                .stream()
+                .filter(entry -> entry.getValue() != null)
+                .forEach(entry -> properties.setProperty(entry.getKey(), entry.getValue().toString()));
+        }
+        
+        return properties;
+    }
 
-    protected void registerOpenApiResources(JAXRSServiceFactoryBean sfb, OpenAPIConfiguration
config) {
-        sfb.setResourceClassesFromBeans(Arrays.asList(new OpenApiResource().openApiConfiguration(config)));
+    protected void registerOpenApiResources(JAXRSServiceFactoryBean sfb, Set<String>
packages, 
+            OpenAPIConfiguration config) {
+        sfb.setResourceClassesFromBeans(Arrays.asList(
+            new OpenApiResource()
+                .openApiConfiguration(config)
+                .configLocation(configLocation)
+                .resourcePackages(packages)));
     }
 
-    protected void registerSwaggerUiResources(JAXRSServiceFactoryBean sfb, ServerProviderFactory
factory, Bus bus) {
-        final Properties swaggerProps = getSwaggerProperties(bus);
-        final Registration swaggerUiRegistration = getSwaggerUi(bus, swaggerProps, isRunAsFilter());
+    protected void registerSwaggerUiResources(JAXRSServiceFactoryBean sfb, Properties properties,

+            ServerProviderFactory factory, Bus bus) {
+        
+        final Registration swaggerUiRegistration = getSwaggerUi(bus, properties, isRunAsFilter());
         
         if (!isRunAsFilter()) {
             sfb.setResourceClassesFromBeans(swaggerUiRegistration.getResources());
@@ -316,11 +382,6 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
         factory.setUserProviders(swaggerUiRegistration.getProviders());
     }
 
-    protected Properties getSwaggerProperties(Bus bus) {
-        // TODO: Read from OpenAPI properties
-        return new Properties();
-    }
-
     /**
      * Detects the application (if present) or creates the default application (in case the
      * scan is disabled)
@@ -348,21 +409,63 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
     /**
      * The info will be used only if there is no @OpenAPIDefinition annotation is present.

      */
-    private Info getInfo() {
-        return new Info()
-            .title(getTitle())
-            .version(getVersion())
-            .description(getDescription())
-            .termsOfService(getTermsOfServiceUrl())
+    private Info getInfo(final Properties properties) {
+        final Info info = new Info()
+            .title(getOrFallback(getTitle(), properties, TITLE_PROPERTY))
+            .version(getOrFallback(getVersion(), properties, VERSION_PROPERTY))
+            .description(getOrFallback(getDescription(), properties, DESCRIPTION_PROPERTY))
+            .termsOfService(getOrFallback(getTermsOfServiceUrl(), properties, TERMS_URL_PROPERTY))
             .contact(new Contact()
-                .name(getContactName())
+                .name(getOrFallback(getContactName(), properties, CONTACT_PROPERTY))
                 .email(getContactEmail())
                 .url(getContactUrl()))
             .license(new License()
-                .name(getLicense())
-                .url(getLicenseUrl()));
+                .name(getOrFallback(getLicense(), properties, LICENSE_PROPERTY))
+                .url(getOrFallback(getLicenseUrl(), properties, LICENSE_URL_PROPERTY)));
+        
+        if (info.getLicense().getName() == null) {
+            info.getLicense().setName(DEFAULT_LICENSE_VALUE);
+        }
+        
+        if (info.getLicense().getUrl() == null && DEFAULT_LICENSE_VALUE.equals(info.getLicense().getName()))
{
+            info.getLicense().setUrl(DEFAULT_LICENSE_URL);
+        }
+        
+        return info;
     }
+
+    private String getOrFallback(String value, Properties properties, String property) {
+        if (value == null && properties != null) {
+            return properties.getProperty(property);
+        } else {
+            return value;
+        }
+    }
+
+    private Boolean getOrFallback(Boolean value, Properties properties, String property)
{
+        Boolean fallback = value;
+        if (value == null && properties != null) {
+            fallback = PropertyUtils.isTrue(properties.get(PRETTY_PRINT_PROPERTY));
+        }
+        
+        if (fallback == null) {
+            return false;
+        }
         
+        return fallback;
+    }
+    
+    private Set<String> getOrFallback(Set<String> collection, Properties properties,
String property) {
+        if (collection.isEmpty() && properties != null) {
+            final String value = properties.getProperty(property);
+            if (!StringUtils.isEmpty(value)) {
+                collection.add(value);
+            }
+        } 
+
+        return collection;
+    }
+
     private Collection<String> scanResourcePackages(JAXRSServiceFactoryBean sfb) {
         return sfb
             .getClassResourceInfo()
@@ -371,9 +474,24 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport
             .collect(Collectors.toSet());
     }
     
-    private Set<String> merge(Set<String> destination, Collection<String>
source) {
-        final Set<String> dst = (destination == null) ? new HashSet<>() : destination;
-        dst.addAll(source);
-        return dst;
+    private static Properties combine(final Properties primary, final Properties secondary)
{
+        if (primary == null) {
+            return secondary;
+        } else if (secondary == null) {
+            return primary;
+        } else {
+            final Properties combined = new Properties();
+            setOrReplace(secondary, combined);
+            setOrReplace(primary, combined);
+            return combined;
+        }
+    }
+
+    private static void setOrReplace(final Properties source, final Properties destination)
{
+        final Enumeration<?> enumeration = source.propertyNames();
+        while (enumeration.hasMoreElements()) {
+            final String name = (String)enumeration.nextElement(); 
+            destination.setProperty(name, source.getProperty(name));
+        }
     }
 }
diff --git a/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/SwaggerProperties.java
b/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/SwaggerProperties.java
new file mode 100644
index 0000000..3cca3cf
--- /dev/null
+++ b/rt/rs/description-openapi-v3/src/main/java/org/apache/cxf/jaxrs/openapi/SwaggerProperties.java
@@ -0,0 +1,69 @@
+/**
+ * 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.openapi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
+
+interface SwaggerProperties {
+    String RESOURCE_PACKAGE_PROPERTY = "resource.package";
+    String TITLE_PROPERTY = "title";
+    String VERSION_PROPERTY = "version";
+    String DESCRIPTION_PROPERTY = "description";
+    String CONTACT_PROPERTY = "contact";
+    String LICENSE_PROPERTY = "license";
+    String LICENSE_URL_PROPERTY = "license.url";
+    String TERMS_URL_PROPERTY = "terms.url";
+    String PRETTY_PRINT_PROPERTY = "pretty.print";
+    String FILTER_CLASS_PROPERTY = "filter.class";
+    
+    /**
+     * Read the Swagger-specific properties from the property file (to seamlessly
+     * support the migration from older Swagger features).
+     * @param location property file location
+     * @param bus bus instance
+     * @return the properties if available 
+     */
+    default Properties getSwaggerProperties(String location, Bus bus) {
+        InputStream is = ResourceUtils.getClasspathResourceStream(location, SwaggerProperties.class,
bus);
+        Properties props = null;
+        
+        if (is != null) {
+            props = new Properties();
+            try {
+                props.load(is);
+            } catch (IOException ex) {
+                props = null;
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ignore) {
+                    // ignore
+                }
+            }
+        }
+
+        return props;
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <commits@cxf.apache.org>'].

Mime
View raw message