| /* ProcessBuilder.java - Represent spawned system process | |
| Copyright (C) 2005 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.lang; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.util.Arrays; | |
| import java.util.List; | |
| import java.util.Map; | |
| /** | |
| * <p> | |
| * This class is used to construct new operating system processes. | |
| * A <code>ProcessBuilder</code> instance basically represent a | |
| * template for a new process. Actual processes are generated from | |
| * this template via use of the <code>start()</code> method, which | |
| * may be invoked multiple times, with each invocation spawning a | |
| * new process with the current attributes of the | |
| * <code>ProcessBuilder</code> object. Each spawned process is | |
| * independent of the <code>ProcessBuilder</code> object, and is | |
| * unaffected by changes in its attributes. | |
| * </p> | |
| * <p> | |
| * The following attributes define a process: | |
| * </p> | |
| * <ul> | |
| * <li>The <emphasis>working directory</emphasis>; the activities of a | |
| * process begin with the current directory set to this. By default, | |
| * this is the working directory of the current process, as defined | |
| * by the <code>user.dir</code> property.</li> | |
| * <li>The <emphasis>command</emphasis> which invokes the process. This | |
| * usually consists of the name of the program binary followed by an | |
| * arbitrary number of arguments. For example, <code>find -type f</code> | |
| * invokes the <code>find</code> binary with the arguments "-type" and "f". | |
| * The command is provided a list, the elements of which are defined in a | |
| * system dependent manner; the layout is affected by expected operating | |
| * system conventions. A common method is to split the command on each | |
| * space within the string. Thus, <code>find -type f</code> forms a | |
| * three element list. However, in some cases, the expectation is that | |
| * this split is performed by the program itself; thus, the list consists | |
| * of only two elements (the program name and its arguments).</li> | |
| * <li>The <emphasis>environment map</emphasis>, which links environment | |
| * variables to their corresponding values. The initial contents of the map | |
| * are the current environment values i.e. it contains the contents of the | |
| * map returned by <code>System.getenv()</code>.</li> | |
| * <li>The <emphasis>redirection flag</emphasis>, which specifies whether | |
| * or not the contents of the error stream should be redirected to standard | |
| * output. By default, this is false, and there are two output streams, one | |
| * for normal data ({@link Process#getOutputStream()}) and one for error data | |
| * ({@link Process#getErrorStream()}). When set to true, the two are merged, | |
| * which simplifies the interleaving of the two streams. Data is read using | |
| * the stream returned by {@link Process#getOutputStream()}, and the | |
| * stream returned by {@link Process#getErrorStream()} throws an immediate | |
| * end-of-file exception.</li> | |
| * </ul> | |
| * <p> | |
| * All checks on attribute validity are delayed until <code>start()</code> | |
| * is called. <code>ProcessBuilder</code> objects are <strong>not | |
| * synchronized</strong>; the user must provide external synchronization | |
| * where multiple threads may interact with the same | |
| * <code>ProcessBuilder</code> object. | |
| * </p> | |
| * | |
| * @author Tom Tromey (tromey@redhat.com) | |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) | |
| * @see Process | |
| * @see System#getenv() | |
| * @since 1.5 | |
| */ | |
| public final class ProcessBuilder | |
| { | |
| /** | |
| * The working directory of the process. | |
| */ | |
| private File directory = new File(System.getProperty("user.dir")); | |
| /** | |
| * The command line syntax for invoking the process. | |
| */ | |
| private List<String> command; | |
| /** | |
| * The mapping of environment variables to values. | |
| */ | |
| private Map<String, String> environment = | |
| new System.EnvironmentMap(System.getenv()); | |
| /** | |
| * A flag indicating whether to redirect the error stream to standard | |
| * output. | |
| */ | |
| private boolean redirect = false; | |
| /** | |
| * Constructs a new <code>ProcessBuilder</code> with the specified | |
| * command being used to invoke the process. The list is used directly; | |
| * external changes are reflected in the <code>ProcessBuilder</code>. | |
| * | |
| * @param command the name of the program followed by its arguments. | |
| */ | |
| public ProcessBuilder(List<String> command) | |
| { | |
| this.command = command; | |
| } | |
| /** | |
| * Constructs a new <code>ProcessBuilder</code> with the specified | |
| * command being used to invoke the process. This constructor | |
| * simplifies creating a new <code>ProcessBuilder</code> by | |
| * converting the provided series of constructor arguments into a | |
| * list of command-line arguments. | |
| * | |
| * @param command the name of the program followed by its arguments. | |
| */ | |
| public ProcessBuilder(String... command) | |
| { | |
| this.command = Arrays.asList(command); | |
| } | |
| /** | |
| * Returns the current command line, used to invoke the process. | |
| * The return value is simply a reference to the list of command | |
| * line arguments used by the <code>ProcessBuilder</code> object; | |
| * any changes made to it will be reflected in the operation of | |
| * the <code>ProcessBuilder</code>. | |
| * | |
| * @return the list of command-line arguments. | |
| */ | |
| public List<String> command() | |
| { | |
| return command; | |
| } | |
| /** | |
| * Sets the command-line arguments to those specified. The list is | |
| * used directly; external changes are reflected in the | |
| * <code>ProcessBuilder</code>. | |
| * | |
| * @param command the name of the program followed by its arguments. | |
| * @return a reference to this process builder. | |
| */ | |
| public ProcessBuilder command(List<String> command) | |
| { | |
| this.command = command; | |
| return this; | |
| } | |
| /** | |
| * Sets the command-line arguments to those specified. | |
| * This simplifies modifying the arguments by converting | |
| * the provided series of constructor arguments into a | |
| * list of command-line arguments. | |
| * | |
| * @param command the name of the program followed by its arguments. | |
| * @return a reference to this process builder. | |
| */ | |
| public ProcessBuilder command(String... command) | |
| { | |
| this.command = Arrays.asList(command); | |
| return this; | |
| } | |
| /** | |
| * Returns the working directory of the process. The | |
| * returned value may be <code>null</code>; this | |
| * indicates that the default behaviour of using the | |
| * working directory of the current process should | |
| * be adopted. | |
| * | |
| * @return the working directory. | |
| */ | |
| public File directory() | |
| { | |
| return directory; | |
| } | |
| /** | |
| * Sets the working directory to that specified. | |
| * The supplied argument may be <code>null</code>, | |
| * which indicates the default value should be used. | |
| * The default is the working directory of the current | |
| * process. | |
| * | |
| * @param directory the new working directory. | |
| * @return a reference to this process builder. | |
| */ | |
| public ProcessBuilder directory(File directory) | |
| { | |
| this.directory = directory; | |
| return this; | |
| } | |
| /** | |
| * <p> | |
| * Returns the system environment variables of the process. | |
| * If the underlying system does not support environment variables, | |
| * an empty map is returned. | |
| * </p> | |
| * <p> | |
| * The returned map does not accept queries using | |
| * null keys or values, or those of a type other than | |
| * <code>String</code>. Attempts to pass in a null value will | |
| * throw a <code>NullPointerException</code>. Types other than | |
| * <code>String</code> throw a <code>ClassCastException</code>. | |
| * </p> | |
| * <p> | |
| * As the returned map is generated using data from the underlying | |
| * platform, it may not comply with the <code>equals()</code> | |
| * and <code>hashCode()</code> contracts. It is also likely that | |
| * the keys of this map will be case-sensitive. | |
| * </p> | |
| * <p> | |
| * Modification of the map is reliant on the underlying platform; | |
| * some may not allow any changes to the environment variables or | |
| * may prevent certain values being used. Attempts to do so will | |
| * throw an <code>UnsupportedOperationException</code> or | |
| * <code>IllegalArgumentException</code>, respectively. | |
| * </p> | |
| * <p> | |
| * Use of this method may require a security check for the | |
| * RuntimePermission "getenv.*". | |
| * </p> | |
| * | |
| * @return a map of the system environment variables for the process. | |
| * @throws SecurityException if the checkPermission method of | |
| * an installed security manager prevents access to | |
| * the system environment variables. | |
| * @since 1.5 | |
| */ | |
| public Map<String, String> environment() | |
| { | |
| return environment; | |
| } | |
| /** | |
| * Returns true if the output stream and error stream of the | |
| * process will be merged to form one composite stream. The | |
| * default return value is <code>false</code>. | |
| * | |
| * @return true if the output stream and error stream are to | |
| * be merged. | |
| */ | |
| public boolean redirectErrorStream() | |
| { | |
| return redirect; | |
| } | |
| /** | |
| * Sets the error stream redirection flag. If set, the output | |
| * and error streams are merged to form one composite stream. | |
| * | |
| * @param redirect the new value of the redirection flag. | |
| * @return a reference to this process builder. | |
| */ | |
| public ProcessBuilder redirectErrorStream(boolean redirect) | |
| { | |
| this.redirect = redirect; | |
| return this; | |
| } | |
| /** | |
| * <p> | |
| * Starts execution of a new process, based on the attributes of | |
| * this <code>ProcessBuilder</code> object. This is the point | |
| * at which the command-line arguments are checked. The list | |
| * must be non-empty and contain only non-null string objects. | |
| * The other attributes have default values which are used in | |
| * cases where their values are not explicitly specified. | |
| * </p> | |
| * <p> | |
| * If a security manager is in place, then the | |
| * {@link SecurityManager#checkExec()} method is called to | |
| * ensure that permission is given to execute the process. | |
| * </p> | |
| * <p> | |
| * The execution of the process is system-dependent. Various | |
| * exceptions may result, due to problems at the operating system | |
| * level. These are all returned as a form of {@link IOException}. | |
| * </p> | |
| * | |
| * @return a <code>Process</code> object, representing the spawned | |
| * subprocess. | |
| * @throws IOException if a problem occurs with executing the process | |
| * at the operating system level. | |
| * @throws IndexOutOfBoundsException if the command to execute is | |
| * actually an empty list. | |
| * @throws NullPointerException if the command to execute is null | |
| * or the list contains null elements. | |
| * @throws SecurityException if a security manager exists and prevents | |
| * execution of the subprocess. | |
| */ | |
| public Process start() throws IOException | |
| { | |
| SecurityManager sm = SecurityManager.current; // Be thread-safe! | |
| if (sm != null) | |
| sm.checkExec(command.get(0)); | |
| return VMProcess.exec(command, environment, directory, redirect); | |
| } | |
| } |