| /* |
| * 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; |
| } |
| } |