最新消息:天气越来越冷,记得加一件厚衣裳

Maven集成 – ProcessBuilder

Java w3sun 1528浏览 0评论

背景

一般在使用maven进行程序打包过程中最常用方法是使用maven-assembly-plugin或者maven-shade-plugin插件。最近在做项目的时候需要对用户所指定git仓库中代码进行编译打包,由于无法获取Jenkins较高授权,因此只能将用户代码从git仓库中拉取到本地进行打包,这种情况下就需要将编译打包过程集成到java代码中,因此调研了几种集成形式,以下提供测试代码。

Maven集成

package com.w3sun.it.maven;


import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.google.common.io.Files;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

/**
 * @author neters
 */
public class ProcessMavenBuilder {
  private static final Logger logger = LoggerFactory.getLogger(ProcessMavenBuilder.class);
  private static final String CMD = "mvn";
  private static final String DEFAULT_MAVEN_HOME_ENV = "M2_HOME";
  private static final String DEFAULT_MAVEN_HOME_PROPERTY = "maven.home";

  private File logFile = Paths.get("/var/log/mvnit.log").toFile();

  public ProcessMavenBuilder() throws IOException {
    //empty the constructor
  }

  public ProcessMavenBuilder(File logFile) throws IOException {
    this.logFile = logFile;
  }

  public File getLogFile() {
    return logFile;
  }

  /**
   * Generate the default maven install directory path for detecting the mvn command.
   *
   * @return mvn command path in String by default
   */
  public String getMavenCommand() {
    return getMavenCommand(null, null);
  }

  /**
   * Method overload for detecting maven install directory and the mvn command.
   *
   * @param mavenHomeEnv M2_HOME
   * @return mvn command path in String
   */
  public String getMavenCommand(String mavenHomeEnv) {
    return getMavenCommand(null, mavenHomeEnv);
  }

  /**
   * Generate the complete path for `mvn` command.
   *
   * @param mavenHomeInProperty    {maven.home} by default
   * @param mavenHomeInEnvironment {M2_HOME} by default
   * @return
   */
  public String getMavenCommand(String mavenHomeInProperty, String mavenHomeInEnvironment) {
    String mavenHomeProp = Strings.isNullOrEmpty(mavenHomeInProperty) ? DEFAULT_MAVEN_HOME_PROPERTY : mavenHomeInProperty;
    String mavenHomeEnv = Strings.isNullOrEmpty(mavenHomeInEnvironment) ? DEFAULT_MAVEN_HOME_ENV : mavenHomeInEnvironment;

    String mavenHome = System.getProperty(mavenHomeProp);
    if (Strings.isNullOrEmpty(mavenHome)) {
      mavenHome = System.getenv(mavenHomeEnv);
      if (Strings.isNullOrEmpty(mavenHome)) {
        return StringUtils.EMPTY;
      }
    }

    StringBuilder sb = new StringBuilder(mavenHome);
    return sb.append(File.separator)
            .append("bin")
            .append(File.separator)
            .append(CMD)
            .toString();
  }

  /**
   * Run the build process in the `workingDirectory` according to specified goals.
   *
   * @param goals            plugin goals
   * @param workingDirectory current project or sub-project work directory
   */
  public void build(String goals, String workingDirectory) {
    build(null, goals, workingDirectory);
  }

  /**
   * Run the build process in the `workingDirectory` according to specified goals.
   *
   * @param mavenCommand     complete path of {mvn} command
   * @param goals            plugin goals
   * @param workingDirectory current project or sub-project work directory
   */
  public void build(String mavenCommand, String goals, String workingDirectory) {
    String mvn = Strings.isNullOrEmpty(mavenCommand) ? getMavenCommand() : mavenCommand;
    ProcessBuilder processBuilder = new ProcessBuilder(mvn, goals);
    processBuilder.directory(Paths.get(workingDirectory).toFile());
    try {
      redirectLogToFile(processBuilder);
      Process process = processBuilder.start();
      int exitCode = process.waitFor();
      System.out.println(Files.toString(this.logFile, Charsets.UTF_8));
      if (0 != exitCode) {
        //compile failed
      } else {
        //compile successed
      }
    } catch (Exception e) {
      String error = String.format("build error!", e.getMessage());
      logger.error(error);
    }
  }

  /**
   * Redirect log generated by maven package process, either error or sucess message.
   *
   * @param processBuilder ProcessBuilder
   * @throws IOException IOException
   */
  private void redirectLogToFile(ProcessBuilder processBuilder) throws IOException {
    processBuilder.redirectErrorStream(true);
    if (!logFile.exists()) {
      boolean newFile = logFile.createNewFile();
      if (newFile) {
        String info = String.format("new log file was generated!", "redirect log to file!");
        logger.info(info);
      }
    }
    processBuilder.redirectOutput(logFile);
  }
}

上述代码效果和执行脚本代码类似,使用了maven-assembly-plugin进行打包:

/**
 * @author neters
 */
public class MavenBuild {
  public static void main(String[] args) {
    try {
      ProcessMavenBuilder builder = new ProcessMavenBuilder(new File("/Users/neters/demos/it/log.dat"));
      builder.build("assembly:assembly", "/Users/neters/demos/it");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

效果

虽然可以进行打包,但是这种方式使用过程中存在一些不可控的因素,比如还需要用户指定打包插件类别,插件会对系统环境造成污染等。如果在要求不太高的环境或者场景中可以考虑上述方式,如果对系统环境或者打包过程中有洁癖要求不建议此种方式。

转载请注明:雪后西塘 » Maven集成 – ProcessBuilder

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址