You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/07/09 12:35:51 UTC

[commons-exec] branch master updated: Simplify

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-exec.git


The following commit(s) were added to refs/heads/master by this push:
     new 8186ee3  Simplify
8186ee3 is described below

commit 8186ee338f01a1fd90028de88638032cc2dbea64
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Jul 9 08:35:46 2022 -0400

    Simplify
---
 .../java/org/apache/commons/exec/CommandLine.java  | 880 ++++++++++-----------
 1 file changed, 436 insertions(+), 444 deletions(-)

diff --git a/src/main/java/org/apache/commons/exec/CommandLine.java b/src/main/java/org/apache/commons/exec/CommandLine.java
index d2da131..9df00b1 100644
--- a/src/main/java/org/apache/commons/exec/CommandLine.java
+++ b/src/main/java/org/apache/commons/exec/CommandLine.java
@@ -1,444 +1,436 @@
-/*
- * 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.commons.exec;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.apache.commons.exec.util.StringUtils;
-
-/**
- * CommandLine objects help handling command lines specifying processes to
- * execute. The class can be used to a command line by an application.
- *
- */
-public class CommandLine {
-
-    /**
-     * The arguments of the command.
-     */
-    private final Vector<Argument> arguments = new Vector<>();
-
-    /**
-     * The program to execute.
-     */
-    private final String executable;
-
-    /**
-     * A map of name value pairs used to expand command line arguments
-     */
-    private Map<String, ?> substitutionMap; // N.B. This can contain values other than Strings
-
-    /**
-     * Was a file being used to set the executable?
-     */
-    private final boolean isFile;
-
-    /**
-     * Create a command line from a string.
-     *
-     * @param line the first element becomes the executable, the rest the arguments
-     * @return the parsed command line
-     * @throws IllegalArgumentException If line is null or all whitespace
-     */
-    public static CommandLine parse(final String line) {
-        return parse(line, null);
-    }
-
-    /**
-     * Create a command line from a string.
-     *
-     * @param line the first element becomes the executable, the rest the arguments
-     * @param substitutionMap the name/value pairs used for substitution
-     * @return the parsed command line
-     * @throws IllegalArgumentException If line is null or all whitespace
-     */
-    public static CommandLine parse(final String line, final Map<String, ?> substitutionMap) {
-
-        if (line == null) {
-            throw new IllegalArgumentException("Command line can not be null");
-        }
-        if (line.trim().isEmpty()) {
-            throw new IllegalArgumentException("Command line can not be empty");
-        }
-        final String[] tmp = translateCommandline(line);
-
-        final CommandLine cl = new CommandLine(tmp[0]);
-        cl.setSubstitutionMap(substitutionMap);
-        for (int i = 1; i < tmp.length; i++) {
-            cl.addArgument(tmp[i]);
-        }
-
-        return cl;
-    }
-
-    /**
-     * Create a command line without any arguments.
-     *
-     * @param executable the executable
-     */
-    public CommandLine(final String executable) {
-        this.isFile=false;
-        this.executable=toCleanExecutable(executable);
-    }
-
-    /**
-     * Create a command line without any arguments.
-     *
-     * @param  executable the executable file
-     */
-    public CommandLine(final File executable) {
-        this.isFile=true;
-        this.executable=toCleanExecutable(executable.getAbsolutePath());
-    }
-
-    /**
-     * Copy constructor.
-     *
-     * @param other the instance to copy
-     */
-    public CommandLine(final CommandLine other)
-    {
-        this.executable = other.getExecutable();
-        this.isFile = other.isFile();
-        this.arguments.addAll(other.arguments);
-
-        if (other.getSubstitutionMap() != null)
-        {
-            final Map<String, Object> omap = new HashMap<>();
-            this.substitutionMap = omap;
-            final Iterator<String> iterator = other.substitutionMap.keySet().iterator();
-            while (iterator.hasNext())
-            {
-                final String key = iterator.next();
-                omap.put(key, other.getSubstitutionMap().get(key));
-            }
-        }
-    }
-
-    /**
-     * Returns the executable.
-     *
-     * @return The executable
-     */
-    public String getExecutable() {
-        // Expand the executable and replace '/' and '\\' with the platform
-        // specific file separator char. This is safe here since we know
-        // that this is a platform specific command.
-        return StringUtils.fixFileSeparatorChar(expandArgument(executable));
-    }
-
-    /**
-     * Was a file being used to set the executable?
-     *
-     * @return true if a file was used for setting the executable
-     */
-    public boolean isFile() {
-        return isFile;
-    }
-
-    /**
-     * Add multiple arguments. Handles parsing of quotes and whitespace.
-     *
-     * @param addArguments An array of arguments
-     * @return The command line itself
-     */
-    public CommandLine addArguments(final String[] addArguments) {
-        return this.addArguments(addArguments, true);
-    }
-
-    /**
-     * Add multiple arguments.
-     *
-     * @param addArguments An array of arguments
-     * @param handleQuoting Add the argument with/without handling quoting
-     * @return The command line itself
-     */
-    public CommandLine addArguments(final String[] addArguments, final boolean handleQuoting) {
-        if (addArguments != null) {
-            for (final String addArgument : addArguments) {
-                addArgument(addArgument, handleQuoting);
-            }
-        }
-
-        return this;
-    }
-
-    /**
-     * Add multiple arguments. Handles parsing of quotes and whitespace.
-     * Please note that the parsing can have undesired side-effects therefore
-     * it is recommended to build the command line incrementally.
-     *
-     * @param addArguments An string containing multiple arguments.
-     * @return The command line itself
-     */
-    public CommandLine addArguments(final String addArguments) {
-        return this.addArguments(addArguments, true);
-    }
-
-    /**
-     * Add multiple arguments. Handles parsing of quotes and whitespace.
-     * Please note that the parsing can have undesired side-effects therefore
-     * it is recommended to build the command line incrementally.
-     *
-     * @param addArguments An string containing multiple arguments.
-     * @param handleQuoting Add the argument with/without handling quoting
-     * @return The command line itself
-     */
-    public CommandLine addArguments(final String addArguments, final boolean handleQuoting) {
-        if (addArguments != null) {
-            final String[] argumentsArray = translateCommandline(addArguments);
-            addArguments(argumentsArray, handleQuoting);
-        }
-
-        return this;
-    }
-
-    /**
-     * Add a single argument. Handles quoting.
-     *
-     * @param argument The argument to add
-     * @return The command line itself
-     * @throws IllegalArgumentException If argument contains both single and double quotes
-     */
-    public CommandLine addArgument(final String argument) {
-        return this.addArgument(argument, true);
-    }
-
-   /**
-    * Add a single argument.
-    *
-    * @param argument The argument to add
-    * @param handleQuoting Add the argument with/without handling quoting
-    * @return The command line itself
-    */
-   public CommandLine addArgument(final String argument, final boolean handleQuoting) {
-
-       if (argument == null)
-       {
-           return this;
-       }
-
-       // check if we can really quote the argument - if not throw an
-       // IllegalArgumentException
-       if (handleQuoting)
-       {
-           StringUtils.quoteArgument(argument);
-       }
-
-       arguments.add(new Argument(argument, handleQuoting));
-       return this;
-   }
-
-    /**
-     * Returns the expanded and quoted command line arguments.
-     *
-     * @return The quoted arguments
-     */
-    public String[] getArguments() {
-
-        Argument currArgument;
-        String expandedArgument;
-        final String[] result = new String[arguments.size()];
-
-        for (int i=0; i<result.length; i++) {
-            currArgument = arguments.get(i);
-            expandedArgument = expandArgument(currArgument.getValue());
-            result[i] = currArgument.isHandleQuoting() ? StringUtils.quoteArgument(expandedArgument) : expandedArgument;
-        }
-
-        return result;
-    }
-
-    /**
-     * @return the substitution map
-     */
-    public Map<String, ?> getSubstitutionMap() {
-        return substitutionMap;
-    }
-
-    /**
-     * Set the substitutionMap to expand variables in the
-     * command line.
-     *
-     * @param substitutionMap the map
-     */
-    public void setSubstitutionMap(final Map<String, ?> substitutionMap) {
-        this.substitutionMap = substitutionMap;
-    }
-
-    /**
-     * Returns the command line as an array of strings.
-     *
-     * @return The command line as an string array
-     */
-    public String[] toStrings() {
-        final String[] result = new String[arguments.size() + 1];
-        result[0] = this.getExecutable();
-        System.arraycopy(getArguments(), 0, result, 1, result.length-1);
-        return result;
-    }
-
-    /**
-     * Stringify operator returns the command line as a string.
-     * Parameters are correctly quoted when containing a space or
-     * left untouched if the are already quoted.
-     *
-     * @return the command line as single string
-     */
-    @Override
-    public String toString() {
-        return "[" + StringUtils.toString(toStrings(), ", ") + "]";
-    }
-
-    // --- Implementation ---------------------------------------------------
-
-    /**
-     * Expand variables in a command line argument.
-     *
-     * @param argument the argument
-     * @return the expanded string
-     */
-    private String expandArgument(final String argument) {
-        final StringBuffer stringBuffer = StringUtils.stringSubstitution(argument, this.getSubstitutionMap(), true);
-        return stringBuffer.toString();
-    }
-
-    /**
-     * Crack a command line.
-     *
-     * @param toProcess
-     *            the command line to process
-     * @return the command line broken into strings. An empty or null toProcess
-     *         parameter results in a zero sized array
-     */
-    private static String[] translateCommandline(final String toProcess) {
-        if (toProcess == null || toProcess.isEmpty()) {
-            // no command? no string
-            return new String[0];
-        }
-
-        // parse with a simple finite state machine
-
-        final int normal = 0;
-        final int inQuote = 1;
-        final int inDoubleQuote = 2;
-        int state = normal;
-        final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
-        final ArrayList<String> list = new ArrayList<>();
-        StringBuilder current = new StringBuilder();
-        boolean lastTokenHasBeenQuoted = false;
-
-        while (tok.hasMoreTokens()) {
-            final String nextTok = tok.nextToken();
-            switch (state) {
-            case inQuote:
-                if ("\'".equals(nextTok)) {
-                    lastTokenHasBeenQuoted = true;
-                    state = normal;
-                } else {
-                    current.append(nextTok);
-                }
-                break;
-            case inDoubleQuote:
-                if ("\"".equals(nextTok)) {
-                    lastTokenHasBeenQuoted = true;
-                    state = normal;
-                } else {
-                    current.append(nextTok);
-                }
-                break;
-            default:
-                if ("\'".equals(nextTok)) {
-                    state = inQuote;
-                } else if ("\"".equals(nextTok)) {
-                    state = inDoubleQuote;
-                } else if (" ".equals(nextTok)) {
-                    if (lastTokenHasBeenQuoted || current.length() != 0) {
-                        list.add(current.toString());
-                        current = new StringBuilder();
-                    }
-                } else {
-                    current.append(nextTok);
-                }
-                lastTokenHasBeenQuoted = false;
-                break;
-            }
-        }
-
-        if (lastTokenHasBeenQuoted || current.length() != 0) {
-            list.add(current.toString());
-        }
-
-        if (state == inQuote || state == inDoubleQuote) {
-            throw new IllegalArgumentException("Unbalanced quotes in "
-                    + toProcess);
-        }
-
-        final String[] args = new String[list.size()];
-        return list.toArray(args);
-    }
-
-    /**
-     * Cleans the executable string. The argument is trimmed and '/' and '\\' are
-     * replaced with the platform specific file separator char
-     *
-     * @param dirtyExecutable the executable
-     * @return the platform-specific executable string
-     */
-    private String toCleanExecutable(final String dirtyExecutable) {
-        if (dirtyExecutable == null) {
-            throw new IllegalArgumentException("Executable can not be null");
-        }
-        if (dirtyExecutable.trim().isEmpty()) {
-            throw new IllegalArgumentException("Executable can not be empty");
-        }
-        return StringUtils.fixFileSeparatorChar(dirtyExecutable);
-    }
-
-    /**
-     * Encapsulates a command line argument.
-     */
-    class Argument {
-
-        private final String value;
-        private final boolean handleQuoting;
-
-        private Argument(final String value, final boolean handleQuoting)
-        {
-            this.value = value.trim();
-            this.handleQuoting = handleQuoting;
-        }
-
-        private String getValue()
-        {
-            return value;
-        }
-
-        private boolean isHandleQuoting()
-        {
-            return handleQuoting;
-        }
-    }
-}
+/*
+ * 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.commons.exec;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.commons.exec.util.StringUtils;
+
+/**
+ * CommandLine objects help handling command lines specifying processes to
+ * execute. The class can be used to a command line by an application.
+ *
+ */
+public class CommandLine {
+
+    /**
+     * The arguments of the command.
+     */
+    private final Vector<Argument> arguments = new Vector<>();
+
+    /**
+     * The program to execute.
+     */
+    private final String executable;
+
+    /**
+     * A map of name value pairs used to expand command line arguments
+     */
+    private Map<String, ?> substitutionMap; // N.B. This can contain values other than Strings
+
+    /**
+     * Was a file being used to set the executable?
+     */
+    private final boolean isFile;
+
+    /**
+     * Create a command line from a string.
+     *
+     * @param line the first element becomes the executable, the rest the arguments
+     * @return the parsed command line
+     * @throws IllegalArgumentException If line is null or all whitespace
+     */
+    public static CommandLine parse(final String line) {
+        return parse(line, null);
+    }
+
+    /**
+     * Create a command line from a string.
+     *
+     * @param line the first element becomes the executable, the rest the arguments
+     * @param substitutionMap the name/value pairs used for substitution
+     * @return the parsed command line
+     * @throws IllegalArgumentException If line is null or all whitespace
+     */
+    public static CommandLine parse(final String line, final Map<String, ?> substitutionMap) {
+
+        if (line == null) {
+            throw new IllegalArgumentException("Command line can not be null");
+        }
+        if (line.trim().isEmpty()) {
+            throw new IllegalArgumentException("Command line can not be empty");
+        }
+        final String[] tmp = translateCommandline(line);
+
+        final CommandLine cl = new CommandLine(tmp[0]);
+        cl.setSubstitutionMap(substitutionMap);
+        for (int i = 1; i < tmp.length; i++) {
+            cl.addArgument(tmp[i]);
+        }
+
+        return cl;
+    }
+
+    /**
+     * Create a command line without any arguments.
+     *
+     * @param executable the executable
+     */
+    public CommandLine(final String executable) {
+        this.isFile=false;
+        this.executable=toCleanExecutable(executable);
+    }
+
+    /**
+     * Create a command line without any arguments.
+     *
+     * @param  executable the executable file
+     */
+    public CommandLine(final File executable) {
+        this.isFile=true;
+        this.executable=toCleanExecutable(executable.getAbsolutePath());
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the instance to copy
+     */
+    public CommandLine(final CommandLine other)
+    {
+        this.executable = other.getExecutable();
+        this.isFile = other.isFile();
+        this.arguments.addAll(other.arguments);
+
+        if (other.getSubstitutionMap() != null)
+        {
+            this.substitutionMap = new HashMap<>(other.getSubstitutionMap());
+        }
+    }
+
+    /**
+     * Returns the executable.
+     *
+     * @return The executable
+     */
+    public String getExecutable() {
+        // Expand the executable and replace '/' and '\\' with the platform
+        // specific file separator char. This is safe here since we know
+        // that this is a platform specific command.
+        return StringUtils.fixFileSeparatorChar(expandArgument(executable));
+    }
+
+    /**
+     * Was a file being used to set the executable?
+     *
+     * @return true if a file was used for setting the executable
+     */
+    public boolean isFile() {
+        return isFile;
+    }
+
+    /**
+     * Add multiple arguments. Handles parsing of quotes and whitespace.
+     *
+     * @param addArguments An array of arguments
+     * @return The command line itself
+     */
+    public CommandLine addArguments(final String[] addArguments) {
+        return this.addArguments(addArguments, true);
+    }
+
+    /**
+     * Add multiple arguments.
+     *
+     * @param addArguments An array of arguments
+     * @param handleQuoting Add the argument with/without handling quoting
+     * @return The command line itself
+     */
+    public CommandLine addArguments(final String[] addArguments, final boolean handleQuoting) {
+        if (addArguments != null) {
+            for (final String addArgument : addArguments) {
+                addArgument(addArgument, handleQuoting);
+            }
+        }
+
+        return this;
+    }
+
+    /**
+     * Add multiple arguments. Handles parsing of quotes and whitespace.
+     * Please note that the parsing can have undesired side-effects therefore
+     * it is recommended to build the command line incrementally.
+     *
+     * @param addArguments An string containing multiple arguments.
+     * @return The command line itself
+     */
+    public CommandLine addArguments(final String addArguments) {
+        return this.addArguments(addArguments, true);
+    }
+
+    /**
+     * Add multiple arguments. Handles parsing of quotes and whitespace.
+     * Please note that the parsing can have undesired side-effects therefore
+     * it is recommended to build the command line incrementally.
+     *
+     * @param addArguments An string containing multiple arguments.
+     * @param handleQuoting Add the argument with/without handling quoting
+     * @return The command line itself
+     */
+    public CommandLine addArguments(final String addArguments, final boolean handleQuoting) {
+        if (addArguments != null) {
+            final String[] argumentsArray = translateCommandline(addArguments);
+            addArguments(argumentsArray, handleQuoting);
+        }
+
+        return this;
+    }
+
+    /**
+     * Add a single argument. Handles quoting.
+     *
+     * @param argument The argument to add
+     * @return The command line itself
+     * @throws IllegalArgumentException If argument contains both single and double quotes
+     */
+    public CommandLine addArgument(final String argument) {
+        return this.addArgument(argument, true);
+    }
+
+   /**
+    * Add a single argument.
+    *
+    * @param argument The argument to add
+    * @param handleQuoting Add the argument with/without handling quoting
+    * @return The command line itself
+    */
+   public CommandLine addArgument(final String argument, final boolean handleQuoting) {
+
+       if (argument == null)
+       {
+           return this;
+       }
+
+       // check if we can really quote the argument - if not throw an
+       // IllegalArgumentException
+       if (handleQuoting)
+       {
+           StringUtils.quoteArgument(argument);
+       }
+
+       arguments.add(new Argument(argument, handleQuoting));
+       return this;
+   }
+
+    /**
+     * Returns the expanded and quoted command line arguments.
+     *
+     * @return The quoted arguments
+     */
+    public String[] getArguments() {
+
+        Argument currArgument;
+        String expandedArgument;
+        final String[] result = new String[arguments.size()];
+
+        for (int i=0; i<result.length; i++) {
+            currArgument = arguments.get(i);
+            expandedArgument = expandArgument(currArgument.getValue());
+            result[i] = currArgument.isHandleQuoting() ? StringUtils.quoteArgument(expandedArgument) : expandedArgument;
+        }
+
+        return result;
+    }
+
+    /**
+     * @return the substitution map
+     */
+    public Map<String, ?> getSubstitutionMap() {
+        return substitutionMap;
+    }
+
+    /**
+     * Set the substitutionMap to expand variables in the
+     * command line.
+     *
+     * @param substitutionMap the map
+     */
+    public void setSubstitutionMap(final Map<String, ?> substitutionMap) {
+        this.substitutionMap = substitutionMap;
+    }
+
+    /**
+     * Returns the command line as an array of strings.
+     *
+     * @return The command line as an string array
+     */
+    public String[] toStrings() {
+        final String[] result = new String[arguments.size() + 1];
+        result[0] = this.getExecutable();
+        System.arraycopy(getArguments(), 0, result, 1, result.length-1);
+        return result;
+    }
+
+    /**
+     * Stringify operator returns the command line as a string.
+     * Parameters are correctly quoted when containing a space or
+     * left untouched if the are already quoted.
+     *
+     * @return the command line as single string
+     */
+    @Override
+    public String toString() {
+        return "[" + StringUtils.toString(toStrings(), ", ") + "]";
+    }
+
+    // --- Implementation ---------------------------------------------------
+
+    /**
+     * Expand variables in a command line argument.
+     *
+     * @param argument the argument
+     * @return the expanded string
+     */
+    private String expandArgument(final String argument) {
+        final StringBuffer stringBuffer = StringUtils.stringSubstitution(argument, this.getSubstitutionMap(), true);
+        return stringBuffer.toString();
+    }
+
+    /**
+     * Crack a command line.
+     *
+     * @param toProcess
+     *            the command line to process
+     * @return the command line broken into strings. An empty or null toProcess
+     *         parameter results in a zero sized array
+     */
+    private static String[] translateCommandline(final String toProcess) {
+        if (toProcess == null || toProcess.isEmpty()) {
+            // no command? no string
+            return new String[0];
+        }
+
+        // parse with a simple finite state machine
+
+        final int normal = 0;
+        final int inQuote = 1;
+        final int inDoubleQuote = 2;
+        int state = normal;
+        final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
+        final ArrayList<String> list = new ArrayList<>();
+        StringBuilder current = new StringBuilder();
+        boolean lastTokenHasBeenQuoted = false;
+
+        while (tok.hasMoreTokens()) {
+            final String nextTok = tok.nextToken();
+            switch (state) {
+            case inQuote:
+                if ("\'".equals(nextTok)) {
+                    lastTokenHasBeenQuoted = true;
+                    state = normal;
+                } else {
+                    current.append(nextTok);
+                }
+                break;
+            case inDoubleQuote:
+                if ("\"".equals(nextTok)) {
+                    lastTokenHasBeenQuoted = true;
+                    state = normal;
+                } else {
+                    current.append(nextTok);
+                }
+                break;
+            default:
+                if ("\'".equals(nextTok)) {
+                    state = inQuote;
+                } else if ("\"".equals(nextTok)) {
+                    state = inDoubleQuote;
+                } else if (" ".equals(nextTok)) {
+                    if (lastTokenHasBeenQuoted || current.length() != 0) {
+                        list.add(current.toString());
+                        current = new StringBuilder();
+                    }
+                } else {
+                    current.append(nextTok);
+                }
+                lastTokenHasBeenQuoted = false;
+                break;
+            }
+        }
+
+        if (lastTokenHasBeenQuoted || current.length() != 0) {
+            list.add(current.toString());
+        }
+
+        if (state == inQuote || state == inDoubleQuote) {
+            throw new IllegalArgumentException("Unbalanced quotes in "
+                    + toProcess);
+        }
+
+        final String[] args = new String[list.size()];
+        return list.toArray(args);
+    }
+
+    /**
+     * Cleans the executable string. The argument is trimmed and '/' and '\\' are
+     * replaced with the platform specific file separator char
+     *
+     * @param dirtyExecutable the executable
+     * @return the platform-specific executable string
+     */
+    private String toCleanExecutable(final String dirtyExecutable) {
+        if (dirtyExecutable == null) {
+            throw new IllegalArgumentException("Executable can not be null");
+        }
+        if (dirtyExecutable.trim().isEmpty()) {
+            throw new IllegalArgumentException("Executable can not be empty");
+        }
+        return StringUtils.fixFileSeparatorChar(dirtyExecutable);
+    }
+
+    /**
+     * Encapsulates a command line argument.
+     */
+    class Argument {
+
+        private final String value;
+        private final boolean handleQuoting;
+
+        private Argument(final String value, final boolean handleQuoting)
+        {
+            this.value = value.trim();
+            this.handleQuoting = handleQuoting;
+        }
+
+        private String getValue()
+        {
+            return value;
+        }
+
+        private boolean isHandleQuoting()
+        {
+            return handleQuoting;
+        }
+    }
+}