Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 59234200B6F for ; Wed, 24 Aug 2016 13:11:00 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5600D160AC1; Wed, 24 Aug 2016 11:10:55 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 02922160AA4 for ; Wed, 24 Aug 2016 13:10:53 +0200 (CEST) Received: (qmail 96465 invoked by uid 500); 24 Aug 2016 11:10:43 -0000 Mailing-List: contact commits-help@syncope.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@syncope.apache.org Delivered-To: mailing list commits@syncope.apache.org Received: (qmail 96456 invoked by uid 99); 24 Aug 2016 11:10:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Aug 2016 11:10:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 19718E0BD9; Wed, 24 Aug 2016 11:10:43 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: ilgrosso@apache.org To: commits@syncope.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: syncope git commit: [SYNCOPE-925] Extending CXF's Swagger2Feature on purpose Date: Wed, 24 Aug 2016 11:10:43 +0000 (UTC) archived-at: Wed, 24 Aug 2016 11:11:00 -0000 Repository: syncope Updated Branches: refs/heads/master 5b8237e0b -> 39f7f7ebf [SYNCOPE-925] Extending CXF's Swagger2Feature on purpose Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/39f7f7eb Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/39f7f7eb Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/39f7f7eb Branch: refs/heads/master Commit: 39f7f7ebff132173d5ca6ff6ec5e7692327524dc Parents: 5b8237e Author: Francesco Chicchiriccò Authored: Wed Aug 24 13:10:30 2016 +0200 Committer: Francesco Chicchiriccò Committed: Wed Aug 24 13:10:30 2016 +0200 ---------------------------------------------------------------------- .../rest/cxf/ExtendedSwagger2Serializers.java | 214 +++++++++++++++++++ .../syncope/core/rest/cxf/Swagger2Feature.java | 164 ++------------ .../core/rest/cxf/Swagger2Serializers.java | 36 ++++ .../src/main/resources/restCXFContext.xml | 7 +- .../src/main/resources/jboss/restCXFContext.xml | 8 +- 5 files changed, 275 insertions(+), 154 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/39f7f7eb/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ExtendedSwagger2Serializers.java ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ExtendedSwagger2Serializers.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ExtendedSwagger2Serializers.java new file mode 100644 index 0000000..41710fb --- /dev/null +++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ExtendedSwagger2Serializers.java @@ -0,0 +1,214 @@ +/* + * 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.syncope.core.rest.cxf; + +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; +import io.swagger.models.parameters.HeaderParameter; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +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.collections4.ComparatorUtils; +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 org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.rest.api.RESTHeaders; +import org.apache.syncope.core.persistence.api.DomainsHolder; +import org.apache.syncope.core.spring.ApplicationContextProvider; + +public class ExtendedSwagger2Serializers extends SwaggerSerializers implements Swagger2Serializers { + + protected boolean dynamicBasePath; + + protected boolean replaceTags; + + protected DocumentationProvider javadocProvider; + + protected List cris; + + protected final List domains = new ArrayList<>(); + + public ExtendedSwagger2Serializers() { + super(); + + domains.addAll(ApplicationContextProvider.getApplicationContext(). + getBean(DomainsHolder.class).getDomains().keySet()); + } + + @Override + public void setDynamicBasePath(final boolean dynamicBasePath) { + this.dynamicBasePath = dynamicBasePath; + } + + @Override + public void setReplaceTags(final boolean replaceTags) { + this.replaceTags = replaceTags; + } + + @Override + public void setJavadocProvider(final DocumentationProvider javadocProvider) { + this.javadocProvider = javadocProvider; + } + + @Override + public void setClassResourceInfos(final List classResourceInfos) { + this.cris = classResourceInfos; + } + + @Override + public void writeTo( + final Swagger data, + final Class type, + final Type genericType, + final Annotation[] annotations, + final MediaType mediaType, + final MultivaluedMap 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 operations = new HashMap<>(); + Map, OperationResourceInfo> methods = new HashMap<>(); + for (ClassResourceInfo cri : cris) { + for (OperationResourceInfo ori : cri.getMethodDispatcher().getOperationResourceInfos()) { + String normalizedPath = getNormalizedPath( + cri.getURITemplate().getValue(), ori.getURITemplate().getValue()); + + operations.put(normalizedPath, cri); + methods.put(ImmutablePair.of(ori.getHttpMethod(), normalizedPath), ori); + } + } + + if (replaceTags && data.getTags() != null) { + data.getTags().clear(); + } + for (final Map.Entry 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 subentry : entry.getValue().getOperationMap().entrySet()) { + if (replaceTags && tag != null) { + subentry.getValue().setTags(Collections.singletonList(tag.getName())); + } + + Pair 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)); + + boolean domainHeaderParameterFound = false; + for (int i = 0; i < subentry.getValue().getParameters().size(); i++) { + subentry.getValue().getParameters().get(i). + setDescription(javadocProvider.getMethodParameterDoc(ori, i)); + + if (subentry.getValue().getParameters().get(i) instanceof HeaderParameter + && RESTHeaders.DOMAIN.equals( + subentry.getValue().getParameters().get(i).getName())) { + + domainHeaderParameterFound = true; + } + } + if (!domainHeaderParameterFound) { + HeaderParameter domainHeaderParameter = new HeaderParameter(); + domainHeaderParameter.setName(RESTHeaders.DOMAIN); + domainHeaderParameter.setRequired(true); + domainHeaderParameter.setType("string"); + domainHeaderParameter.setEnum(domains); + domainHeaderParameter.setDefault(SyncopeConstants.MASTER_DOMAIN); + + subentry.getValue().getParameters().add(domainHeaderParameter); + } + + if (subentry.getValue().getResponses() != null + && !subentry.getValue().getResponses().isEmpty()) { + + subentry.getValue().getResponses().entrySet().iterator().next().getValue(). + setDescription(javadocProvider.getMethodResponseDoc(ori)); + } + } + } + } + } + if (replaceTags && data.getTags() != null) { + Collections.sort(data.getTags(), new Comparator() { + + @Override + public int compare(final Tag tag1, final Tag tag2) { + return ComparatorUtils.naturalComparator().compare(tag1.getName(), tag2.getName()); + } + }); + } + + super.writeTo(data, type, genericType, annotations, mediaType, headers, out); + } + + protected String getNormalizedPath(final String classResourcePath, final String operationResourcePath) { + StringBuilder normalizedPath = new StringBuilder(); + + String[] segments = org.apache.commons.lang3.StringUtils.split(classResourcePath + operationResourcePath, + "/"); + for (String segment : segments) { + if (!org.apache.commons.lang3.StringUtils.isEmpty(segment)) { + normalizedPath.append("/").append(segment); + } + } + // Adapt to Swagger's path expression + if (normalizedPath.toString().endsWith(":.*}")) { + normalizedPath.setLength(normalizedPath.length() - 4); + normalizedPath.append('}'); + } + return StringUtils.EMPTY.equals(normalizedPath.toString()) ? "/" : normalizedPath.toString(); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/39f7f7eb/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Feature.java ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Feature.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Feature.java index 1578032..e01d7e2 100644 --- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Feature.java +++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Feature.java @@ -22,25 +22,13 @@ 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; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Swagger; -import io.swagger.models.Tag; import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; import java.net.URI; import java.net.URL; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.servlet.ServletContext; @@ -49,23 +37,15 @@ import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriInfo; -import org.apache.commons.collections4.ComparatorUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.apache.cxf.Bus; 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.OperationResourceInfo; -import org.apache.cxf.jaxrs.model.doc.DocumentationProvider; import org.apache.cxf.jaxrs.provider.ServerProviderFactory; import org.apache.cxf.jaxrs.utils.InjectionUtils; -import org.apache.cxf.jaxrs.utils.JAXRSUtils; /** * Automatically loads available javadocs from class loader (when {@link java.net.URLClassLoader}). @@ -82,7 +62,13 @@ public class Swagger2Feature extends org.apache.cxf.jaxrs.swagger.Swagger2Featur super.initialize(server, bus); } - // ------- Remove the code below this point when CXF-6990 is part of next CXF release (3.1.8?) ----- + // ------- Remove the code below this point when CXF 3.1.8 is available ----- + private Swagger2Serializers swagger2Serializers; + + public void setSwagger2Serializers(final Swagger2Serializers swagger2Serializers) { + this.swagger2Serializers = swagger2Serializers; + } + @Override protected void addSwaggerResource(final Server server, final Bus bus) { List swaggerResources = new LinkedList<>(); @@ -107,7 +93,13 @@ public class Swagger2Feature extends org.apache.cxf.jaxrs.swagger.Swagger2Featur if (SWAGGER_UI_RESOURCE_ROOT != null) { providers.add(new SwaggerUIFilter()); } - providers.add(new Swagger2Serializers(dynamicBasePath, replaceTags, javadocProvider, cris)); + + if (swagger2Serializers != null) { + swagger2Serializers.setJavadocProvider(javadocProvider); + swagger2Serializers.setClassResourceInfos(cris); + providers.add(swagger2Serializers); + } + providers.add(new ReaderConfigFilter()); ((ServerProviderFactory) server.getEndpoint().get( ServerProviderFactory.class.getName())).setUserProviders(providers); @@ -180,132 +172,4 @@ public class Swagger2Feature extends org.apache.cxf.jaxrs.swagger.Swagger2Featur } } - protected static class Swagger2Serializers extends SwaggerSerializers { - - protected final boolean dynamicBasePath; - - protected final boolean replaceTags; - - protected final DocumentationProvider javadocProvider; - - protected final List cris; - - public Swagger2Serializers( - final boolean dynamicBasePath, - final boolean replaceTags, - final DocumentationProvider javadocProvider, - final List 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 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 operations = new HashMap<>(); - Map, OperationResourceInfo> methods = new HashMap<>(); - for (ClassResourceInfo cri : cris) { - for (OperationResourceInfo ori : cri.getMethodDispatcher().getOperationResourceInfos()) { - String normalizedPath = getNormalizedPath( - cri.getURITemplate().getValue(), ori.getURITemplate().getValue()); - - operations.put(normalizedPath, cri); - methods.put(ImmutablePair.of(ori.getHttpMethod(), normalizedPath), ori); - } - } - - if (replaceTags && data.getTags() != null) { - data.getTags().clear(); - } - for (final Map.Entry 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 subentry : entry.getValue(). - getOperationMap().entrySet()) { - if (replaceTags && tag != null) { - subentry.getValue().setTags(Collections.singletonList(tag.getName())); - } - - Pair 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)); - } - } - } - } - } - if (replaceTags && data.getTags() != null) { - Collections.sort(data.getTags(), new Comparator() { - - @Override - public int compare(final Tag tag1, final Tag tag2) { - return ComparatorUtils.naturalComparator().compare(tag1.getName(), tag2.getName()); - } - }); - } - - super.writeTo(data, type, genericType, annotations, mediaType, headers, out); - } - - protected String getNormalizedPath(final String classResourcePath, final String operationResourcePath) { - StringBuilder normalizedPath = new StringBuilder(); - - String[] segments = org.apache.commons.lang3.StringUtils.split(classResourcePath + operationResourcePath, - "/"); - for (String segment : segments) { - if (!org.apache.commons.lang3.StringUtils.isEmpty(segment)) { - normalizedPath.append("/").append(segment); - } - } - // Adapt to Swagger's path expression - if (normalizedPath.toString().endsWith(":.*}")) { - normalizedPath.setLength(normalizedPath.length() - 4); - normalizedPath.append('}'); - } - return StringUtils.EMPTY.equals(normalizedPath.toString()) ? "/" : normalizedPath.toString(); - } - } } http://git-wip-us.apache.org/repos/asf/syncope/blob/39f7f7eb/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Serializers.java ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Serializers.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Serializers.java new file mode 100644 index 0000000..39abf7b --- /dev/null +++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/Swagger2Serializers.java @@ -0,0 +1,36 @@ +/* + * 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.syncope.core.rest.cxf; + +import io.swagger.models.Swagger; +import java.util.List; +import javax.ws.rs.ext.MessageBodyWriter; +import org.apache.cxf.jaxrs.model.ClassResourceInfo; +import org.apache.cxf.jaxrs.model.doc.DocumentationProvider; + +public interface Swagger2Serializers extends MessageBodyWriter { + + void setDynamicBasePath(boolean dynamicBasePath); + + void setReplaceTags(boolean replaceTags); + + void setJavadocProvider(DocumentationProvider javadocProvider); + + void setClassResourceInfos(List classResourceInfos); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/39f7f7eb/core/rest-cxf/src/main/resources/restCXFContext.xml ---------------------------------------------------------------------- diff --git a/core/rest-cxf/src/main/resources/restCXFContext.xml b/core/rest-cxf/src/main/resources/restCXFContext.xml index f7714a1..4f4d12b 100644 --- a/core/rest-cxf/src/main/resources/restCXFContext.xml +++ b/core/rest-cxf/src/main/resources/restCXFContext.xml @@ -99,6 +99,10 @@ under the License. + + + + @@ -109,8 +113,7 @@ under the License. - - + + + + + @@ -115,14 +119,14 @@ under the License. - - /WEB-INF/lib/syncope-common-rest-api-${syncope.version}-javadoc.jar /WEB-INF/lib/syncope-ext-camel-rest-api-${syncope.version}-javadoc.jar + +