mojohaus / exec-maven-plugin

Exec Maven Plugin
https://www.mojohaus.org/exec-maven-plugin/
Apache License 2.0
166 stars 97 forks source link

Execution of Windows batch script in path containing blank fails in combination with arguments with quotes #421

Open cgoeller opened 6 months ago

cgoeller commented 6 months ago

Plugin Version 3.2.0 Maven: 3.9.6 Platform: Windows 10

The example contains three executions of which one is failing.

A windows .cmd script is executed which is located in a folder that contains spaces in its name. If the argument to that command contains quotes (single or double quotes) the execution fails.

Without arguments or with plain arguments it works as expected. A .cmd script in a folder without spaces works in all cases.

exec-example.zip

mvn package  
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:exec-demo >------------------------
[INFO] Building exec-demo 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] 
[INFO] --- exec:3.2.0:exec (works) @ exec-demo ---

C:\Temp\exec-example>echo "hi from subfolder" 
"hi from subfolder"
[INFO] 
[INFO] --- exec:3.2.0:exec (works2) @ exec-demo ---

C:\Temp\exec-example>echo "hi from subfolder with spaces" 
"hi from subfolder with spaces"
[INFO] 
[INFO] --- exec:3.2.0:exec (does-not-work) @ exec-demo ---
Der Befehl "C:\Temp\exec-example\subfolder" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
[ERROR] Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
    at org.apache.commons.exec.DefaultExecutor.executeInternal (DefaultExecutor.java:355)
    at org.apache.commons.exec.DefaultExecutor.execute (DefaultExecutor.java:253)
    at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:884)
    at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:844)
    at org.codehaus.mojo.exec.ExecMojo.execute (ExecMojo.java:450)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:568)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.628 s
[INFO] Finished at: 2024-03-20T15:55:00+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.2.0:exec (does-not-work) on project exec-demo: Command execution failed.: Process exited with an error: 1 (Exit value: 1) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
cgoeller commented 6 months ago

It seems as if the bug exists in the apache-commons-exec library (tested with version 1.4.0)

This example app produces the same error message:

package org.example;

import java.io.IOException;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;

public class App {

  public static void main(String[] args) {

    CommandLine commandLine = new CommandLine("C:\\Windows\\system32\\cmd.exe");
    commandLine.addArgument("/c");
    commandLine.addArgument("C:\\Program Files\\nodejs\\npx.cmd");
    commandLine.addArgument("--node-options='--openssl-legacy-provider --max_old_space_size=4096'");

    DefaultExecutor executor = DefaultExecutor.builder().get();
    try {
      int exitValue = executor.execute(commandLine);
      System.out.println(exitValue);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}

The call to org.apache.commons.exec.util.StringUtils#quoteArgument removes the last single quote from the argument, which seems incorrect.

Found some related issues

https://issues.apache.org/jira/browse/EXEC-36 https://issues.apache.org/jira/browse/EXEC-82 https://issues.apache.org/jira/browse/EXEC-83