/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.maven.executor;
import com.liferay.maven.executor.internal.FileUtil;
import com.liferay.maven.executor.internal.Validator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.junit.rules.ExternalResource;
/**
* @author Andrea Di Giorgi
*/
public class MavenExecutor extends ExternalResource {
public Result execute(File projectDir, String... args) throws Exception {
Path mavenHomeDirPath = _checkMavenHomeDirPath();
List<String> commands = new ArrayList<>();
String mavenExecutableFileName = "mvn";
boolean mavenDebug = isMavenDebug();
if (mavenDebug) {
mavenExecutableFileName = "mvnDebug";
}
if (_isWindows()) {
mavenExecutableFileName += ".cmd";
}
Path mavenExecutablePath = mavenHomeDirPath.resolve(
"bin/" + mavenExecutableFileName);
commands.add(String.valueOf(mavenExecutablePath.toAbsolutePath()));
commands.add("--errors");
for (String arg : args) {
commands.add(arg);
}
writeSettingsXmlFile();
ProcessBuilder processBuilder = new ProcessBuilder(commands);
processBuilder.directory(projectDir);
if (mavenDebug) {
processBuilder.inheritIO();
}
Map<String, String> environment = processBuilder.environment();
environment.put(
"M2_HOME", String.valueOf(mavenHomeDirPath.toAbsolutePath()));
environment.put("MAVEN_OPTS", getMavenOpts());
Process process = processBuilder.start();
StringBuilder sb = new StringBuilder();
_append(sb, process.getInputStream());
_append(sb, process.getErrorStream());
int exitCode = process.waitFor();
return new Result(exitCode, sb.toString());
}
public String getHttpNonProxyHosts() {
return System.getProperty("http.nonProxyHosts");
}
public String getHttpProxyHost() {
return System.getProperty("http.proxyHost");
}
public String getHttpProxyPassword() {
return System.getProperty("http.proxyPassword");
}
public int getHttpProxyPort() {
String port = System.getProperty("http.proxyPort");
if (Validator.isNull(port)) {
return 0;
}
return Integer.parseInt(port);
}
public String getHttpProxyUser() {
return System.getProperty("http.proxyUser");
}
public Path getMavenHomeDirPath() {
return _checkMavenHomeDirPath();
}
public Path getMavenLocalRepositoryDirPath() {
String dirName = System.getProperty("maven.repo.local");
if (Validator.isNull(dirName)) {
return null;
}
return Paths.get(dirName);
}
public String getRepositoryUrl() {
return System.getProperty("repository.url");
}
public static class Result {
public final int exitCode;
public final String output;
private Result(int exitCode, String output) {
this.exitCode = exitCode;
this.output = output;
}
}
@Override
protected void after() {
if (_mavenHomeDirPath != null) {
try {
FileUtil.deleteDirectory(_mavenHomeDirPath);
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
@Override
protected void before() throws Throwable {
String mavenDistributionFileName = getMavenDistributionFileName();
if (Validator.isNull(mavenDistributionFileName)) {
throw new IllegalArgumentException(
"Please set the \"maven.distribution.file.name\" system " +
"property");
}
_mavenHomeDirPath = Files.createTempDirectory("maven");
FileUtil.unzip(mavenDistributionFileName, _mavenHomeDirPath, true);
if (!_isWindows()) {
Set<PosixFilePermission> posixFilePermissions =
PosixFilePermissions.fromString("rwxr-xr-x");
Files.setPosixFilePermissions(
_mavenHomeDirPath.resolve("bin/mvn"), posixFilePermissions);
}
};
protected String getMavenDistributionFileName() {
return System.getProperty("maven.distribution.file.name");
}
protected String getMavenOpts() {
return "-Dfile.encoding=UTF-8";
}
protected boolean isMavenDebug() {
return Boolean.getBoolean("maven.debug");
}
protected void writeSettingsXmlFile() throws IOException {
boolean localRepository = false;
boolean mirrors = false;
boolean proxies = false;
Path localRepositoryDirPath = getMavenLocalRepositoryDirPath();
if (localRepositoryDirPath != null) {
localRepository = true;
}
String repositoryUrl = getRepositoryUrl();
if (Validator.isNotNull(repositoryUrl)) {
mirrors = true;
}
String httpProxyHost = getHttpProxyHost();
int httpProxyPort = getHttpProxyPort();
if (Validator.isNotNull(httpProxyHost) && (httpProxyPort > 0)) {
proxies = true;
}
if (!localRepository && !mirrors && !proxies) {
return;
}
String settingsXml = FileUtil.read(
MavenExecutor.class, "dependencies/settings_xml.tmpl");
if (localRepository) {
settingsXml = settingsXml.replace(
"[$LOCAL_REPOSITORY_DIR$]",
FileUtil.getAbsolutePath(localRepositoryDirPath));
}
else {
settingsXml = settingsXml.replaceFirst(
"<localRepository>[\\s\\S]+<\\/localRepository>", "");
}
if (mirrors) {
settingsXml = settingsXml.replace(
"[$REPOSITORY_URL$]", repositoryUrl);
}
else {
settingsXml = settingsXml.replaceFirst(
"<mirrors>[\\s\\S]+<\\/mirrors>", "");
}
if (proxies) {
settingsXml = settingsXml.replace(
"[$HTTP_PROXY_HOST$]", httpProxyHost);
settingsXml = settingsXml.replace(
"[$HTTP_PROXY_PORT$]", String.valueOf(httpProxyPort));
settingsXml = _replaceSettingsXmlElement(
settingsXml, "[$HTTP_PROXY_USERNAME$]", getHttpProxyUser());
settingsXml = _replaceSettingsXmlElement(
settingsXml, "[$HTTP_PROXY_PASSWORD$]", getHttpProxyPassword());
settingsXml = _replaceSettingsXmlElement(
settingsXml, "[$HTTP_PROXY_NON_PROXY_HOSTS$]",
getHttpNonProxyHosts());
}
else {
settingsXml = settingsXml.replaceFirst(
"<proxies>[\\s\\S]+<\\/proxies>", "");
}
Path settingsXmlPath = _mavenHomeDirPath.resolve("conf/settings.xml");
Files.write(
settingsXmlPath, settingsXml.getBytes(StandardCharsets.UTF_8));
}
private static void _append(StringBuilder sb, InputStream inputStream)
throws IOException {
try (BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
String line = null;
while ((line = bufferedReader.readLine()) != null) {
if (sb.length() > 0) {
sb.append(System.lineSeparator());
}
sb.append(line);
}
}
}
private static boolean _isWindows() {
if (File.pathSeparatorChar == ';') {
return true;
}
return false;
}
private static String _replaceSettingsXmlElement(
String settingsXml, String placeholder, String value) {
if (Validator.isNotNull(value)) {
settingsXml = settingsXml.replace(placeholder, value);
}
else {
settingsXml = settingsXml.replaceFirst(
"<\\w+>" + Pattern.quote(placeholder) + "<\\/\\w+>\\s+", "");
}
return settingsXml;
}
private Path _checkMavenHomeDirPath() {
if (_mavenHomeDirPath == null) {
throw new IllegalStateException(
"The Maven home directory has not yet been created");
}
return _mavenHomeDirPath;
}
private Path _mavenHomeDirPath;
}