This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-toolkit.git
commit c8658ec773a72e96f84138279253cd70a7d6949d Author: MabinGo <[email protected]> AuthorDate: Mon May 20 20:20:24 2019 +0800 Add feature of contract generating document Signed-off-by: MabinGo <[email protected]> --- doc-generator/pom.xml | 118 +++++++++++++++++++++ .../docgen/ContractsAsciidocGenerator.java | 87 +++++++++++++++ .../docgen/ContractsSwaggerUIGenerator.java | 109 +++++++++++++++++++ .../apache/servicecomb/docgen/DocGenerator.java | 27 +++++ .../servicecomb/docgen/DocGeneratorManager.java | 48 +++++++++ .../org.apache.servicecomb.docgen.DocGenerator | 19 ++++ .../src/main/resources/webroot/swagger-ui.html | 32 ++++++ pom.xml | 1 + swagger-ui.html | 32 ++++++ 9 files changed, 473 insertions(+) diff --git a/doc-generator/pom.xml b/doc-generator/pom.xml new file mode 100755 index 0000000..bf5ba09 --- /dev/null +++ b/doc-generator/pom.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>toolkit</artifactId> + <groupId>org.apache.servicecomb</groupId> + <version>0.1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>doc-generator</artifactId> + + <repositories> + <repository> + <snapshots> + <enabled>false</enabled> + </snapshots> + <id>jcenter-releases</id> + <name>jcenter</name> + <url>http://jcenter.bintray.com</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>org.asciidoctor</groupId> + <artifactId>asciidoctorj</artifactId> + <version>1.6.2</version> + </dependency> + + <dependency> + <groupId>org.asciidoctor</groupId> + <artifactId>asciidoctorj-pdf</artifactId> + <version>1.5.0-alpha.15</version> + <exclusions> + <exclusion> + <groupId>org.jruby</groupId> + <artifactId>jruby-complete</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.jruby</groupId> + <artifactId>jruby-complete</artifactId> + <version>9.2.6.0</version> + </dependency> + + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>swagger-generator-core</artifactId> + <version>1.2.0</version> + </dependency> + + <dependency> + <groupId>io.github.swagger2markup</groupId> + <artifactId>swagger2markup</artifactId> + <version>1.3.2</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.4</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit</artifactId> + <version>5.3.0.201903130848-r</version> + </dependency> + + <!--<dependency>--> + <!--<groupId>org.apache.servicecomb</groupId>--> + <!--<artifactId>toolkit-common</artifactId>--> + <!--<version>${project.version}</version>--> + <!--</dependency>--> + + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java new file mode 100755 index 0000000..1e28116 --- /dev/null +++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java @@ -0,0 +1,87 @@ +/* + * 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.servicecomb.docgen; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; + +import org.asciidoctor.Asciidoctor; +import org.asciidoctor.Attributes; +import org.asciidoctor.AttributesBuilder; +import org.asciidoctor.OptionsBuilder; +import org.asciidoctor.SafeMode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Ordering; + +import io.github.swagger2markup.Swagger2MarkupConverter; +import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder; +import io.swagger.models.Swagger; +import io.swagger.models.parameters.Parameter; + + +public class ContractsAsciidocGenerator implements DocGenerator { + + private static final Logger LOGGER = LoggerFactory.getLogger(ContractsAsciidocGenerator.class); + + private final static String DOC_FORMAT = "asciidoc"; + + @Override + public boolean canProcess(String type) { + return type != null && DOC_FORMAT.equals(type.toLowerCase()); + } + + @Override + public String generate(Swagger contractContent, String outputPath) { + + Asciidoctor asciidoctor = Asciidoctor.Factory.create(); + Swagger2MarkupConverter.Builder markupBuilder = Swagger2MarkupConverter.from(contractContent); + Swagger2MarkupConfigBuilder swagger2MarkupConfigBuilder = new Swagger2MarkupConfigBuilder() + .withParameterOrdering(Ordering + .explicit("path", "query", "header", "cookie", "formData", "body") + .onResultOf(Parameter::getIn)); + String markup = markupBuilder.withConfig(swagger2MarkupConfigBuilder.build()).build().toString(); + + final Map<String, Object> optionsMap = OptionsBuilder.options() + .docType("book") + .backend("html5") + .headerFooter(true) + .safe(SafeMode.UNSAFE) + .attributes(AttributesBuilder.attributes() + .attribute("toclevels", 3) + .attribute(Attributes.TOC_2, true) + .attribute(Attributes.TOC_POSITION, "left") + .attribute(Attributes.LINK_CSS, true) + .attribute(Attributes.SECTION_NUMBERS, true) + .attribute(Attributes.SECT_NUM_LEVELS, 4)) + .asMap(); + String asciidocResult = asciidoctor.convert(markup, optionsMap); + try { + Files.write(Paths.get(outputPath), asciidocResult.getBytes()); + } catch (IOException e) { + LOGGER.error(e.getMessage()); + } + + return asciidocResult; + } +} diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java new file mode 100755 index 0000000..2f154b5 --- /dev/null +++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java @@ -0,0 +1,109 @@ +/* + * 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.servicecomb.docgen; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.swagger.models.Swagger; +import io.swagger.util.Json; + +public class ContractsSwaggerUIGenerator implements DocGenerator { + + private static Pattern variablePattern = Pattern.compile("(?<=\\{\\{)[a-zA-Z0-9_-]*(?=\\}\\})"); + + private final static String DOC_FORMAT = "html"; + + @Override + + public boolean canProcess(String type) { + return DOC_FORMAT.equals(type); + } + + @Override + public String generate(Swagger contractContent, String outputPath) { + + String swaggerUiHtml = null; + try { + String swaggerJson = Json.mapper().writeValueAsString(contractContent); + swaggerUiHtml = renderHtml(getSwaggerUiHtml(), Collections.singletonMap("spec", swaggerJson)); + + outputPath = correctPath(outputPath); + Path outputFile = Paths.get(outputPath); + + if (!Files.exists(outputFile)) { + if (outputFile.getParent() != null) { + Files.createDirectories(outputFile.getParent()); + } + Files.createFile(outputFile); + } + + Files.write(outputFile, swaggerUiHtml.getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + + return swaggerUiHtml; + } + + private String correctPath(String filepath) { + + if (!filepath.endsWith("." + DOC_FORMAT)) { + return filepath + DOC_FORMAT; + } + + return filepath; + } + + private String renderHtml(String html, Map<String, String> args) { + + Matcher variableMatcher = variablePattern.matcher(html); + while (variableMatcher.find()) { + String variableStr = variableMatcher.group(); + String variableValue = args.get(variableStr); + + html = html.replace("{{" + variableStr + "}}", variableValue); + } + + return html; + } + + private String getSwaggerUiHtml() throws IOException { + int len; + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + InputStream in = this.getClass().getClassLoader().getResourceAsStream("webroot/swagger-ui.html"); + + byte[] buf = new byte[1024]; + while ((len = in.read(buf)) != -1) { + bout.write(buf, 0, len); + } + bout.close(); + in.close(); + + return new String(bout.toByteArray()); + } +} diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java new file mode 100755 index 0000000..6381e5e --- /dev/null +++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java @@ -0,0 +1,27 @@ +/* + * 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.servicecomb.docgen; + +import io.swagger.models.Swagger; + +public interface DocGenerator { + + boolean canProcess(String type); + + String generate(Swagger source, String outputPath); +} diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java new file mode 100755 index 0000000..17566b8 --- /dev/null +++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java @@ -0,0 +1,48 @@ +/* + * 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.servicecomb.docgen; + +import java.util.ServiceLoader; +import java.util.concurrent.CopyOnWriteArrayList; + +import io.swagger.models.Swagger; + +public class DocGeneratorManager { + + private final static CopyOnWriteArrayList<DocGenerator> registeredGenerators = new CopyOnWriteArrayList<>(); + + static { + loadInitialDocGenerators(); + } + + private static void loadInitialDocGenerators() { + + ServiceLoader.load(DocGenerator.class).forEach(registeredGenerators::add); + } + + public static String generate(Swagger source, String outputPath, String outputType) { + + for (DocGenerator docGenerator : registeredGenerators) { + if (docGenerator.canProcess(outputType)) { + return docGenerator.generate(source, outputPath); + } + } + + return null; + } +} diff --git a/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator b/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator new file mode 100755 index 0000000..aa6fb85 --- /dev/null +++ b/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator @@ -0,0 +1,19 @@ +# +# 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. +# + +org.apache.servicecomb.docgen.ContractsAsciidocGenerator +org.apache.servicecomb.docgen.ContractsSwaggerUIGenerator \ No newline at end of file diff --git a/doc-generator/src/main/resources/webroot/swagger-ui.html b/doc-generator/src/main/resources/webroot/swagger-ui.html new file mode 100755 index 0000000..6718b91 --- /dev/null +++ b/doc-generator/src/main/resources/webroot/swagger-ui.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + + <meta charset="UTF-8"> + <title>Title</title> + + <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/swagger-ui.css"> + <script src="https://unpkg.com/[email protected]/swagger-ui-standalone-preset.js"></script> + <script src="https://unpkg.com/[email protected]/swagger-ui-bundle.js"></script> +</head> +<body> + +<div id="swagger-ui"></div> + +</body> + + +<script> + const ui = SwaggerUIBundle({ + spec: JSON.parse('{{spec}}'), + dom_id: '#swagger-ui', + deepLinking: true, + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + layout: "StandaloneLayout" + }) +</script> + +</html> \ No newline at end of file diff --git a/pom.xml b/pom.xml index ca48b94..d97307d 100755 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ <modules> <module>code-generator</module> <module>toolkit-cli</module> + <module>doc-generator</module> </modules> </project> diff --git a/swagger-ui.html b/swagger-ui.html new file mode 100755 index 0000000..282a229 --- /dev/null +++ b/swagger-ui.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + + <meta charset="UTF-8"> + <title>Title</title> + + <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/swagger-ui.css"> + <script src="https://unpkg.com/[email protected]/swagger-ui-standalone-preset.js"></script> + <script src="https://unpkg.com/[email protected]/swagger-ui-bundle.js"></script> +</head> +<body> + +<div id="swagger-ui"></div> + +</body> + + +<script> + const ui = SwaggerUIBundle({ + spec: JSON.parse('{"swagger":"2.0","info":{"description":"ThisisasampleserverPetstoreserver.YoucanfindoutmoreaboutSwaggerat[http://swagger.io](http://swagger.io)oron[irc.freenode.net,#swagger](http://swagger.io/irc/).Forthissample,youcanusetheapikey`special-key`totesttheauthorizationfilters.","version":"1.0.0","title":"SwaggerPetstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"[email protected]"},"license":{"name":"Apache2.0","url":"http://www.apache.org/li [...] + dom_id: '#swagger-ui', + deepLinking: true, + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + layout: "StandaloneLayout" + }) +</script> + +</html> \ No newline at end of file
