Commons Exec
  1. Commons Exec
  2. EXEC-54

Problem with argument containing spaces

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.1
    • Fix Version/s: None
    • Environment:

      Mac OsX 10.6.6, JVM 1.6.0

      Description

      I am new to Commons Exec, so this could also be an error in usage, but...

      When I use the CommandLine class to add a argument that contains spaces, some quotes are added and are then part of the argument that is given.

      For example: When I call java "what version" I get java.lang.NoClassDefFoundError: what version, and when I call java "\"what version\"" (which contains escaped quotes, that are part of the command line argument itself), I get java.lang.NoClassDefFoundError: "what version".

      So the following test fails, because as you can see in the last line, Apache Exec is producing the latter version where it should have produced the first version:

      	@Test
      	public void testArgumentQuoting() throws Exception {
      		String argument = "what version";
      		DefaultExecutor executor = new DefaultExecutor();
      		DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
      		ByteArrayOutputStream out = new ByteArrayOutputStream();
      		PumpStreamHandler streamHandler = new PumpStreamHandler(out, out);
      		executor.setStreamHandler(streamHandler);
      		CommandLine cmdLine = new CommandLine("java");
      		cmdLine.addArgument(argument);
      		executor.execute(cmdLine, resultHandler);
      		resultHandler.waitFor();
      		String resultPattern = "Exception in thread \"main\" java\\.lang\\.NoClassDefFoundError: ([\\w \"]+)";
      		Pattern pattern = Pattern.compile(resultPattern);
      		Matcher matcher = pattern.matcher(out.toString());
      		Assert.assertTrue(matcher.find());
      		// Note: Result should be <what version> and NOT <"what version">!
      		Assert.assertEquals(argument, matcher.group(1));
      	}
      

      Note that the same test passes if the space is removed from the argument. Please also note, that I am not trying to start an external Java process, but this is merely an example that I assume will work on every developers machine.

        Activity

        Jeremias Rößler created issue -
        Hide
        Siegfried Goeschl added a comment -

        No - the code works a intended. Lets assume that your argument is not "what version" but "C:\Document And Settings\documents\432432.pdf" - in that case it is helpful to automatically quote the argument (in that case a file name) otherwise the callee will get three command line arguments instead of one

        • C:\Document
        • And
        • Settings\documents\432432.pdf
        Show
        Siegfried Goeschl added a comment - No - the code works a intended. Lets assume that your argument is not "what version" but "C:\Document And Settings\documents\432432.pdf" - in that case it is helpful to automatically quote the argument (in that case a file name) otherwise the callee will get three command line arguments instead of one C:\Document And Settings\documents\432432.pdf
        Siegfried Goeschl made changes -
        Field Original Value New Value
        Assignee Siegfried Goeschl [ sgoeschl ]
        Hide
        Jeremias Rößler added a comment -

        Sorry for being not clear enough: My point is that the argument is doubly quoted, and the first quotes are then escaped and become part of the argument itself, which is definitely not what is intended. To stick to your example, the argument being given to the process is not "C:\Document And Settings\documents\432432.pdf" which would be correct, but "\"C:\Document And Settings\documents\432432.pdf\"" (note the double and escaped quotes).

        Show
        Jeremias Rößler added a comment - Sorry for being not clear enough: My point is that the argument is doubly quoted, and the first quotes are then escaped and become part of the argument itself, which is definitely not what is intended. To stick to your example, the argument being given to the process is not "C:\Document And Settings\documents\432432.pdf" which would be correct, but "\"C:\Document And Settings\documents\432432.pdf\"" (note the double and escaped quotes).
        Hide
        Rupert Westenthaler added a comment -

        Came along the same "Issue" but with a different conclusion. (see http://markmail.org/message/xbcseasols7ae2mc for details)

        In short:

        Commons Exec does NOT double quote the parameter. The problem is that the "java" executable does not support quoted jar files (see also http://stackoverflow.com/questions/5569591/unable-to-access-jarfile-in-linux-land).

        So I assume this issue can be closed. However I would still be interested in an utility that can be used to escape (instead of quote) parsed parameters. This would be very handy when calling executable (like java) that do not interpret quotation marks.

        Show
        Rupert Westenthaler added a comment - Came along the same "Issue" but with a different conclusion. (see http://markmail.org/message/xbcseasols7ae2mc for details) In short: Commons Exec does NOT double quote the parameter. The problem is that the "java" executable does not support quoted jar files (see also http://stackoverflow.com/questions/5569591/unable-to-access-jarfile-in-linux-land ). So I assume this issue can be closed. However I would still be interested in an utility that can be used to escape (instead of quote) parsed parameters. This would be very handy when calling executable (like java) that do not interpret quotation marks.
        Hide
        Sebb added a comment -

        Note that the quoting / escaping requirements vary by OS.
        AFAIK, not all OSes support escapes, and the mechanism may vary depending on the shell that is used.

        Show
        Sebb added a comment - Note that the quoting / escaping requirements vary by OS. AFAIK, not all OSes support escapes, and the mechanism may vary depending on the shell that is used.
        Hide
        Dominik Stadler added a comment -

        This just hit me for the second time and it was really a pain to debug. I see that both ways of doing quoting and not doing quoting have their use, what I don't understand is the default of doing this quote-handling always unless turned off by passing "false" to addArgument().

        Why is it necessary when you later pass a String[]-Array with separate arguments to the Runtime.exec() method in Java13CommandLauncher anyway. Isn't this also supposed to handle blanks correctly and thus we are doing the same thing twice here?

        I see that other Launcher-Implementations use versions where they pass one String to the exec-call, so it seems the question of quoting is dependent on which exact Launcher you are using, shouldn't the default be based on that then?

        Show
        Dominik Stadler added a comment - This just hit me for the second time and it was really a pain to debug. I see that both ways of doing quoting and not doing quoting have their use, what I don't understand is the default of doing this quote-handling always unless turned off by passing "false" to addArgument(). Why is it necessary when you later pass a String[]-Array with separate arguments to the Runtime.exec() method in Java13CommandLauncher anyway. Isn't this also supposed to handle blanks correctly and thus we are doing the same thing twice here? I see that other Launcher-Implementations use versions where they pass one String to the exec-call, so it seems the question of quoting is dependent on which exact Launcher you are using, shouldn't the default be based on that then?
        Hide
        DHadka added a comment - - edited

        I'm running into a similar issue as above. In my case, I want to pass a folder on the command line, such as C:\Documents and Settings\user\folder. So I call

        command.addArgument("C:\\Documents and Settings\\user\\folder\\")

        Commons Exec then adds the quotes around the argument. But on Windows, the trailing \ in the path escapes the quote, which then is passed as part of the argument. In this case, the program receives the argument as: C:\Documents and Settings\users\folder", with the quote as part of the argument. This creates a subtle and hard to track error condition.

        Consider these cases:
        C:\NoSpace\in\path - Works correctly
        C:\NoSpace\in\path\ - Works correctly (no quotes are added since no spaces in path)
        C:/NoSpace/in/path - Works correctly
        C:/NoSpace/in/path/ - Works correctly
        C:\With Space\in\path - Works correctly
        C:\With Space\in\path\ - Fails due to this bug
        C:/With Space/in/path - Works correctly
        C:/With Space/in/path/ - Works correctly

        Show
        DHadka added a comment - - edited I'm running into a similar issue as above. In my case, I want to pass a folder on the command line, such as C:\Documents and Settings\user\folder . So I call command.addArgument("C:\\Documents and Settings\\user\\folder\\") Commons Exec then adds the quotes around the argument. But on Windows, the trailing \ in the path escapes the quote, which then is passed as part of the argument. In this case, the program receives the argument as: C:\Documents and Settings\users\folder" , with the quote as part of the argument. This creates a subtle and hard to track error condition. Consider these cases: C:\NoSpace\in\path - Works correctly C:\NoSpace\in\path\ - Works correctly (no quotes are added since no spaces in path) C:/NoSpace/in/path - Works correctly C:/NoSpace/in/path/ - Works correctly C:\With Space\in\path - Works correctly C:\With Space\in\path\ - Fails due to this bug C:/With Space/in/path - Works correctly C:/With Space/in/path/ - Works correctly

          People

          • Assignee:
            Siegfried Goeschl
            Reporter:
            Jeremias Rößler
          • Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:

              Development