public ArgumentListBuilder toWindowsCommand(boolean escapeVars) {
        ArgumentListBuilder windowsCommand = new ArgumentListBuilder().add("cmd.exe", "/C");
        boolean quoted, percent;
        for (int i = 0; i < args.size(); i++) {
            StringBuilder quotedArgs = new StringBuilder();
            String arg = args.get(i);
            quoted = percent = false;
            for (int j = 0; j < arg.length(); j++) {
                char c = arg.charAt(j);
                if (!quoted && (c == ' ' || c == '*' || c == '?' || c == ',' || c == ';')) {
                    quoted = startQuoting(quotedArgs, arg, j);
                }
                else if (c == '^' || c == '&' || c == '<' || c == '>' || c == '|') {
                    if (!quoted) quoted = startQuoting(quotedArgs, arg, j);
                    // quotedArgs.append('^'); See note in javadoc above
                }
                else if (c == '"') {
                    if (!quoted) quoted = startQuoting(quotedArgs, arg, j);
                    quotedArgs.append('"');
                }
                else if (percent && escapeVars
                         && ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
                    if (!quoted) quoted = startQuoting(quotedArgs, arg, j);
                    quotedArgs.append('"').append(c);
                    c = '"';
                }
                percent = c == '%';
                if (quoted) quotedArgs.append(c);
            }
            if (i == 0) {
                if (quoted) {
                    quotedArgs.insert(0, '"');
                } else {
                    quotedArgs.append('"');
                }
            }
            if (quoted) {
                quotedArgs.append('"');
            } else {
                quotedArgs.append(arg);
            }

            windowsCommand.add(quotedArgs, mask.get(i));
        }
        // (comment copied from old code in hudson.tasks.Ant)
        // on Windows, executing batch file can't return the correct error code,
        // so we need to wrap it into cmd.exe.
        // double %% is needed because we want ERRORLEVEL to be expanded after
        // batch file executed, not before. This alone shows how broken Windows is...
        windowsCommand.add("&&").add("exit").add("%%ERRORLEVEL%%\"");
        return windowsCommand;
    }
@Test
    public void testToWindowsCommand() {
        ArgumentListBuilder builder = new ArgumentListBuilder().
                add("ant.bat").add("-Dfoo1=abc").  // nothing special, no quotes
                add("-Dfoo2=foo bar").add("-Dfoo3=/u*r").add("-Dfoo4=/us?").  // add quotes
                add("-Dfoo10=bar,baz").
                add("-Dfoo5=foo;bar^baz").add("-Dfoo6=<xml>&here;</xml>"). // add quotes
                add("-Dfoo7=foo|bar\"baz"). // add quotes and "" for "
                add("-Dfoo8=% %QED% %comspec% %-%(%.%"). // add quotes, and extra quotes for %Q and %c
                add("-Dfoo9=%'''%%@%"); // no quotes as none of the % are followed by a letter
        // By default, does not escape %VAR%
        assertThat(builder.toWindowsCommand().toCommandArray(), is(new String[] { "cmd.exe", "/C",
                "\"ant.bat", "-Dfoo1=abc", "\"-Dfoo2=foo bar\"", "\"-Dfoo3=/u*r\"", "\"-Dfoo4=/us?\"",
                "\"-Dfoo10=bar,baz\"", "\"-Dfoo5=foo;bar^baz\"", "\"-Dfoo6=<xml>&here;</xml>\"",
                "\"-Dfoo7=foo|bar\"\"baz\"", "\"-Dfoo8=% %QED% %comspec% %-%(%.%\"",
                "-Dfoo9=%'''%%@%", "&&", "exit", "%%ERRORLEVEL%%\"" }));
        // Pass flag to escape %VAR%
        assertThat(builder.toWindowsCommand(true).toCommandArray(), is(new String[] { "cmd.exe", "/C",
                "\"ant.bat", "-Dfoo1=abc", "\"-Dfoo2=foo bar\"", "\"-Dfoo3=/u*r\"", "\"-Dfoo4=/us?\"",
                "\"-Dfoo10=bar,baz\"", "\"-Dfoo5=foo;bar^baz\"", "\"-Dfoo6=<xml>&here;</xml>\"",
                "\"-Dfoo7=foo|bar\"\"baz\"", "\"-Dfoo8=% %\"Q\"ED% %\"c\"omspec% %-%(%.%\"",
                "-Dfoo9=%'''%%@%", "&&", "exit", "%%ERRORLEVEL%%\"" }));
        // Try to hide password
        builder.add("-Dpassword=hidden", true);
        // By default, does not escape %VAR%
        assertThat(builder.toWindowsCommand().toString(), is(
                "cmd.exe /C \"ant.bat -Dfoo1=abc \"\"-Dfoo2=foo bar\"\" \"-Dfoo3=/u*r\" "
                    + "\"-Dfoo4=/us?\" \"-Dfoo10=bar,baz\" \"-Dfoo5=foo;bar^baz\" "
                    + "\"-Dfoo6=<xml>&here;</xml>\" \"-Dfoo7=foo|bar\"\"baz\" "
                    + "\"\"-Dfoo8=% %QED% %comspec% %-%(%.%\"\" -Dfoo9=%'''%%@% ****** "
                    + "&& exit %%ERRORLEVEL%%\""));
        // Pass flag to escape %VAR%
        assertThat(builder.toWindowsCommand(true).toString(), is(
                "cmd.exe /C \"ant.bat -Dfoo1=abc \"\"-Dfoo2=foo bar\"\" \"-Dfoo3=/u*r\" "
                    + "\"-Dfoo4=/us?\" \"-Dfoo10=bar,baz\" \"-Dfoo5=foo;bar^baz\" "
                    + "\"-Dfoo6=<xml>&here;</xml>\" \"-Dfoo7=foo|bar\"\"baz\" "
                    + "\"\"-Dfoo8=% %\"Q\"ED% %\"c\"omspec% %-%(%.%\"\" -Dfoo9=%'''%%@% ****** "
                    + "&& exit %%ERRORLEVEL%%\""));
    }