blob: b351d01888db24f6d4bc1a8f529f867860dfa24e [file] [log] [blame]
package org.apache.maven.shared.invoker;
/*
* 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.
*/
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 ( StringUtils.isNotEmpty( threads ) )
{
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 + ".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;
}
}