You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2019/06/21 07:09:22 UTC
[servicecomb-toolkit] 06/49: Add feature of contract generating
document
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 <bi...@huawei.com>
AuthorDate: Mon May 20 20:20:24 2019 +0800
Add feature of contract generating document
Signed-off-by: MabinGo <bi...@huawei.com>
---
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/swagger-ui-dist@3.22.1/swagger-ui.css">
+ <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-standalone-preset.js"></script>
+ <script src="https://unpkg.com/swagger-ui-dist@3.22.1/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/swagger-ui-dist@3.22.1/swagger-ui.css">
+ <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-standalone-preset.js"></script>
+ <script src="https://unpkg.com/swagger-ui-dist@3.22.1/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":"apiteam@swagger.io"},"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