blob: a6863c24d3d72297c75aae0b40be4d7f34ea714f [file] [log] [blame]
/*
* 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.maven.shared.invoker;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.apache.maven.shared.invoker.InvocationRequest.CheckSumPolicy;
import org.apache.maven.shared.invoker.InvocationRequest.ReactorFailureBehavior;
import org.apache.maven.shared.utils.Os;
import org.apache.maven.shared.utils.StringUtils;
import org.apache.maven.shared.utils.cli.CommandLineException;
import org.apache.maven.shared.utils.cli.Commandline;
/**
* <p>MavenCommandLineBuilder class.</p>
*/
public class MavenCommandLineBuilder {
private static final InvokerLogger DEFAULT_LOGGER = new SystemOutLogger();
private InvokerLogger logger = DEFAULT_LOGGER;
private File baseDirectory;
private File localRepositoryDirectory;
private File mavenHome;
private File mavenExecutable;
/**
* <p>build.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @return a {@link org.apache.maven.shared.utils.cli.Commandline} object.
* @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
*/
public Commandline build(InvocationRequest request) throws CommandLineConfigurationException {
Commandline cli = new Commandline();
setupMavenHome(request);
// discover value for working directory
setupBaseDirectory(request);
cli.setWorkingDirectory(baseDirectory);
checkRequiredState();
setupMavenExecutable(request);
cli.setExecutable(mavenExecutable.getAbsolutePath());
// handling for OS-level envars
setShellEnvironment(request, cli);
// interactive, offline, update-snapshots,
// debug/show-errors, checksum policy
setFlags(request, cli);
// failure behavior and [eventually] forced-reactor
// includes/excludes, etc.
setReactorBehavior(request, cli);
// local repository location
setLocalRepository(request, cli);
// pom-file handling
setPomLocation(request, cli);
setSettingsLocation(request, cli);
setToolchainsLocation(request, cli);
setProperties(request, cli);
setProfiles(request, cli);
setGoals(request, cli);
setThreads(request, cli);
setArgs(request, cli);
return cli;
}
/**
* <p>checkRequiredState.</p>
*/
protected void checkRequiredState() {
if (logger == null) {
throw new IllegalStateException("A logger instance is required.");
}
}
/**
* <p>setSettingsLocation.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setSettingsLocation(InvocationRequest request, Commandline cli) {
File userSettingsFile = request.getUserSettingsFile();
if (userSettingsFile != null) {
try {
userSettingsFile = userSettingsFile.getCanonicalFile();
} catch (IOException e) {
logger.debug(
"Failed to canonicalize user settings path: " + userSettingsFile.getAbsolutePath()
+ ". Using as-is.",
e);
}
cli.createArg().setValue("-s");
cli.createArg().setValue(userSettingsFile.getPath());
}
File globalSettingsFile = request.getGlobalSettingsFile();
if (globalSettingsFile != null) {
try {
globalSettingsFile = globalSettingsFile.getCanonicalFile();
} catch (IOException e) {
logger.debug(
"Failed to canonicalize global settings path: " + globalSettingsFile.getAbsolutePath()
+ ". Using as-is.",
e);
}
cli.createArg().setValue("-gs");
cli.createArg().setValue(globalSettingsFile.getPath());
}
}
/**
* <p>setToolchainsLocation.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setToolchainsLocation(InvocationRequest request, Commandline cli) {
File toolchainsFile = request.getToolchainsFile();
if (toolchainsFile != null) {
try {
toolchainsFile = toolchainsFile.getCanonicalFile();
} catch (IOException e) {
logger.debug(
"Failed to canonicalize toolchains path: " + toolchainsFile.getAbsolutePath()
+ ". Using as-is.",
e);
}
cli.createArg().setValue("-t");
cli.createArg().setValue(toolchainsFile.getPath());
}
}
/**
* <p>setShellEnvironment.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setShellEnvironment(InvocationRequest request, Commandline cli) {
if (request.isShellEnvironmentInherited()) {
cli.addSystemEnvironment();
}
if (request.getJavaHome() != null) {
cli.addEnvironment("JAVA_HOME", request.getJavaHome().getAbsolutePath());
}
if (request.getMavenOpts() != null) {
cli.addEnvironment("MAVEN_OPTS", request.getMavenOpts());
}
for (Map.Entry<String, String> entry : request.getShellEnvironments().entrySet()) {
cli.addEnvironment(entry.getKey(), entry.getValue());
}
}
/**
* <p>setProfiles.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setProfiles(InvocationRequest request, Commandline cli) {
List<String> profiles = request.getProfiles();
if ((profiles != null) && !profiles.isEmpty()) {
cli.createArg().setValue("-P");
cli.createArg().setValue(StringUtils.join(profiles.iterator(), ","));
}
}
/**
* <p>setGoals.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
* @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
*/
protected void setGoals(InvocationRequest request, Commandline cli) throws CommandLineConfigurationException {
List<String> goals = request.getGoals();
if ((goals != null) && !goals.isEmpty()) {
try {
cli.createArg().setLine(StringUtils.join(goals.iterator(), " "));
} catch (CommandLineException e) {
throw new CommandLineConfigurationException("Problem setting goals", e);
}
}
}
/**
* <p>setProperties.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setProperties(InvocationRequest request, Commandline cli) {
Properties properties = request.getProperties();
if (properties != null) {
for (Entry<Object, Object> entry : properties.entrySet()) {
String key = (String) entry.getKey();
String value = (String) entry.getValue();
cli.createArg().setValue("-D");
cli.createArg().setValue(key + '=' + value);
}
}
}
/**
* <p>setPomLocation.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setPomLocation(InvocationRequest request, Commandline cli) {
File pom = request.getPomFile();
String pomFilename = request.getPomFileName();
if (pom == null) {
if (pomFilename != null) {
pom = new File(baseDirectory, pomFilename);
} else {
pom = new File(baseDirectory, "pom.xml");
}
}
try {
pom = pom.getCanonicalFile();
} catch (IOException e) {
logger.debug("Failed to canonicalize the POM path: " + pom + ". Using as-is.", e);
}
if (pom.getParentFile().equals(baseDirectory)) {
// pom in project workspace
if (!"pom.xml".equals(pom.getName())) {
logger.debug("Specified POM file is not named 'pom.xml'. "
+ "Using the '-f' command-line option to accommodate non-standard filename...");
cli.createArg().setValue("-f");
cli.createArg().setValue(pom.getName());
}
} else {
cli.createArg().setValue("-f");
cli.createArg().setValue(pom.getPath());
}
}
void setupBaseDirectory(InvocationRequest request) {
File baseDirectoryFromRequest = null;
if (request.getBaseDirectory() != null) {
baseDirectoryFromRequest = request.getBaseDirectory();
} else {
File pomFile = request.getPomFile();
if (pomFile != null) {
baseDirectoryFromRequest = pomFile.getParentFile();
}
}
if (baseDirectoryFromRequest != null) {
baseDirectory = baseDirectoryFromRequest;
}
if (baseDirectory == null) {
baseDirectory = new File(System.getProperty("user.dir"));
} else if (baseDirectory.isFile()) {
logger.warn(
"Specified base directory (" + baseDirectory + ") is a file." + " Using its parent directory...");
baseDirectory = baseDirectory.getParentFile();
}
try {
baseDirectory = baseDirectory.getCanonicalFile();
} catch (IOException e) {
logger.debug("Failed to canonicalize base directory: " + baseDirectory + ". Using as-is.", e);
}
}
/**
* <p>setLocalRepository.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setLocalRepository(InvocationRequest request, Commandline cli) {
File localRepositoryDirectory = request.getLocalRepositoryDirectory(this.localRepositoryDirectory);
if (localRepositoryDirectory != null) {
try {
localRepositoryDirectory = localRepositoryDirectory.getCanonicalFile();
} catch (IOException e) {
logger.debug(
"Failed to canonicalize local repository directory: " + localRepositoryDirectory
+ ". Using as-is.",
e);
}
if (!localRepositoryDirectory.isDirectory()) {
throw new IllegalArgumentException(
"Local repository location: '" + localRepositoryDirectory + "' is NOT a directory.");
}
cli.createArg().setValue("-D");
cli.createArg().setValue("maven.repo.local=" + localRepositoryDirectory.getPath());
}
}
/**
* <p>setReactorBehavior.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setReactorBehavior(InvocationRequest request, Commandline cli) {
// NOTE: The default is "fail-fast"
ReactorFailureBehavior failureBehavior = request.getReactorFailureBehavior();
if (failureBehavior != null) {
if (ReactorFailureBehavior.FailAtEnd.equals(failureBehavior)) {
cli.createArg().setValue("-" + ReactorFailureBehavior.FailAtEnd.getShortOption());
} else if (ReactorFailureBehavior.FailNever.equals(failureBehavior)) {
cli.createArg().setValue("-" + ReactorFailureBehavior.FailNever.getShortOption());
}
}
if (StringUtils.isNotEmpty(request.getResumeFrom())) {
cli.createArg().setValue("-rf");
cli.createArg().setValue(request.getResumeFrom());
}
List<String> projectList = request.getProjects();
if (projectList != null) {
cli.createArg().setValue("-pl");
cli.createArg().setValue(StringUtils.join(projectList.iterator(), ","));
if (request.isAlsoMake()) {
cli.createArg().setValue("-am");
}
if (request.isAlsoMakeDependents()) {
cli.createArg().setValue("-amd");
}
}
}
/**
* <p>setFlags.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setFlags(InvocationRequest request, Commandline cli) {
if (request.isBatchMode()) {
cli.createArg().setValue("-B");
}
if (request.isOffline()) {
cli.createArg().setValue("-o");
}
if (request.isUpdateSnapshots()) {
cli.createArg().setValue("-U");
}
if (!request.isRecursive()) {
cli.createArg().setValue("-N");
}
if (request.isDebug()) {
cli.createArg().setValue("-X");
}
// this is superseded by -X, if it exists.
else if (request.isShowErrors()) {
cli.createArg().setValue("-e");
}
CheckSumPolicy checksumPolicy = request.getGlobalChecksumPolicy();
if (CheckSumPolicy.Fail.equals(checksumPolicy)) {
cli.createArg().setValue("-C");
} else if (CheckSumPolicy.Warn.equals(checksumPolicy)) {
cli.createArg().setValue("-c");
}
if (request.isNonPluginUpdates()) {
cli.createArg().setValue("-npu");
}
if (request.isShowVersion()) {
cli.createArg().setValue("-V");
}
if (request.getBuilder() != null) {
cli.createArg().setValue("-b");
cli.createArg().setValue(request.getBuilder());
}
if (request.isQuiet()) {
cli.createArg().setValue("-q");
}
if (request.isNoTransferProgress()) {
cli.createArg().setValue("-ntp");
}
}
/**
* <p>setThreads.</p>
*
* @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
* @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
*/
protected void setThreads(InvocationRequest request, Commandline cli) {
String threads = request.getThreads();
if (threads != null && !threads.isEmpty()) {
cli.createArg().setValue("-T");
cli.createArg().setValue(threads);
}
}
private void setArgs(InvocationRequest request, Commandline cli) {
for (String arg : request.getArgs()) {
cli.createArg().setValue(arg);
}
}
private void setupMavenHome(InvocationRequest request) {
if (request.getMavenHome() != null) {
mavenHome = request.getMavenHome();
} else if (System.getProperty("maven.home") != null) {
mavenHome = new File(System.getProperty("maven.home"));
}
if (mavenHome != null && !mavenHome.isDirectory()) {
File binDir = mavenHome.getParentFile();
if (binDir != null && "bin".equals(binDir.getName())) {
// ah, they specified the mvn
// executable instead...
mavenHome = binDir.getParentFile();
}
}
if (mavenHome != null && !mavenHome.isDirectory()) {
throw new IllegalStateException("Maven home is set to: '" + mavenHome + "' which is not a directory");
}
logger.debug("Using maven.home of: '" + mavenHome + "'.");
}
/**
* <p>setupMavenExecutable.</p>
*
* @param request a Invoker request
* @throws org.apache.maven.shared.invoker.CommandLineConfigurationException if any.
*/
protected void setupMavenExecutable(InvocationRequest request) throws CommandLineConfigurationException {
if (request.getMavenExecutable() != null) {
mavenExecutable = request.getMavenExecutable();
}
if (mavenExecutable == null || !mavenExecutable.isAbsolute()) {
String executable;
if (mavenExecutable != null) {
executable = mavenExecutable.getPath();
} else {
executable = "mvn";
}
// firs look in project directory
mavenExecutable = detectMavenExecutablePerOs(baseDirectory, executable);
if (mavenExecutable == null) {
// next maven home
mavenExecutable = detectMavenExecutablePerOs(mavenHome, "/bin/" + executable);
}
if (mavenExecutable != null) {
try {
mavenExecutable = mavenExecutable.getCanonicalFile();
} catch (IOException e) {
logger.debug("Failed to canonicalize maven executable: '" + mavenExecutable + "'. Using as-is.", e);
}
} else {
throw new CommandLineConfigurationException("Maven executable: '" + executable + "'"
+ " not found at project dir: '" + baseDirectory + "' nor maven home: '" + mavenHome + "'");
}
}
}
private File detectMavenExecutablePerOs(File baseDirectory, String executable) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
File executableFile = new File(baseDirectory, executable + ".ps1");
if (executableFile.isFile()) {
return executableFile;
}
executableFile = new File(baseDirectory, executable + ".cmd");
if (executableFile.isFile()) {
return executableFile;
}
executableFile = new File(baseDirectory, executable + ".bat");
if (executableFile.isFile()) {
return executableFile;
}
}
File executableFile = new File(baseDirectory, executable);
if (executableFile.isFile()) {
return executableFile;
}
return null;
}
/**
* <p>Getter for the field <code>localRepositoryDirectory</code>.</p>
*
* @return a {@link java.io.File} object.
*/
public File getLocalRepositoryDirectory() {
return localRepositoryDirectory;
}
/**
* <p>Setter for the field <code>localRepositoryDirectory</code>.</p>
*
* @param localRepositoryDirectory a {@link java.io.File} object.
*/
public void setLocalRepositoryDirectory(File localRepositoryDirectory) {
this.localRepositoryDirectory = localRepositoryDirectory;
}
/**
* <p>Getter for the field <code>logger</code>.</p>
*
* @return a {@link org.apache.maven.shared.invoker.InvokerLogger} object.
*/
public InvokerLogger getLogger() {
return logger;
}
/**
* <p>Setter for the field <code>logger</code>.</p>
*
* @param logger a {@link org.apache.maven.shared.invoker.InvokerLogger} object.
*/
public void setLogger(InvokerLogger logger) {
this.logger = logger;
}
/**
* <p>Getter for the field <code>mavenHome</code>.</p>
*
* @return a {@link java.io.File} object.
*/
public File getMavenHome() {
return mavenHome;
}
/**
* <p>Setter for the field <code>mavenHome</code>.</p>
*
* @param mavenHome a {@link java.io.File} object.
*/
public void setMavenHome(File mavenHome) {
this.mavenHome = mavenHome;
}
/**
* <p>Getter for the field <code>baseDirectory</code>.</p>
*
* @return a {@link java.io.File} object.
*/
public File getBaseDirectory() {
return baseDirectory;
}
/**
* <p>Setter for the field <code>baseDirectory</code>.</p>
*
* @param baseDirectory a {@link java.io.File} object.
*/
public void setBaseDirectory(File baseDirectory) {
this.baseDirectory = baseDirectory;
}
/**
* {@code mavenExecutable} can either be relative to ${maven.home}/bin/ or absolute
*
* @param mavenExecutable the executable
*/
public void setMavenExecutable(File mavenExecutable) {
this.mavenExecutable = mavenExecutable;
}
/**
* <p>Getter for the field <code>mavenExecutable</code>.</p>
*
* @return a {@link java.io.File} object.
*/
public File getMavenExecutable() {
return mavenExecutable;
}
}