Frames | No Frames |
1: /* ProcessBuilder.java - Represent spawned system process 2: Copyright (C) 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.lang; 40: 41: import java.io.File; 42: import java.io.IOException; 43: 44: import java.util.Arrays; 45: import java.util.List; 46: import java.util.Map; 47: 48: /** 49: * <p> 50: * This class is used to construct new operating system processes. 51: * A <code>ProcessBuilder</code> instance basically represent a 52: * template for a new process. Actual processes are generated from 53: * this template via use of the <code>start()</code> method, which 54: * may be invoked multiple times, with each invocation spawning a 55: * new process with the current attributes of the 56: * <code>ProcessBuilder</code> object. Each spawned process is 57: * independent of the <code>ProcessBuilder</code> object, and is 58: * unaffected by changes in its attributes. 59: * </p> 60: * <p> 61: * The following attributes define a process: 62: * </p> 63: * <ul> 64: * <li>The <emphasis>working directory</emphasis>; the activities of a 65: * process begin with the current directory set to this. By default, 66: * this is the working directory of the current process, as defined 67: * by the <code>user.dir</code> property.</li> 68: * <li>The <emphasis>command</emphasis> which invokes the process. This 69: * usually consists of the name of the program binary followed by an 70: * arbitrary number of arguments. For example, <code>find -type f</code> 71: * invokes the <code>find</code> binary with the arguments "-type" and "f". 72: * The command is provided a list, the elements of which are defined in a 73: * system dependent manner; the layout is affected by expected operating 74: * system conventions. A common method is to split the command on each 75: * space within the string. Thus, <code>find -type f</code> forms a 76: * three element list. However, in some cases, the expectation is that 77: * this split is performed by the program itself; thus, the list consists 78: * of only two elements (the program name and its arguments).</li> 79: * <li>The <emphasis>environment map</emphasis>, which links environment 80: * variables to their corresponding values. The initial contents of the map 81: * are the current environment values i.e. it contains the contents of the 82: * map returned by <code>System.getenv()</code>.</li> 83: * <li>The <emphasis>redirection flag</emphasis>, which specifies whether 84: * or not the contents of the error stream should be redirected to standard 85: * output. By default, this is false, and there are two output streams, one 86: * for normal data ({@link Process#getOutputStream()}) and one for error data 87: * ({@link Process#getErrorStream()}). When set to true, the two are merged, 88: * which simplifies the interleaving of the two streams. Data is read using 89: * the stream returned by {@link Process#getOutputStream()}, and the 90: * stream returned by {@link Process#getErrorStream()} throws an immediate 91: * end-of-file exception.</li> 92: * </ul> 93: * <p> 94: * All checks on attribute validity are delayed until <code>start()</code> 95: * is called. <code>ProcessBuilder</code> objects are <strong>not 96: * synchronized</strong>; the user must provide external synchronization 97: * where multiple threads may interact with the same 98: * <code>ProcessBuilder</code> object. 99: * </p> 100: * 101: * @author Tom Tromey (tromey@redhat.com) 102: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 103: * @see Process 104: * @see System#getenv() 105: * @since 1.5 106: */ 107: public final class ProcessBuilder 108: { 109: 110: /** 111: * The working directory of the process. 112: */ 113: private File directory = new File(System.getProperty("user.dir")); 114: 115: /** 116: * The command line syntax for invoking the process. 117: */ 118: private List<String> command; 119: 120: /** 121: * The mapping of environment variables to values. 122: */ 123: private Map<String, String> environment = 124: new System.EnvironmentMap(System.getenv()); 125: 126: /** 127: * A flag indicating whether to redirect the error stream to standard 128: * output. 129: */ 130: private boolean redirect = false; 131: 132: /** 133: * Constructs a new <code>ProcessBuilder</code> with the specified 134: * command being used to invoke the process. The list is used directly; 135: * external changes are reflected in the <code>ProcessBuilder</code>. 136: * 137: * @param command the name of the program followed by its arguments. 138: */ 139: public ProcessBuilder(List<String> command) 140: { 141: this.command = command; 142: } 143: 144: /** 145: * Constructs a new <code>ProcessBuilder</code> with the specified 146: * command being used to invoke the process. This constructor 147: * simplifies creating a new <code>ProcessBuilder</code> by 148: * converting the provided series of constructor arguments into a 149: * list of command-line arguments. 150: * 151: * @param command the name of the program followed by its arguments. 152: */ 153: public ProcessBuilder(String... command) 154: { 155: this.command = Arrays.asList(command); 156: } 157: 158: /** 159: * Returns the current command line, used to invoke the process. 160: * The return value is simply a reference to the list of command 161: * line arguments used by the <code>ProcessBuilder</code> object; 162: * any changes made to it will be reflected in the operation of 163: * the <code>ProcessBuilder</code>. 164: * 165: * @return the list of command-line arguments. 166: */ 167: public List<String> command() 168: { 169: return command; 170: } 171: 172: /** 173: * Sets the command-line arguments to those specified. The list is 174: * used directly; external changes are reflected in the 175: * <code>ProcessBuilder</code>. 176: * 177: * @param command the name of the program followed by its arguments. 178: * @return a reference to this process builder. 179: */ 180: public ProcessBuilder command(List<String> command) 181: { 182: this.command = command; 183: return this; 184: } 185: 186: /** 187: * Sets the command-line arguments to those specified. 188: * This simplifies modifying the arguments by converting 189: * the provided series of constructor arguments into a 190: * list of command-line arguments. 191: * 192: * @param command the name of the program followed by its arguments. 193: * @return a reference to this process builder. 194: */ 195: public ProcessBuilder command(String... command) 196: { 197: this.command = Arrays.asList(command); 198: return this; 199: } 200: 201: /** 202: * Returns the working directory of the process. The 203: * returned value may be <code>null</code>; this 204: * indicates that the default behaviour of using the 205: * working directory of the current process should 206: * be adopted. 207: * 208: * @return the working directory. 209: */ 210: public File directory() 211: { 212: return directory; 213: } 214: 215: /** 216: * Sets the working directory to that specified. 217: * The supplied argument may be <code>null</code>, 218: * which indicates the default value should be used. 219: * The default is the working directory of the current 220: * process. 221: * 222: * @param directory the new working directory. 223: * @return a reference to this process builder. 224: */ 225: public ProcessBuilder directory(File directory) 226: { 227: this.directory = directory; 228: return this; 229: } 230: 231: /** 232: * <p> 233: * Returns the system environment variables of the process. 234: * If the underlying system does not support environment variables, 235: * an empty map is returned. 236: * </p> 237: * <p> 238: * The returned map does not accept queries using 239: * null keys or values, or those of a type other than 240: * <code>String</code>. Attempts to pass in a null value will 241: * throw a <code>NullPointerException</code>. Types other than 242: * <code>String</code> throw a <code>ClassCastException</code>. 243: * </p> 244: * <p> 245: * As the returned map is generated using data from the underlying 246: * platform, it may not comply with the <code>equals()</code> 247: * and <code>hashCode()</code> contracts. It is also likely that 248: * the keys of this map will be case-sensitive. 249: * </p> 250: * <p> 251: * Modification of the map is reliant on the underlying platform; 252: * some may not allow any changes to the environment variables or 253: * may prevent certain values being used. Attempts to do so will 254: * throw an <code>UnsupportedOperationException</code> or 255: * <code>IllegalArgumentException</code>, respectively. 256: * </p> 257: * <p> 258: * Use of this method may require a security check for the 259: * RuntimePermission "getenv.*". 260: * </p> 261: * 262: * @return a map of the system environment variables for the process. 263: * @throws SecurityException if the checkPermission method of 264: * an installed security manager prevents access to 265: * the system environment variables. 266: * @since 1.5 267: */ 268: public Map<String, String> environment() 269: { 270: return environment; 271: } 272: 273: /** 274: * Returns true if the output stream and error stream of the 275: * process will be merged to form one composite stream. The 276: * default return value is <code>false</code>. 277: * 278: * @return true if the output stream and error stream are to 279: * be merged. 280: */ 281: public boolean redirectErrorStream() 282: { 283: return redirect; 284: } 285: 286: /** 287: * Sets the error stream redirection flag. If set, the output 288: * and error streams are merged to form one composite stream. 289: * 290: * @param redirect the new value of the redirection flag. 291: * @return a reference to this process builder. 292: */ 293: public ProcessBuilder redirectErrorStream(boolean redirect) 294: { 295: this.redirect = redirect; 296: return this; 297: } 298: 299: /** 300: * <p> 301: * Starts execution of a new process, based on the attributes of 302: * this <code>ProcessBuilder</code> object. This is the point 303: * at which the command-line arguments are checked. The list 304: * must be non-empty and contain only non-null string objects. 305: * The other attributes have default values which are used in 306: * cases where their values are not explicitly specified. 307: * </p> 308: * <p> 309: * If a security manager is in place, then the 310: * {@link SecurityManager#checkExec()} method is called to 311: * ensure that permission is given to execute the process. 312: * </p> 313: * <p> 314: * The execution of the process is system-dependent. Various 315: * exceptions may result, due to problems at the operating system 316: * level. These are all returned as a form of {@link IOException}. 317: * </p> 318: * 319: * @return a <code>Process</code> object, representing the spawned 320: * subprocess. 321: * @throws IOException if a problem occurs with executing the process 322: * at the operating system level. 323: * @throws IndexOutOfBoundsException if the command to execute is 324: * actually an empty list. 325: * @throws NullPointerException if the command to execute is null 326: * or the list contains null elements. 327: * @throws SecurityException if a security manager exists and prevents 328: * execution of the subprocess. 329: */ 330: public Process start() throws IOException 331: { 332: SecurityManager sm = SecurityManager.current; // Be thread-safe! 333: if (sm != null) 334: sm.checkExec(command.get(0)); 335: return VMProcess.exec(command, environment, directory, redirect); 336: } 337: }