| 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.Iterator; |
| 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.CommandLineUtils; |
| import org.apache.maven.shared.utils.cli.Commandline; |
| |
| /** |
| * @version $Id$ |
| */ |
| public class MavenCommandLineBuilder |
| { |
| |
| private static final InvokerLogger DEFAULT_LOGGER = new SystemOutLogger(); |
| |
| private InvokerLogger logger = DEFAULT_LOGGER; |
| |
| private File workingDirectory; |
| |
| private File localRepositoryDirectory; |
| |
| private File mavenHome; |
| |
| private File mavenExecutable; |
| |
| private Properties systemEnvVars; |
| |
| public Commandline build( InvocationRequest request ) |
| throws CommandLineConfigurationException |
| { |
| try |
| { |
| checkRequiredState(); |
| } |
| catch ( IOException e ) |
| { |
| throw new CommandLineConfigurationException( e.getMessage(), e ); |
| } |
| File mvn = null; |
| try |
| { |
| mvn = findMavenExecutable(); |
| } |
| catch ( IOException e ) |
| { |
| throw new CommandLineConfigurationException( e.getMessage(), e ); |
| } |
| Commandline cli = new Commandline(); |
| |
| cli.setExecutable( mvn.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 ); |
| |
| // working directory and local repository location |
| setEnvironmentPaths( request, cli ); |
| |
| // pom-file and basedir handling |
| setPomLocation( request, cli ); |
| |
| setSettingsLocation( request, cli ); |
| |
| setToolchainsLocation( request, cli ); |
| |
| setProperties( request, cli ); |
| |
| setProfiles( request, cli ); |
| |
| setGoals( request, cli ); |
| |
| setThreads( request, cli ); |
| |
| return cli; |
| } |
| |
| protected void checkRequiredState() |
| throws IOException |
| { |
| if ( logger == null ) |
| { |
| throw new IllegalStateException( "A logger instance is required." ); |
| } |
| |
| if ( ( mavenHome == null ) && ( System.getProperty( "maven.home" ) == null ) ) |
| // can be restored with 1.5 |
| // && ( System.getenv( "M2_HOME" ) != null ) ) |
| { |
| if ( !getSystemEnvVars().containsKey( "M2_HOME" ) ) |
| { |
| throw new IllegalStateException( "Maven application directory was not " |
| + "specified, and ${maven.home} is not provided in the system " |
| + "properties. Please specify at least on of these." ); |
| } |
| } |
| } |
| |
| protected void setSettingsLocation( InvocationRequest request, Commandline cli ) |
| { |
| File userSettingsFile = request.getUserSettingsFile(); |
| |
| if ( userSettingsFile != null ) |
| { |
| try |
| { |
| File canSet = userSettingsFile.getCanonicalFile(); |
| userSettingsFile = canSet; |
| } |
| 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 |
| { |
| File canSet = globalSettingsFile.getCanonicalFile(); |
| globalSettingsFile = canSet; |
| } |
| 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() ); |
| } |
| |
| } |
| |
| protected void setToolchainsLocation( InvocationRequest request, Commandline cli ) |
| { |
| File toolchainsFile = request.getToolchainsFile(); |
| |
| if ( toolchainsFile != null ) |
| { |
| try |
| { |
| File canSet = toolchainsFile.getCanonicalFile(); |
| toolchainsFile = canSet; |
| } |
| 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() ); |
| } |
| } |
| |
| protected void setShellEnvironment( InvocationRequest request, Commandline cli ) |
| throws CommandLineConfigurationException |
| { |
| if ( request.isShellEnvironmentInherited() ) |
| { |
| try |
| { |
| cli.addSystemEnvironment(); |
| cli.addEnvironment( "MAVEN_TERMINATE_CMD", "on" ); |
| // MSHARED-261: Ensure M2_HOME is not inherited, but gets a |
| // proper value |
| cli.addEnvironment( "M2_HOME", getMavenHome().getAbsolutePath() ); |
| } |
| catch ( Exception e ) |
| { |
| if ( e instanceof RuntimeException ) |
| { |
| throw (RuntimeException) e; |
| } |
| else |
| { |
| IllegalStateException error = |
| new IllegalStateException( "Unknown error retrieving shell environment variables. Reason: " |
| + e.getMessage() ); |
| error.initCause( e ); |
| |
| throw error; |
| } |
| } |
| } |
| |
| 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() ); |
| } |
| } |
| |
| 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(), "," ) ); |
| } |
| |
| } |
| |
| protected void setGoals( InvocationRequest request, Commandline cli ) |
| { |
| List<String> goals = request.getGoals(); |
| |
| if ( ( goals != null ) && !goals.isEmpty() ) |
| { |
| cli.createArg().setLine( StringUtils.join( goals.iterator(), " " ) ); |
| } |
| } |
| |
| protected void setProperties( InvocationRequest request, Commandline cli ) |
| { |
| Properties properties = request.getProperties(); |
| |
| if ( properties != null ) |
| { |
| for ( Iterator<Entry<Object, Object>> it = properties.entrySet().iterator(); it.hasNext(); ) |
| { |
| Entry<Object, Object> entry = it.next(); |
| |
| String key = (String) entry.getKey(); |
| String value = (String) entry.getValue(); |
| |
| cli.createArg().setValue( "-D" ); |
| cli.createArg().setValue( key + '=' + value ); |
| } |
| } |
| } |
| |
| protected void setPomLocation( InvocationRequest request, Commandline cli ) |
| { |
| boolean pomSpecified = false; |
| |
| File pom = request.getPomFile(); |
| String pomFilename = request.getPomFileName(); |
| File baseDirectory = request.getBaseDirectory(); |
| |
| if ( pom != null ) |
| { |
| pomSpecified = true; |
| } |
| else if ( baseDirectory != null ) |
| { |
| if ( baseDirectory.isDirectory() ) |
| { |
| if ( pomFilename != null ) |
| { |
| pom = new File( baseDirectory, pomFilename ); |
| |
| pomSpecified = true; |
| } |
| else |
| { |
| pom = new File( baseDirectory, "pom.xml" ); |
| } |
| } |
| else |
| { |
| logger.warn( "Base directory is a file. Using base directory as POM location." ); |
| |
| pom = baseDirectory; |
| |
| pomSpecified = true; |
| } |
| } |
| |
| if ( pomSpecified ) |
| { |
| try |
| { |
| File canPom = pom.getCanonicalFile(); |
| pom = canPom; |
| } |
| catch ( IOException e ) |
| { |
| logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e ); |
| } |
| |
| 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() ); |
| } |
| } |
| } |
| |
| protected void setEnvironmentPaths( InvocationRequest request, Commandline cli ) |
| { |
| File workingDirectory = request.getBaseDirectory(); |
| |
| if ( workingDirectory == null ) |
| { |
| File pomFile = request.getPomFile(); |
| if ( pomFile != null ) |
| { |
| workingDirectory = pomFile.getParentFile(); |
| } |
| } |
| |
| if ( workingDirectory == null ) |
| { |
| workingDirectory = this.workingDirectory; |
| } |
| |
| if ( workingDirectory == null ) |
| { |
| workingDirectory = new File( System.getProperty( "user.dir" ) ); |
| } |
| else if ( workingDirectory.isFile() ) |
| { |
| logger.warn( "Specified base directory (" + workingDirectory + ") is a file." |
| + " Using its parent directory..." ); |
| |
| workingDirectory = workingDirectory.getParentFile(); |
| } |
| |
| try |
| { |
| cli.setWorkingDirectory( workingDirectory.getCanonicalPath() ); |
| } |
| catch ( IOException e ) |
| { |
| logger.debug( "Failed to canonicalize base directory: " + workingDirectory + ". Using as-is.", e ); |
| |
| cli.setWorkingDirectory( workingDirectory.getAbsolutePath() ); |
| } |
| |
| File localRepositoryDirectory = request.getLocalRepositoryDirectory( this.localRepositoryDirectory ); |
| |
| if ( localRepositoryDirectory != null ) |
| { |
| try |
| { |
| File canLRD = localRepositoryDirectory.getCanonicalFile(); |
| localRepositoryDirectory = canLRD; |
| } |
| 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() ); |
| } |
| } |
| |
| 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" ); |
| } |
| } |
| } |
| |
| 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( request.getBuilder() ); |
| } |
| } |
| |
| protected void setThreads( InvocationRequest request, Commandline cli ) |
| { |
| String threads = request.getThreads(); |
| if ( StringUtils.isNotEmpty( threads ) ) |
| { |
| cli.createArg().setValue( "-T" ); |
| cli.createArg().setValue( threads ); |
| } |
| |
| } |
| |
| protected File findMavenExecutable() |
| throws CommandLineConfigurationException, IOException |
| { |
| if ( mavenHome == null ) |
| { |
| String mavenHomeProperty = System.getProperty( "maven.home" ); |
| if ( mavenHomeProperty != null ) |
| { |
| mavenHome = new File( mavenHomeProperty ); |
| if ( !mavenHome.isDirectory() ) |
| { |
| File binDir = mavenHome.getParentFile(); |
| if ( binDir != null && "bin".equals( binDir.getName() ) ) |
| { |
| // ah, they specified the mvn |
| // executable instead... |
| mavenHome = binDir.getParentFile(); |
| } |
| else |
| { |
| throw new IllegalStateException( "${maven.home} is not specified as a directory: \'" |
| + mavenHomeProperty + "\'." ); |
| } |
| } |
| } |
| |
| if ( ( mavenHome == null ) && ( getSystemEnvVars().getProperty( "M2_HOME" ) != null ) ) |
| { |
| mavenHome = new File( getSystemEnvVars().getProperty( "M2_HOME" ) ); |
| } |
| } |
| |
| logger.debug( "Using ${maven.home} of: \'" + mavenHome + "\'." ); |
| |
| if ( mavenExecutable == null || !mavenExecutable.isAbsolute() ) |
| { |
| String executable; |
| if ( mavenExecutable != null ) |
| { |
| executable = mavenExecutable.getPath(); |
| } |
| else if ( Os.isFamily( "windows" ) ) |
| { |
| if ( new File( mavenHome, "/bin/mvn.cmd" ).exists() ) |
| { |
| executable = "mvn.cmd"; |
| } |
| else |
| { |
| executable = "mvn.bat"; |
| } |
| } |
| else |
| { |
| executable = "mvn"; |
| } |
| |
| mavenExecutable = new File( mavenHome, "/bin/" + executable ); |
| |
| try |
| { |
| File canonicalMvn = mavenExecutable.getCanonicalFile(); |
| mavenExecutable = canonicalMvn; |
| } |
| catch ( IOException e ) |
| { |
| logger.debug( "Failed to canonicalize maven executable: " + mavenExecutable + ". Using as-is.", e ); |
| } |
| |
| if ( !mavenExecutable.isFile() ) |
| { |
| throw new CommandLineConfigurationException( "Maven executable not found at: " + mavenExecutable ); |
| } |
| } |
| |
| return mavenExecutable; |
| } |
| |
| private Properties getSystemEnvVars() |
| throws IOException |
| { |
| if ( this.systemEnvVars == null ) |
| { |
| // with 1.5 replace with System.getenv() |
| this.systemEnvVars = CommandLineUtils.getSystemEnvVars(); |
| } |
| return this.systemEnvVars; |
| } |
| |
| public File getLocalRepositoryDirectory() |
| { |
| return localRepositoryDirectory; |
| } |
| |
| public void setLocalRepositoryDirectory( File localRepositoryDirectory ) |
| { |
| this.localRepositoryDirectory = localRepositoryDirectory; |
| } |
| |
| public InvokerLogger getLogger() |
| { |
| return logger; |
| } |
| |
| public void setLogger( InvokerLogger logger ) |
| { |
| this.logger = logger; |
| } |
| |
| public File getMavenHome() |
| { |
| return mavenHome; |
| } |
| |
| public void setMavenHome( File mavenHome ) |
| { |
| this.mavenHome = mavenHome; |
| } |
| |
| public File getWorkingDirectory() |
| { |
| return workingDirectory; |
| } |
| |
| public void setWorkingDirectory( File workingDirectory ) |
| { |
| this.workingDirectory = workingDirectory; |
| } |
| |
| /** |
| * {@code mavenExecutable} can either be relative to ${maven.home}/bin/ or absolute |
| * |
| * @param mavenExecutable the executable |
| */ |
| public void setMavenExecutable( File mavenExecutable ) |
| { |
| this.mavenExecutable = mavenExecutable; |
| } |
| |
| public File getMavenExecutable() |
| { |
| return mavenExecutable; |
| } |
| |
| } |