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 667a835a3f041821ded38f71e1c543ef3841fa39
Author: MabinGo <[email protected]>
AuthorDate: Mon Jul 22 20:44:22 2019 +0800

    SCB-1383 support toolkit maven plugin commands that generating code
    
    Signed-off-by: MabinGo <[email protected]>
---
 README-ZH.md                                       | 33 +++++++--
 README.md                                          | 29 +++++++-
 .../toolkit/codegen/ServiceCombCodegen.java        | 13 ++--
 .../servicecomb/toolkit/plugin/GenerateMojo.java   | 25 +++++--
 .../servicecomb/toolkit/plugin/GenerateUtil.java   | 65 ++++++++++++++---
 .../servicecomb/toolkit/plugin/ServiceConfig.java  | 65 +++++++++++++++++
 .../servicecomb/toolkit/plugin/VerifyMojo.java     |  2 +-
 .../toolkit/plugin/GenerateMojoTest.java           | 81 +++++++++++++++-------
 .../toolkit/plugin/GenerateUtilTest.java           | 41 +++++++++--
 9 files changed, 293 insertions(+), 61 deletions(-)

diff --git a/README-ZH.md b/README-ZH.md
index 8cb2023..3eadc62 100755
--- a/README-ZH.md
+++ b/README-ZH.md
@@ -101,7 +101,7 @@ $ mvn clean install
         <contractFileType>yaml</contractFileType>
         <!-- 生成文档的类型,不设置则默认为 html -->
         <documentType>html</documentType>
-        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的契约文件在 contract 
目录,生成的文档在 document 目录 -->
+        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 
目录,契约文件在 contract 目录,文档在 document 目录 -->
         <outputDirectory>./target</outputDirectory>
         <!-- 被解析的契约文件路径,在 sourceType 设置为 contract 时有效,且必须设置 -->
         <contractLocation>./contract</contractLocation>
@@ -109,6 +109,19 @@ $ mvn clean install
         <sourceContractPath>./target/contract</sourceContractPath>
         <!-- 样本契约文件目录,必须设置 -->
         <destinationContractPath>./contract</destinationContractPath>
+        <!-- 生成的微服务代码工程配置 -->
+        <service>
+            <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all -->
+            <serviceType>all</serviceType>
+            <!-- 微服务的 groupid,用户可选,默认值为 domain.orgnization.project -->
+            <groupId>domain.orgnization.project</groupId>
+            <!-- 微服务的 artifactId,用户可选,默认值为 sample -->
+            <artifactId>sample</artifactId>
+            <!-- 微服务的 artifactVersion,用户可选,默认值为 0.1.0-SNAPSHOT -->
+            <artifactVersion>0.1.0-SNAPSHOT</artifactVersion>
+            <!-- 微服务的 packageName,用户可选,默认值为 domain.orgnization.project.sample 
-->
+            <packageName>domain.orgnization.project.sample</packageName>
+        </service>
     </configuration>
 </plugin>
 ```
@@ -122,7 +135,7 @@ mvn toolkit:generate
 mvn toolkit:verify
 ```
 
-#### 3.2.2.1 解析代码,生成OpenAPI规范契约、文档
+#### 3.2.2.1 解析代码,生成微服务代码工程、OpenAPI规范契约、文档
 
 配置项(不显式设置 `<configuration>` 则使用默认配置)
 例:
@@ -134,8 +147,13 @@ mvn toolkit:verify
     <configuration>
         <!-- 输入源。设置为 code,表示解析当前代码;设置为 contract,表示解析指定目录的契约文件。不设置则默认为 code -->
         <sourceType>code</sourceType>
-        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的契约文件在 contract 
目录,生成的文档在 document 目录 -->
+        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 
目录,契约文件在 contract 目录,文档在 document 目录 -->
         <outputDirectory>./target</outputDirectory>
+        <!-- 生成的微服务代码工程配置 -->
+        <service>
+            <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all -->
+            <serviceType>all</serviceType>
+        </service>
     </configuration>
 </plugin>
 ```
@@ -145,7 +163,7 @@ mvn toolkit:verify
 mvn toolkit:generate
 ```
 
-#### 3.2.2.2 解析契约,生成文档
+#### 3.2.2.2 解析契约,生成微服务工程、文档
 
 配置项(不显式设置 `<configuration>` 则使用默认配置)
 例:
@@ -159,8 +177,13 @@ mvn toolkit:generate
         <sourceType>contract</sourceType>
         <!-- 被解析的契约文件路径,在 sourceType 设置为 contract 时有效,且必须设置 -->
         <contractLocation>./contract</contractLocation>
-        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的契约文件在 contract 
目录,生成的文档在 document 目录 -->
+        <!-- 生成契约文件、文档的根目录,不设置则默认为运行命令所在目录下的 target 目录,生成的微服务工程在 project 
目录,契约文件在 contract 目录,文档在 document 目录 -->
         <outputDirectory>./target</outputDirectory>
+        <!-- 生成的微服务代码工程配置 -->
+        <service>
+            <!-- 微服务的类型,可生成 provider/consumer/all,默认值为 all -->
+            <serviceType>provider</serviceType>
+        </service>
     </configuration>
 </plugin>
 ```
diff --git a/README.md b/README.md
index 55405cf..a2a4117 100755
--- a/README.md
+++ b/README.md
@@ -99,7 +99,7 @@ Configured in the pom file of the maven project
         <contractFileType>yaml</contractFileType>
         <!-- The type of the generated document. If not set, the default is 
'html' -->
         <documentType>html</documentType>
-        <!-- The root directory to save contract file and document. If it is 
not set, the default is the 'target' under the directory where the command is 
run -->
+        <!-- The root directory to save microservice project,contract file and 
document. If it is not set, the default is the 'target' under the directory 
where the command is run -->
         <outputDirectory>./target</outputDirectory>
         <!-- Input contract file path. Valid when sourceType is set to 
'contract', must be set -->
         <contractLocation>./contract</contractLocation>
@@ -107,6 +107,19 @@ Configured in the pom file of the maven project
         <sourceContractPath>./target/contract</sourceContractPath>
         <!-- Sample contract file path, must be set -->
         <destinationContractPath>./contract</destinationContractPath>
+        <!-- Generated microservice project configuration -->
+        <service>
+            <!-- Microservice type,can generated 'provider/consumer/all',the 
default is 'all' -->
+            <serviceType>all</serviceType>
+            <!-- Microservice project 'groupid',optional,the default is 
'domain.orgnization.project' -->
+            <groupId>domain.orgnization.project</groupId>
+            <!-- Microservice project 'artifactId',optional,the default is 
'sample' -->
+            <artifactId>sample</artifactId>
+            <!-- Microservice project 'artifactVersion',optional,the default 
is '0.1.0-SNAPSHOT' -->
+            <artifactVersion>0.1.0-SNAPSHOT</artifactVersion>
+            <!-- Microservice project 'packageName',optional,the default is 
'domain.orgnization.project.sample' -->
+            <packageName>domain.orgnization.project.sample</packageName>
+        </service>
     </configuration>
 </plugin>
 ```
@@ -120,7 +133,7 @@ mvn toolkit:generate
 mvn toolkit:verify
 ```
 
-#### 3.2.2.1 Extract the OpenAPI contract file and document from the code
+#### 3.2.2.1 Extract the microservice project, OpenAPI contract file and 
document from the code
 
 Configuration(use default configuration if not set `<configuration>`)
 
@@ -135,6 +148,11 @@ example
         <sourceType>code</sourceType>
         <!-- The root directory to save contract file and document. If it is 
not set, the default is the 'target' under the directory where the command is 
run -->
         <outputDirectory>./target</outputDirectory>
+        <!-- Generated microservice project configuration -->
+        <service>
+            <!-- Microservice type,can generated 'provider/consumer/all',the 
default is 'all' -->
+            <serviceType>all</serviceType>
+        </service>
     </configuration>
 </plugin>
 ```
@@ -145,7 +163,7 @@ mvn toolkit:generate
 ```
 
 
-#### 3.2.2.2 Generate document from contract
+#### 3.2.2.2 Generate the microservice project and document from contract
 
 Configuration(use default configuration if not set `<configuration>`)
 
@@ -162,6 +180,11 @@ example
         <outputDirectory>./target</outputDirectory>
         <!-- Input contract file path. Valid when sourceType is set to 
'contract', must be set -->
         <contractLocation>./contract</contractLocation>
+        <!-- Generated microservice project configuration -->
+        <service>
+            <!-- Microservice type,can generated 'provider/consumer/all',the 
default is 'all' -->
+            <serviceType>provider</serviceType>
+        </service>
     </configuration>
 </plugin>
 ```
diff --git 
a/codegen/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombCodegen.java
 
b/codegen/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombCodegen.java
index ae1df67..bc4cba0 100755
--- 
a/codegen/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombCodegen.java
+++ 
b/codegen/src/main/java/org/apache/servicecomb/toolkit/codegen/ServiceCombCodegen.java
@@ -99,18 +99,17 @@ public class ServiceCombCodegen extends AbstractJavaCodegen 
implements CodegenCo
     modelTemplateFiles.put(modelTemplateFolder + "/model.mustache", ".java");
     modelTemplateFiles.remove("model.mustache");
 
-    groupId = "org.apache.servicecomb.toolkit";
-    artifactId = "app";
+    groupId = "domain.orgnization.project";
+    artifactId = "sample";
 
     apiPackage = groupId + "." + artifactId + ".api";
     modelPackage = groupId + "." + artifactId + ".model";
     mainClassPackage = groupId + "." + artifactId;
 
-    supportedLibraries.put(DEFAULT_LIBRARY, "ServiceComb Server application 
using the springboot programming model.");
-    supportedLibraries.put(POJO_LIBRARY, "ServiceComb Server application using 
the pojo programming model.");
-    supportedLibraries.put(JAX_RS_LIBRARY, "ServiceComb Server application 
using the jax-rs programming model.");
-    supportedLibraries
-        .put(SPRING_BOOT_LIBRARY, "ServiceComb Server application using the 
SpringBoot programming model.");
+    supportedLibraries.put(DEFAULT_LIBRARY, "ServiceComb Server application 
using the SpringMVC programming model.");
+    supportedLibraries.put(POJO_LIBRARY, "ServiceComb Server application using 
the POJO programming model.");
+    supportedLibraries.put(JAX_RS_LIBRARY, "ServiceComb Server application 
using the JAX-RS programming model.");
+    supportedLibraries.put(SPRING_BOOT_LIBRARY, "ServiceComb Server 
application using the SpringBoot programming model.");
 
     setLibrary(DEFAULT_LIBRARY);
 
diff --git 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateMojo.java
 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateMojo.java
index 1569019..fa2635f 100755
--- 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateMojo.java
+++ 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateMojo.java
@@ -57,15 +57,15 @@ public class GenerateMojo extends AbstractMojo {
   @Parameter(defaultValue = "./target")
   private String outputDirectory;
 
+  @Parameter
+  private ServiceConfig service;
+
   @Override
   public void execute() {
 
     switch (SourceType.valueOf(sourceType.toUpperCase())) {
       case CODE:
         // generate contract file
-        if (outputDirectory == null) {
-          throw new RuntimeException("output directory setting is invalid");
-        }
         String contractOutput = outputDirectory + File.separator + "contract";
         try {
           FileUtils.createDirectory(contractOutput);
@@ -76,14 +76,14 @@ public class GenerateMojo extends AbstractMojo {
         GenerateUtil.generateContract(project, contractOutput, 
contractFileType, "default");
         contractLocation = contractOutput;
         if (Objects.requireNonNull(new 
File(contractOutput).listFiles()).length == 0) {
-          LOGGER.info("No contract in the code");
+          LOGGER.info("no contract in the code");
           return;
         }
 
         break;
       case CONTRACT:
         if (contractLocation == null) {
-          throw new RuntimeException("contract location is invalid or not 
set");
+          throw new RuntimeException("invalid or not config contract 
location");
         }
 
         if (!new File(contractLocation).exists()) {
@@ -92,7 +92,20 @@ public class GenerateMojo extends AbstractMojo {
 
         break;
       default:
-        throw new RuntimeException("source type " + sourceType + " is not 
supported");
+        throw new RuntimeException("not support source type " + sourceType);
+    }
+
+    //generate microservice project
+    if (service == null) {
+      LOGGER.info("no service configuration and do not generate code");
+      return;
+    }
+    String codeOutput = outputDirectory + File.separator + "project";
+    try {
+      FileUtils.createDirectory(codeOutput);
+      GenerateUtil.generateCode(service, contractLocation, codeOutput, 
"default");
+    } catch (IOException e) {
+      throw new RuntimeException("failed to generate code", e);
     }
 
     //generate document
diff --git 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateUtil.java
 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateUtil.java
index 7747fef..905015a 100755
--- 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateUtil.java
+++ 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/GenerateUtil.java
@@ -25,6 +25,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -32,15 +33,15 @@ import java.util.Objects;
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.project.MavenProject;
 import org.apache.servicecomb.swagger.SwaggerUtils;
+import org.apache.servicecomb.toolkit.CodeGenerator;
 import org.apache.servicecomb.toolkit.ContractsGenerator;
 import org.apache.servicecomb.toolkit.DocGenerator;
 import org.apache.servicecomb.toolkit.GeneratorFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.servicecomb.toolkit.codegen.ProjectMetaConstant;
 
-public class GenerateUtil {
+import io.swagger.codegen.config.CodegenConfigurator;
 
-  private static Logger LOGGER = LoggerFactory.getLogger(GenerateUtil.class);
+public class GenerateUtil {
 
   public static void generateContract(MavenProject project, String 
contractOutput, String contractFileType,
       String type) {
@@ -57,16 +58,17 @@ public class GenerateUtil {
     // TODO: support users to add other getGenerator type soon
     ContractsGenerator contractGenerator = 
GeneratorFactory.getGenerator(ContractsGenerator.class, type);
     Objects.requireNonNull(contractGenerator).configure(contractConfig);
-    contractGenerator.generate();
+    if (!contractGenerator.generate()) {
+      throw new RuntimeException("failed to generate contract by generator " + 
type);
+    }
   }
 
-  public static void generateDocument(String contractLocation, String 
documentOutput, String type)
-      throws IOException {
+  public static void generateDocument(String contractLocation, String 
documentOutput, String type) throws IOException {
 
     // TODO: support users to add other getGenerator type soon
     DocGenerator docGenerator = 
GeneratorFactory.getGenerator(DocGenerator.class, type);
     if (docGenerator == null) {
-      throw new RuntimeException("DocGenerator's implementation is not found");
+      throw new RuntimeException("not found document generator's 
implementation");
     }
 
     Files.walkFileTree(Paths.get(contractLocation), new 
SimpleFileVisitor<Path>() {
@@ -81,10 +83,55 @@ public class GenerateUtil {
             .substring(0, file.toFile().getName().indexOf(".")));
 
         docGenerator.configure(docGeneratorConfig);
-        docGenerator.generate();
+        if (!docGenerator.generate()) {
+          throw new RuntimeException("failed to generate document by generator 
" + type);
+        }
 
         return super.visitFile(file, attrs);
       }
     });
   }
+
+  public static void generateCode(ServiceConfig service, String 
contractLocation,
+      String codeOutput, String type) throws IOException {
+
+    CodeGenerator codeGenerator = 
GeneratorFactory.getGenerator(CodeGenerator.class, type);
+    if (codeGenerator == null) {
+      throw new RuntimeException("not found code generator's implementation");
+    }
+
+    CodegenConfigurator configurator = new CodegenConfigurator();
+    configurator.setOutputDir(codeOutput)
+        .setLang("ServiceComb")
+        .setApiPackage(service.getPackageName())
+        .setGroupId(service.getGroupId())
+        .setArtifactId(service.getArtifactId())
+        .setModelPackage(service.getPackageName())
+        .setLibrary(service.getProgrammingModel())
+        .addAdditionalProperty("mainClassPackage", service.getPackageName())
+        .setArtifactVersion(service.getArtifactVersion())
+        .addAdditionalProperty(ProjectMetaConstant.SERVICE_TYPE, 
service.getServiceType());
+
+    File contractFile = new File(contractLocation);
+    if (contractFile.isDirectory()) {
+
+      Files.walkFileTree(Paths.get(contractFile.toURI()), new 
SimpleFileVisitor<Path>() {
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
throws IOException {
+          configurator.setInputSpec(file.toFile().getCanonicalPath());
+          
Objects.requireNonNull(codeGenerator).configure(Collections.singletonMap("configurator",
 configurator));
+          if (!codeGenerator.generate()) {
+            throw new RuntimeException("failed to generate code by generator " 
+ type);
+          }
+          return super.visitFile(file, attrs);
+        }
+      });
+    } else {
+      configurator.setInputSpec(contractLocation);
+      
Objects.requireNonNull(codeGenerator).configure(Collections.singletonMap("configurator",
 configurator));
+      if (!codeGenerator.generate()) {
+        throw new RuntimeException("failed to generate code by generator " + 
type);
+      }
+    }
+  }
 }
diff --git 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/ServiceConfig.java
 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/ServiceConfig.java
new file mode 100755
index 0000000..3edaeab
--- /dev/null
+++ 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/ServiceConfig.java
@@ -0,0 +1,65 @@
+/*
+ * 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.toolkit.plugin;
+
+import org.apache.maven.plugins.annotations.Parameter;
+
+public class ServiceConfig {
+
+  @Parameter(defaultValue = "all")
+  private String serviceType;
+
+  @Parameter(defaultValue = "domain.orgnization.project")
+  private String groupId;
+
+  @Parameter(defaultValue = "sample")
+  private String artifactId;
+
+  @Parameter(defaultValue = "0.1.0-SNAPSHOT")
+  private String artifactVersion;
+
+  @Parameter(defaultValue = "domain.orgnization.project.sample")
+  private String packageName;
+
+  @Parameter(defaultValue = "SpringMVC")
+  private String programmingModel;
+
+  public String getServiceType() {
+    return serviceType;
+  }
+
+  public String getGroupId() {
+    return groupId;
+  }
+
+  public String getArtifactId() {
+    return artifactId;
+  }
+
+  public String getArtifactVersion() {
+    return artifactVersion;
+  }
+
+  public String getPackageName() {
+    return packageName;
+  }
+
+  public String getProgrammingModel() {
+    return programmingModel;
+  }
+}
diff --git 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/VerifyMojo.java
 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/VerifyMojo.java
index f6d7376..43d1b28 100755
--- 
a/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/VerifyMojo.java
+++ 
b/toolkit-maven-plugin/src/main/java/org/apache/servicecomb/toolkit/plugin/VerifyMojo.java
@@ -71,7 +71,7 @@ public class VerifyMojo extends AbstractMojo {
 
         break;
       default:
-        throw new RuntimeException("source type " + sourceType + " is not 
supported");
+        throw new RuntimeException("not support source type " + sourceType);
     }
 
     try {
diff --git 
a/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateMojoTest.java
 
b/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateMojoTest.java
index fdbde2f..326c438 100644
--- 
a/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateMojoTest.java
+++ 
b/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateMojoTest.java
@@ -19,14 +19,15 @@ package org.apache.servicecomb.toolkit.plugin;
 
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
 
 import java.io.File;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -37,6 +38,7 @@ import org.apache.maven.plugin.testing.MojoRule;
 import org.apache.maven.plugin.testing.resources.TestResources;
 import org.apache.maven.project.MavenProject;
 import org.apache.servicecomb.toolkit.common.ClassMaker;
+import org.apache.servicecomb.toolkit.common.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -59,15 +61,15 @@ public class GenerateMojoTest {
 
   @Test
   public void testGenerateMojo() throws Exception {
-    File baseDir = this.resources.getBasedir(TEST_PROJECT_WITHCONTRACT);
+    File baseDirWithContract = 
this.resources.getBasedir(TEST_PROJECT_WITHCONTRACT);
     File baseDirWithoutContract = 
this.resources.getBasedir(TEST_PROJECT_WITHOUTCONTRACT);
     File contractLocation = 
this.resources.getBasedir(TEST_PROJECT_CONTRACTLOCATION);
 
-    File pom = new File(baseDir, "pom.xml");
+    File pom = new File(baseDirWithContract, "pom.xml");
     AbstractMojo generateMojo = (AbstractMojo) 
this.rule.lookupMojo(PLUGIN_GOAL, pom);
     assertNotNull(generateMojo);
 
-    String testDir = baseDir + File.separator;
+    String testDirWithContract = baseDirWithContract + File.separator;
     String testDirWithoutContract = baseDirWithoutContract + File.separator;
     String classesPath = "target/classes";
 
@@ -78,68 +80,99 @@ public class GenerateMojoTest {
 
     List<String> runtimeUrlPath = new ArrayList<>();
     runtimeUrlPath.add(testDirWithoutContract + classesPath);
-
     given(project.getRuntimeClasspathElements()).willReturn(runtimeUrlPath);
     rule.setVariableValueToObject(generateMojo, "project", project);
 
+    String outputDirectory = null;
+    String contractOutput = null;
+    String projectOutput = null;
+    String documentOutput = null;
+
     try {
+      outputDirectory = "./target";
+
       rule.setVariableValueToObject(generateMojo, "sourceType", "code");
-      rule.setVariableValueToObject(generateMojo, "outputDirectory", 
"./target");
+      rule.setVariableValueToObject(generateMojo, "outputDirectory", 
outputDirectory);
+
       generateMojo.execute();
 
       assertEquals(0, Objects.requireNonNull(
-          Paths.get(rule.getVariableValueFromObject(generateMojo, 
"contractLocation").toString()).toFile()
-              .listFiles()).length);
+          new File(rule.getVariableValueFromObject(generateMojo, 
"contractLocation").toString()).listFiles()).length);
     } catch (MojoFailureException e) {
       fail();
     }
 
     // code has contract
-    ClassMaker.compile(testDir);
+    ClassMaker.compile(testDirWithContract);
 
     runtimeUrlPath.remove(0);
-    runtimeUrlPath.add(testDir + classesPath);
+    runtimeUrlPath.add(testDirWithContract + classesPath);
     given(project.getRuntimeClasspathElements()).willReturn(runtimeUrlPath);
-
     rule.setVariableValueToObject(generateMojo, "project", project);
 
     try {
+      outputDirectory = "./target";
+      contractOutput = outputDirectory + File.separator + "contract";
+      projectOutput = outputDirectory + File.separator + "project";
+      documentOutput = outputDirectory + File.separator + "document";
+
       rule.setVariableValueToObject(generateMojo, "sourceType", "code");
-      rule.setVariableValueToObject(generateMojo, "outputDirectory", 
"./target");
+      rule.setVariableValueToObject(generateMojo, "outputDirectory", 
outputDirectory);
       rule.setVariableValueToObject(generateMojo, "contractFileType", "yaml");
       rule.setVariableValueToObject(generateMojo, "documentType", "html");
-      generateMojo.execute();
-    } catch (RuntimeException e) {
-      fail();
-    }
 
-    try {
-      rule.setVariableValueToObject(generateMojo, "sourceType", "code");
       generateMojo.execute();
 
-      rule.setVariableValueToObject(generateMojo, "outputDirectory", null);
-      generateMojo.execute();
+      assertNotEquals(0, Objects.requireNonNull(new 
File(outputDirectory).listFiles()).length);
+      assertNotEquals(0, Objects.requireNonNull(new 
File(contractOutput).listFiles()).length);
+      assertNotEquals(0, Objects.requireNonNull(new 
File(projectOutput).listFiles()).length);
+      assertNotEquals(0, Objects.requireNonNull(new 
File(documentOutput).listFiles()).length);
     } catch (RuntimeException e) {
-      assertEquals("output directory setting is invalid", e.getMessage());
+      fail();
     }
 
+    boolean isSuccessful;
     try {
+      isSuccessful = false;
+
       rule.setVariableValueToObject(generateMojo, "sourceType", "contract");
       rule.setVariableValueToObject(generateMojo, "contractLocation", null);
+
       generateMojo.execute();
     } catch (RuntimeException e) {
-      assertEquals("contract location is invalid or not set", e.getMessage());
+      assertEquals("invalid or not config contract location", e.getMessage());
+      isSuccessful = true;
     }
+    assertTrue(isSuccessful);
 
     try {
+      isSuccessful = false;
+
       rule.setVariableValueToObject(generateMojo, "sourceType", "contract");
       rule.setVariableValueToObject(generateMojo, "contractLocation", "");
-      generateMojo.execute();
 
-      rule.setVariableValueToObject(generateMojo, "contractLocation", 
"nonexists");
       generateMojo.execute();
     } catch (RuntimeException e) {
       assertThat(e.getMessage(), containsString("is not exists"));
+      isSuccessful = true;
     }
+    assertTrue(isSuccessful);
+
+    outputDirectory = "./target";
+    projectOutput = outputDirectory + File.separator + "project";
+    ServiceConfig service = new ServiceConfig();
+
+    rule.setVariableValueToObject(generateMojo, "sourceType", "code");
+    rule.setVariableValueToObject(generateMojo, "outputDirectory", 
outputDirectory);
+    FileUtils.createDirectory(projectOutput);
+    rule.setVariableValueToObject(generateMojo, "service", null);
+    generateMojo.execute();
+    assertEquals(0, Objects.requireNonNull(new 
File(projectOutput).listFiles()).length);
+
+    rule.setVariableValueToObject(generateMojo, "sourceType", "code");
+    rule.setVariableValueToObject(generateMojo, "outputDirectory", 
outputDirectory);
+    rule.setVariableValueToObject(generateMojo, "service", service);
+    generateMojo.execute();
+    assertNotEquals(0, Objects.requireNonNull(new 
File(projectOutput).listFiles()).length);
   }
 }
\ No newline at end of file
diff --git 
a/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateUtilTest.java
 
b/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateUtilTest.java
index eaf6d1d..07d8273 100644
--- 
a/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateUtilTest.java
+++ 
b/toolkit-maven-plugin/src/test/java/org/apache/servicecomb/toolkit/plugin/GenerateUtilTest.java
@@ -17,15 +17,21 @@
 
 package org.apache.servicecomb.toolkit.plugin;
 
+import static org.apache.servicecomb.toolkit.plugin.GenerateUtil.generateCode;
 import static 
org.apache.servicecomb.toolkit.plugin.GenerateUtil.generateContract;
 import static 
org.apache.servicecomb.toolkit.plugin.GenerateUtil.generateDocument;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
 
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.plugin.testing.resources.TestResources;
@@ -49,29 +55,52 @@ public class GenerateUtilTest {
 
     MavenProject project = mock(MavenProject.class);
 
-    generateContract(project, "target/contract", "yaml", "default");
-
+    String contractOutput = "target/contract";
     
when(project.getRuntimeClasspathElements()).thenThrow(DependencyResolutionRequiredException.class);
     try {
-      generateContract(project, "target/contract", "yaml", "default");
+      generateContract(project, contractOutput, "yaml", "default");
     } catch (RuntimeException e) {
       assertEquals("failed to get runtime class elements", e.getMessage());
       return;
     }
+
+    fail();
+  }
+
+  @Test
+  public void testGenerateCode() throws IOException {
+    File contractLocation = 
resources.getBasedir(TEST_PROJECT_CONTRACTLOCATION);
+
+    String projectOutput = "./target/project";
+    ServiceConfig service = new ServiceConfig();
+    generateCode(service, contractLocation.getCanonicalPath(), projectOutput, 
"default");
+    assertNotEquals(0, Objects.requireNonNull(new 
File(projectOutput).listFiles()).length);
+
+    try {
+      generateCode(service, contractLocation.getCanonicalPath(), 
projectOutput, "invalidType");
+    } catch (RuntimeException e) {
+      assertEquals("not found code generator's implementation", 
e.getMessage());
+      return;
+    }
+
     fail();
   }
 
   @Test
   public void testGenerateDocument() throws IOException {
     File contractLocation = 
resources.getBasedir(TEST_PROJECT_CONTRACTLOCATION);
-    generateDocument(contractLocation.getCanonicalPath(), "target/document", 
"default");
+
+    String codeOutput = "./target/document";
+    generateDocument(contractLocation.getCanonicalPath(), codeOutput, 
"default");
+    assertNotEquals(0, Objects.requireNonNull(new 
File(codeOutput).listFiles()).length);
 
     try {
-      generateDocument(contractLocation.getCanonicalPath(), "target/document", 
"others");
+      generateDocument(contractLocation.getCanonicalPath(), codeOutput, 
"invalidType");
     } catch (RuntimeException e) {
-      assertEquals("DocGenerator's implementation is not found", 
e.getMessage());
+      assertEquals("not found document generator's implementation", 
e.getMessage());
       return;
     }
+
     fail();
   }
 }
\ No newline at end of file

Reply via email to