API Overview API Index Package Overview Direct link to this page
JDK 1.6
  java.lang. ProcessBuilder View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

/*
 * @(#)ProcessBuilder.java	1.9 06/03/22
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * @author  Martin Buchholz
 * @version 1.9, 06/03/22
 */

package java.lang;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * This class is used to create operating system processes.
 *
 * <p>Each <code>ProcessBuilder</code> instance manages a collection
 * of process attributes.  The {@link #start()} method creates a new
 * {@link Process} instance with those attributes.  The {@link
 * #start()} method can be invoked repeatedly from the same instance
 * to create new subprocesses with identical or related attributes.
 *
 * <p>Each process builder manages these process attributes:
 *
 * <ul>
 *
 * <li>a <i>command</i>, a list of strings which signifies the
 * external program file to be invoked and its arguments, if any.
 * Which string lists represent a valid operating system command is
 * system-dependent.  For example, it is common for each conceptual
 * argument to be an element in this list, but there are operating
 * systems where programs are expected to tokenize command line
 * strings themselves - on such a system a Java implementation might
 * require commands to contain exactly two elements.
 *
 * <li>an <i>environment</i>, which is a system-dependent mapping from
 * <i>variables</i> to <i>values</i>.  The initial value is a copy of
 * the environment of the current process (see {@link System#getenv()}).
 *
 * <li>a <i>working directory</i>.  The default value is the current
 * working directory of the current process, usually the directory
 * named by the system property <code>user.dir</code>.
 *
 * <li>a <i>redirectErrorStream</i> property.  Initially, this property
 * is <code>false</code>, meaning that the standard output and error
 * output of a subprocess are sent to two separate streams, which can
 * be accessed using the {@link Process#getInputStream()} and {@link
 * Process#getErrorStream()} methods.  If the value is set to
 * <code>true</code>, the standard error is merged with the standard
 * output.  This makes it easier to correlate error messages with the
 * corresponding output.  In this case, the merged data can be read
 * from the stream returned by {@link Process#getInputStream()}, while
 * reading from the stream returned by {@link
 * Process#getErrorStream()} will get an immediate end of file.
 *
 * </ul>
 *
 * <p>Modifying a process builder's attributes will affect processes
 * subsequently started by that object's {@link #start()} method, but
 * will never affect previously started processes or the Java process
 * itself.
 *
 * <p>Most error checking is performed by the {@link #start()} method.
 * It is possible to modify the state of an object so that {@link
 * #start()} will fail.  For example, setting the command attribute to
 * an empty list will not throw an exception unless {@link #start()}
 * is invoked.
 *
 * <p><strong>Note that this class is not synchronized.</strong>
 * If multiple threads access a <code>ProcessBuilder</code> instance
 * concurrently, and at least one of the threads modifies one of the
 * attributes structurally, it <i>must</i> be synchronized externally.
 *
 * <p>Starting a new process which uses the default working directory
 * and environment is easy:
 *
 * <blockquote><pre>
 * Process p = new ProcessBuilder("myCommand", "myArg").start();
 * </pre></blockquote>
 *
 * <p>Here is an example that starts a process with a modified working
 * directory and environment:
 *
 * <blockquote><pre>
 * ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
 * Map&lt;String, String&gt; env = pb.environment();
 * env.put("VAR1", "myValue");
 * env.remove("OTHERVAR");
 * env.put("VAR2", env.get("VAR1") + "suffix");
 * pb.directory(new File("myDir"));
 * Process p = pb.start();
 * </pre></blockquote>
 *
 * <p>To start a process with an explicit set of environment
 * variables, first call {@link java.util.Map#clear() Map.clear()}
 * before adding environment variables.
 *
 * @since 1.5
 */

public final class ProcessBuilder {
    private List<String> command;
    private File directory;
    private Map<String,String> environment;
    private boolean redirectErrorStream;

    /**
     * Constructs a process builder with the specified operating
     * system program and arguments.  This constructor does <i>not</i>
     * make a copy of the <code>command</code> list.  Subsequent
     * updates to the list will be reflected in the state of the
     * process builder.  It is not checked whether
     * <code>command</code> corresponds to a valid operating system
     * command.</p>
     *
     * @param   command  The list containing the program and its arguments
     *
     * @throws  NullPointerException
     *          If the argument is <code>null</code>
     */
    public ProcessBuilder(List<String> command) {
	if (command == null)
	    throw new NullPointerException();
	this.command = command;
    }

    /**
     * Constructs a process builder with the specified operating
     * system program and arguments.  This is a convenience
     * constructor that sets the process builder's command to a string
     * list containing the same strings as the <code>command</code>
     * array, in the same order.  It is not checked whether
     * <code>command</code> corresponds to a valid operating system
     * command.</p>
     *
     * @param   command  A string array containing the program and its arguments
     */
    public ProcessBuilder(String... command) {
	this.command = new ArrayList<String>(command.length);
	for (String arg : command)
	    this.command.add(arg);
    }

    /**
     * Sets this process builder's operating system program and
     * arguments.  This method does <i>not</i> make a copy of the
     * <code>command</code> list.  Subsequent updates to the list will
     * be reflected in the state of the process builder.  It is not
     * checked whether <code>command</code> corresponds to a valid
     * operating system command.</p>
     *
     * @param   command  The list containing the program and its arguments
     * @return  This process builder
     *
     * @throws  NullPointerException
     *          If the argument is <code>null</code>
     */
    public ProcessBuilder command(List<String> command) {
	if (command == null)
	    throw new NullPointerException();
	this.command = command;
	return this;
    }

    /**
     * Sets this process builder's operating system program and
     * arguments.  This is a convenience method that sets the command
     * to a string list containing the same strings as the
     * <code>command</code> array, in the same order.  It is not
     * checked whether <code>command</code> corresponds to a valid
     * operating system command.</p>
     *
     * @param   command  A string array containing the program and its arguments
     * @return  This process builder
     */
    public ProcessBuilder command(String... command) {
	this.command = new ArrayList<String>(command.length);
	for (String arg : command)
	    this.command.add(arg);
	return this;
    }

    /**
     * Returns this process builder's operating system program and
     * arguments.  The returned list is <i>not</i> a copy.  Subsequent
     * updates to the list will be reflected in the state of this
     * process builder.</p>
     *
     * @return  This process builder's program and its arguments
     */
    public List<String> command() {
	return command;
    }

    /**
     * Returns a string map view of this process builder's environment.
     *
     * Whenever a process builder is created, the environment is
     * initialized to a copy of the current process environment (see
     * {@link System#getenv()}).  Subprocesses subsequently started by
     * this object's {@link #start()} method will use this map as
     * their environment.
     *
     * <p>The returned object may be modified using ordinary {@link
     * java.util.Map Map} operations.  These modifications will be
     * visible to subprocesses started via the {@link #start()}
     * method.  Two <code>ProcessBuilder</code> instances always
     * contain independent process environments, so changes to the
     * returned map will never be reflected in any other
     * <code>ProcessBuilder</code> instance or the values returned by
     * {@link System#getenv System.getenv}.
     *
     * <p>If the system does not support environment variables, an
     * empty map is returned.
     *
     * <p>The returned map does not permit null keys or values.
     * Attempting to insert or query the presence of a null key or
     * value will throw a {@link NullPointerException}.
     * Attempting to query the presence of a key or value which is not
     * of type {@link String} will throw a {@link ClassCastException}.
     *
     * <p>The behavior of the returned map is system-dependent.  A
     * system may not allow modifications to environment variables or
     * may forbid certain variable names or values.  For this reason,
     * attempts to modify the map may fail with
     * {@link UnsupportedOperationException} or
     * {@link IllegalArgumentException}
     * if the modification is not permitted by the operating system.
     *
     * <p>Since the external format of environment variable names and
     * values is system-dependent, there may not be a one-to-one
     * mapping between them and Java's Unicode strings.  Nevertheless,
     * the map is implemented in such a way that environment variables
     * which are not modified by Java code will have an unmodified
     * native representation in the subprocess.
     *
     * <p>The returned map and its collection views may not obey the
     * general contract of the {@link Object#equals} and
     * {@link Object#hashCode} methods.
     *
     * <p>The returned map is typically case-sensitive on all platforms.
     *
     * <p>If a security manager exists, its
     * {@link SecurityManager#checkPermission checkPermission}
     * method is called with a
     * <code>{@link RuntimePermission}("getenv.*")</code>
     * permission.  This may result in a {@link SecurityException} being
     * thrown.
     *
     * <p>When passing information to a Java subprocess,
     * <a href=System.html#EnvironmentVSSystemProperties>system properties</a>
     * are generally preferred over environment variables.</p>
     *
     * @return  This process builder's environment
     *
     * @throws  SecurityException
     *          If a security manager exists and its
     *          {@link SecurityManager#checkPermission checkPermission}
     *          method doesn't allow access to the process environment
     *
     * @see     Runtime#exec(String[],String[],java.io.File)
     * @see     System#getenv()
     */
    public Map<String,String> environment() {
	SecurityManager security = System.getSecurityManager();
	if (security != null)
	    security.checkPermission(new RuntimePermission("getenv.*"));

	if (environment == null)
	    environment = ProcessEnvironment.environment();

	assert environment != null;

	return environment;
    }

    // Only for use by Runtime.exec(...envp...)
    ProcessBuilder environment(String[] envp) {
	assert environment == null;
	if (envp != null) {
	    environment = ProcessEnvironment.emptyEnvironment(envp.length);
	    assert environment != null;

	    for (String envstring : envp) {
		// Before 1.5, we blindly passed invalid envstrings
		// to the child process.
		// We would like to throw an exception, but do not,
		// for compatibility with old broken code.

		// Silently discard any trailing junk.
		if (envstring.indexOf((int) '\u0000') != -1)
		    envstring = envstring.replaceFirst("\u0000.*", "");

		int eqlsign =
		    envstring.indexOf('=', ProcessEnvironment.MIN_NAME_LENGTH);
		// Silently ignore envstrings lacking the required `='.
		if (eqlsign != -1)
		    environment.put(envstring.substring(0,eqlsign),
				    envstring.substring(eqlsign+1));
	    }
	}
	return this;
    }

    /**
     * Returns this process builder's working directory.
     *
     * Subprocesses subsequently started by this object's {@link
     * #start()} method will use this as their working directory.
     * The returned value may be <code>null</code> -- this means to use
     * the working directory of the current Java process, usually the
     * directory named by the system property <code>user.dir</code>,
     * as the working directory of the child process.</p>
     *
     * @return  This process builder's working directory
     */
    public File directory() {
	return directory;
    }

    /**
     * Sets this process builder's working directory.
     *
     * Subprocesses subsequently started by this object's {@link
     * #start()} method will use this as their working directory.
     * The argument may be <code>null</code> -- this means to use the
     * working directory of the current Java process, usually the
     * directory named by the system property <code>user.dir</code>,
     * as the working directory of the child process.</p>
     *
     * @param   directory  The new working directory
     * @return  This process builder
     */
    public ProcessBuilder directory(File directory) {
	this.directory = directory;
	return this;
    }

    /**
     * Tells whether this process builder merges standard error and
     * standard output.
     *
     * <p>If this property is <code>true</code>, then any error output
     * generated by subprocesses subsequently started by this object's
     * {@link #start()} method will be merged with the standard
     * output, so that both can be read using the
     * {@link Process#getInputStream()} method.  This makes it easier
     * to correlate error messages with the corresponding output.
     * The initial value is <code>false</code>.</p>
     *
     * @return  This process builder's <code>redirectErrorStream</code> property
     */
    public boolean redirectErrorStream() {
	return redirectErrorStream;
    }

    /**
     * Sets this process builder's <code>redirectErrorStream</code> property.
     *
     * <p>If this property is <code>true</code>, then any error output
     * generated by subprocesses subsequently started by this object's
     * {@link #start()} method will be merged with the standard
     * output, so that both can be read using the
     * {@link Process#getInputStream()} method.  This makes it easier
     * to correlate error messages with the corresponding output.
     * The initial value is <code>false</code>.</p>
     *
     * @param   redirectErrorStream  The new property value
     * @return  This process builder
     */
    public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
	this.redirectErrorStream = redirectErrorStream;
	return this;
    }

    /**
     * Starts a new process using the attributes of this process builder.
     *
     * <p>The new process will
     * invoke the command and arguments given by {@link #command()},
     * in a working directory as given by {@link #directory()},
     * with a process environment as given by {@link #environment()}.
     *
     * <p>This method checks that the command is a valid operating
     * system command.  Which commands are valid is system-dependent,
     * but at the very least the command must be a non-empty list of
     * non-null strings.
     *
     * <p>If there is a security manager, its
     * {@link SecurityManager#checkExec checkExec}
     * method is called with the first component of this object's
     * <code>command</code> array as its argument. This may result in
     * a {@link SecurityException} being thrown.
     *
     * <p>Starting an operating system process is highly system-dependent.
     * Among the many things that can go wrong are:
     * <ul>
     * <li>The operating system program file was not found.
     * <li>Access to the program file was denied.
     * <li>The working directory does not exist.
     * </ul>
     *
     * <p>In such cases an exception will be thrown.  The exact nature
     * of the exception is system-dependent, but it will always be a
     * subclass of {@link IOException}.
     *
     * <p>Subsequent modifications to this process builder will not
     * affect the returned {@link Process}.</p>
     *
     * @return  A new {@link Process} object for managing the subprocess
     *
     * @throws  NullPointerException
     *          If an element of the command list is null
     *
     * @throws  IndexOutOfBoundsException
     *          If the command is an empty list (has size <code>0</code>)
     *
     * @throws  SecurityException
     *          If a security manager exists and its
     *          {@link SecurityManager#checkExec checkExec}
     *          method doesn't allow creation of the subprocess
     *
     * @throws  IOException
     *          If an I/O error occurs
     *
     * @see     Runtime#exec(String[], String[], java.io.File)
     * @see     SecurityManager#checkExec(String)
     */
    public Process start() throws IOException {
	// Must convert to array first -- a malicious user-supplied
	// list might try to circumvent the security check.
	String[] cmdarray = command.toArray(new String[command.size()]);
	for (String arg : cmdarray)
	    if (arg == null)
		throw new NullPointerException();
	// Throws IndexOutOfBoundsException if command is empty
	String prog = cmdarray[0];

	SecurityManager security = System.getSecurityManager();
	if (security != null)
	    security.checkExec(prog);

	String dir = directory == null ? null : directory.toString();

	try {
	    return ProcessImpl.start(cmdarray,
				     environment,
				     dir,
				     redirectErrorStream);
	} catch (IOException e) {
	    // It's much easier for us to create a high-quality error
	    // message than the low-level C code which found the problem.
	    throw new IOException(
		"Cannot run program \"" + prog + "\""
		+ (dir == null ? "" : " (in directory \"" + dir + "\")")
		+ ": " + e.getMessage(),
		e);
	}
    }
}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar