001 /* ProcessBuilder.java - Represent spawned system process 002 Copyright (C) 2005 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package java.lang; 040 041 import java.io.File; 042 import java.io.IOException; 043 044 import java.util.Arrays; 045 import java.util.List; 046 import java.util.Map; 047 048 /** 049 * <p> 050 * This class is used to construct new operating system processes. 051 * A <code>ProcessBuilder</code> instance basically represent a 052 * template for a new process. Actual processes are generated from 053 * this template via use of the <code>start()</code> method, which 054 * may be invoked multiple times, with each invocation spawning a 055 * new process with the current attributes of the 056 * <code>ProcessBuilder</code> object. Each spawned process is 057 * independent of the <code>ProcessBuilder</code> object, and is 058 * unaffected by changes in its attributes. 059 * </p> 060 * <p> 061 * The following attributes define a process: 062 * </p> 063 * <ul> 064 * <li>The <emphasis>working directory</emphasis>; the activities of a 065 * process begin with the current directory set to this. By default, 066 * this is the working directory of the current process, as defined 067 * by the <code>user.dir</code> property.</li> 068 * <li>The <emphasis>command</emphasis> which invokes the process. This 069 * usually consists of the name of the program binary followed by an 070 * arbitrary number of arguments. For example, <code>find -type f</code> 071 * invokes the <code>find</code> binary with the arguments "-type" and "f". 072 * The command is provided a list, the elements of which are defined in a 073 * system dependent manner; the layout is affected by expected operating 074 * system conventions. A common method is to split the command on each 075 * space within the string. Thus, <code>find -type f</code> forms a 076 * three element list. However, in some cases, the expectation is that 077 * this split is performed by the program itself; thus, the list consists 078 * of only two elements (the program name and its arguments).</li> 079 * <li>The <emphasis>environment map</emphasis>, which links environment 080 * variables to their corresponding values. The initial contents of the map 081 * are the current environment values i.e. it contains the contents of the 082 * map returned by <code>System.getenv()</code>.</li> 083 * <li>The <emphasis>redirection flag</emphasis>, which specifies whether 084 * or not the contents of the error stream should be redirected to standard 085 * output. By default, this is false, and there are two output streams, one 086 * for normal data ({@link Process#getOutputStream()}) and one for error data 087 * ({@link Process#getErrorStream()}). When set to true, the two are merged, 088 * which simplifies the interleaving of the two streams. Data is read using 089 * the stream returned by {@link Process#getOutputStream()}, and the 090 * stream returned by {@link Process#getErrorStream()} throws an immediate 091 * end-of-file exception.</li> 092 * </ul> 093 * <p> 094 * All checks on attribute validity are delayed until <code>start()</code> 095 * is called. <code>ProcessBuilder</code> objects are <strong>not 096 * synchronized</strong>; the user must provide external synchronization 097 * where multiple threads may interact with the same 098 * <code>ProcessBuilder</code> object. 099 * </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 }