All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.exec.CommandLine Maven / Gradle / Ivy

The newest version!
/* 
 * 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 org.apache.commons.exec.util.StringUtils;

import java.io.File;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Map;

/**
 * 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 {

    private static final String SINGLE_QUOTE = "\'";

    private static final String DOUBLE_QUOTE = "\"";

    /**
     * The arguments of the command.
     */
    private Vector arguments = new Vector();

    /**
     * The program to execute.
     */
    private String executable = null;

    /**
     * A map of name value pairs used to expand command line arguments
     */
    private Map substitutionMap;

    private final boolean isFile;

    /**
     * Create a command line from a string.
     * 
     * @param line
     *            the 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 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, Map substitutionMap) {
                
        if (line == null) {
            throw new IllegalArgumentException("Command line can not be null");
        } else if (line.trim().length() == 0) {
            throw new IllegalArgumentException("Command line can not be empty");
        } else {
            String[] tmp = translateCommandline(line);

            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(String executable) {
        this.isFile=false;
        setExecutable(executable);
    }

    /**
     * Create a command line without any arguments.
     *
     * @param  executable the executable 
     */
    public CommandLine(File executable) {
        this.isFile=true;
        setExecutable(executable.getAbsolutePath());
    }

    /**
     * Returns the executable
     * 
     * @return The executable
     */
    public String getExecutable() {
        return this.expandArgument(executable);
    }

    public boolean isFile(){
        return isFile;
    }

    /**
     * Add multiple arguments. Handles parsing of quotes and whitespace.
     * 
     * @param arguments An array of arguments
     * @return The command line itself
     */
    public CommandLine addArguments(final String[] arguments) {
        return this.addArguments(arguments, true);
    }

    /**
     * Add multiple arguments.
     *
     * @param arguments An array of arguments
     * @param handleQuoting Add the argument with/without handling quoting
     * @return The command line itself
     */
    public CommandLine addArguments(final String[] arguments, boolean handleQuoting) {
        if (arguments != null) {
            for (int i = 0; i < arguments.length; i++) {
                addArgument(arguments[i], handleQuoting);
            }
        }

        return this;
    }

    /**
     * Add multiple arguments. Handles parsing of quotes and whitespace.
     * 
     * @param arguments An string containing multiple arguments. 
     * @return The command line itself
     */
    public CommandLine addArguments(final String arguments) {
        return this.addArguments(arguments, true);
    }

    /**
     * Add multiple arguments. Handles parsing of quotes and whitespace.
     *
     * @param arguments An string containing multiple arguments.
     * @param handleQuoting Add the argument with/without handling quoting
     * @return The command line itself
     */
    public CommandLine addArguments(final String arguments, boolean handleQuoting) {
        if (arguments != null) {
            String[] argmentsArray = translateCommandline(arguments);
            addArguments(argmentsArray, 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, boolean handleQuoting) {
        if (argument == null) {
           return this;
        }

        if(handleQuoting) {
            arguments.add(quoteArgument(argument));
        }
        else {
            arguments.add(argument);
        }

        return this;
   }

    /**
     * Returns the quoted arguments 
     * @return The quoted arguments
     */
    public String[] getArguments() {
        String[] result = new String[arguments.size()];
        result = (String[]) arguments.toArray(result);
        return this.expandArguments(result);
    }

    /**
     * @return the substitution map
     */
    public Map getSubstitutionMap() {
        return substitutionMap;
    }

    /**
     * Set the substitutionMap to expand variables in the
     * command line
     * @param substitutionMap the map
     */
    public void setSubstitutionMap(Map substitutionMap) {
        this.substitutionMap = substitutionMap;
    }

    // --- Implementation ---------------------------------------------------

    /**
     * Put quotes around the given String if necessary.
     * 

* If the argument doesn't include spaces or quotes, return it as is. If it * contains double quotes, use single quotes - else surround the argument by * double quotes. *

* * @param argument the argument to be quoted * @return the quoted argument * @throws IllegalArgumentException If argument contains both types of quotes */ private static String quoteArgument(final String argument) { String cleanedArgument = argument.trim(); while(cleanedArgument.startsWith(SINGLE_QUOTE) || cleanedArgument.startsWith(DOUBLE_QUOTE)) { cleanedArgument = cleanedArgument.substring(1); } while(cleanedArgument.endsWith(SINGLE_QUOTE) || cleanedArgument.endsWith(DOUBLE_QUOTE)) { cleanedArgument = cleanedArgument.substring(0, cleanedArgument.length() - 1); } final StringBuffer buf = new StringBuffer(); if (cleanedArgument.indexOf(DOUBLE_QUOTE) > -1) { if (cleanedArgument.indexOf(SINGLE_QUOTE) > -1) { throw new IllegalArgumentException( "Can't handle single and double quotes in same argument"); } else { return buf.append(SINGLE_QUOTE).append(cleanedArgument).append( SINGLE_QUOTE).toString(); } } else if (cleanedArgument.indexOf(SINGLE_QUOTE) > -1 || cleanedArgument.indexOf(" ") > -1) { return buf.append(DOUBLE_QUOTE).append(cleanedArgument).append( DOUBLE_QUOTE).toString(); } else { return cleanedArgument; } } /** * Expand variables in a command line argument. * * @param argument the argument * @return the expanded string */ private String expandArgument(final String argument) { StringBuffer stringBuffer = StringUtils.stringSubstitution(argument, this.getSubstitutionMap(), true); return stringBuffer.toString(); } /** * Expand variables in a command line arguments. * * @param arguments the arguments to be expadedn * @return the expanded string */ private String[] expandArguments(final String[] arguments) { String[] result = new String[arguments.length]; for(int i=0; i 0) { sb.append(' '); } sb.append(strings[i]); } return sb.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.length() == 0) { // 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; StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true); Vector v = new Vector(); StringBuffer current = new StringBuffer(); boolean lastTokenHasBeenQuoted = false; while (tok.hasMoreTokens()) { 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) { v.addElement(current.toString()); current = new StringBuffer(); } } else { current.append(nextTok); } lastTokenHasBeenQuoted = false; break; } } if (lastTokenHasBeenQuoted || current.length() != 0) { v.addElement(current.toString()); } if (state == inQuote || state == inDoubleQuote) { throw new IllegalArgumentException("Unbalanced quotes in " + toProcess); } String[] args = new String[v.size()]; v.copyInto(args); return args; } private void setExecutable(final String executable) { if (executable == null) { throw new IllegalArgumentException("Executable can not be null"); } else if(executable.trim().length() == 0) { throw new IllegalArgumentException("Executable can not be empty"); } else { this.executable = executable.replace('/', File.separatorChar).replace( '\\', File.separatorChar); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy