8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.io.File;
29 import java.io.FileDescriptor;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.util.Arrays;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Map;
37 import sun.security.action.GetPropertyAction;
38
39 /**
40 * This class is used to create operating system processes.
41 *
42 * <p>Each {@code ProcessBuilder} instance manages a collection
43 * of process attributes. The {@link #start()} method creates a new
44 * {@link Process} instance with those attributes. The {@link
45 * #start()} method can be invoked repeatedly from the same instance
46 * to create new subprocesses with identical or related attributes.
47 * <p>
192 private List<String> command;
193 private File directory;
194 private Map<String,String> environment;
195 private boolean redirectErrorStream;
196 private Redirect[] redirects;
197
198 /**
199 * Constructs a process builder with the specified operating
200 * system program and arguments. This constructor does <i>not</i>
201 * make a copy of the {@code command} list. Subsequent
202 * updates to the list will be reflected in the state of the
203 * process builder. It is not checked whether
204 * {@code command} corresponds to a valid operating system
205 * command.
206 *
207 * @param command the list containing the program and its arguments
208 */
209 public ProcessBuilder(List<String> command) {
210 if (command == null)
211 throw new NullPointerException();
212 this.command = command;
213 }
214
215 /**
216 * Constructs a process builder with the specified operating
217 * system program and arguments. This is a convenience
218 * constructor that sets the process builder's command to a string
219 * list containing the same strings as the {@code command}
220 * array, in the same order. It is not checked whether
221 * {@code command} corresponds to a valid operating system
222 * command.
223 *
224 * @param command a string array containing the program and its arguments
225 */
226 public ProcessBuilder(String... command) {
227 this.command = new ArrayList<>(command.length);
228 for (String arg : command)
229 this.command.add(arg);
230 }
231
232 /**
233 * Sets this process builder's operating system program and
234 * arguments. This method does <i>not</i> make a copy of the
235 * {@code command} list. Subsequent updates to the list will
236 * be reflected in the state of the process builder. It is not
237 * checked whether {@code command} corresponds to a valid
238 * operating system command.
239 *
240 * @param command the list containing the program and its arguments
241 * @return this process builder
242 */
243 public ProcessBuilder command(List<String> command) {
244 if (command == null)
245 throw new NullPointerException();
246 this.command = command;
247 return this;
248 }
249
250 /**
251 * Sets this process builder's operating system program and
252 * arguments. This is a convenience method that sets the command
253 * to a string list containing the same strings as the
254 * {@code command} array, in the same order. It is not
255 * checked whether {@code command} corresponds to a valid
256 * operating system command.
257 *
258 * @param command a string array containing the program and its arguments
259 * @return this process builder
260 */
261 public ProcessBuilder command(String... command) {
262 this.command = new ArrayList<>(command.length);
263 for (String arg : command)
264 this.command.add(arg);
265 return this;
266 }
267
268 /**
269 * Returns this process builder's operating system program and
270 * arguments. The returned list is <i>not</i> a copy. Subsequent
271 * updates to the list will be reflected in the state of this
272 * process builder.
273 *
274 * @return this process builder's program and its arguments
275 */
276 public List<String> command() {
277 return command;
278 }
279
280 /**
281 * Returns a string map view of this process builder's environment.
282 *
283 * Whenever a process builder is created, the environment is
284 * initialized to a copy of the current process environment (see
285 * {@link System#getenv()}). Subprocesses subsequently started by
286 * this object's {@link #start()} method will use this map as
287 * their environment.
288 *
289 * <p>The returned object may be modified using ordinary {@link
290 * java.util.Map Map} operations. These modifications will be
291 * visible to subprocesses started via the {@link #start()}
292 * method. Two {@code ProcessBuilder} instances always
293 * contain independent process environments, so changes to the
294 * returned map will never be reflected in any other
295 * {@code ProcessBuilder} instance or the values returned by
296 * {@link System#getenv System.getenv}.
297 *
333 *
334 * <p>When passing information to a Java subprocess,
335 * <a href=System.html#EnvironmentVSSystemProperties>system properties</a>
336 * are generally preferred over environment variables.
337 *
338 * @return this process builder's environment
339 *
340 * @throws SecurityException
341 * if a security manager exists and its
342 * {@link SecurityManager#checkPermission checkPermission}
343 * method doesn't allow access to the process environment
344 *
345 * @see Runtime#exec(String[],String[],java.io.File)
346 * @see System#getenv()
347 */
348 public Map<String,String> environment() {
349 SecurityManager security = System.getSecurityManager();
350 if (security != null)
351 security.checkPermission(new RuntimePermission("getenv.*"));
352
353 if (environment == null)
354 environment = ProcessEnvironment.environment();
355
356 assert environment != null;
357
358 return environment;
359 }
360
361 // Only for use by Runtime.exec(...envp...)
362 ProcessBuilder environment(String[] envp) {
363 assert environment == null;
364 if (envp != null) {
365 environment = ProcessEnvironment.emptyEnvironment(envp.length);
366 assert environment != null;
367
368 for (String envstring : envp) {
369 // Before 1.5, we blindly passed invalid envstrings
370 // to the child process.
371 // We would like to throw an exception, but do not,
372 // for compatibility with old broken code.
373
374 // Silently discard any trailing junk.
375 if (envstring.indexOf((int) '\u0000') != -1)
376 envstring = envstring.replaceFirst("\u0000.*", "");
377
378 int eqlsign =
1280 }
1281 redirects[1] = new RedirectPipeImpl(); // placeholder for new output
1282 }
1283 processes.add(builder.start(redirects));
1284 prevOutput = redirects[1];
1285 }
1286 } catch (Exception ex) {
1287 // Cleanup processes already started
1288 processes.forEach(Process::destroyForcibly);
1289 processes.forEach(p -> {
1290 try {
1291 p.waitFor(); // Wait for it to exit
1292 } catch (InterruptedException ie) {
1293 // If interrupted; continue with next Process
1294 Thread.currentThread().interrupt();
1295 }
1296 });
1297 throw ex;
1298 }
1299 return processes;
1300 }
1301 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang;
27
28 import java.lang.invoke.MethodHandles;
29 import java.lang.invoke.VarHandle;
30 import java.io.File;
31 import java.io.FileDescriptor;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.OutputStream;
35 import java.util.Arrays;
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.Map;
39 import sun.security.action.GetPropertyAction;
40
41 /**
42 * This class is used to create operating system processes.
43 *
44 * <p>Each {@code ProcessBuilder} instance manages a collection
45 * of process attributes. The {@link #start()} method creates a new
46 * {@link Process} instance with those attributes. The {@link
47 * #start()} method can be invoked repeatedly from the same instance
48 * to create new subprocesses with identical or related attributes.
49 * <p>
194 private List<String> command;
195 private File directory;
196 private Map<String,String> environment;
197 private boolean redirectErrorStream;
198 private Redirect[] redirects;
199
200 /**
201 * Constructs a process builder with the specified operating
202 * system program and arguments. This constructor does <i>not</i>
203 * make a copy of the {@code command} list. Subsequent
204 * updates to the list will be reflected in the state of the
205 * process builder. It is not checked whether
206 * {@code command} corresponds to a valid operating system
207 * command.
208 *
209 * @param command the list containing the program and its arguments
210 */
211 public ProcessBuilder(List<String> command) {
212 if (command == null)
213 throw new NullPointerException();
214 COMMAND.setRelease(this, command);
215 }
216
217 /**
218 * Constructs a process builder with the specified operating
219 * system program and arguments. This is a convenience
220 * constructor that sets the process builder's command to a string
221 * list containing the same strings as the {@code command}
222 * array, in the same order. It is not checked whether
223 * {@code command} corresponds to a valid operating system
224 * command.
225 *
226 * @param command a string array containing the program and its arguments
227 */
228 public ProcessBuilder(String... command) {
229 List<String> commandList = new ArrayList<>(command.length);
230 for (String arg : command)
231 commandList.add(arg);
232 COMMAND.setRelease(this, commandList);
233 }
234
235 /**
236 * Sets this process builder's operating system program and
237 * arguments. This method does <i>not</i> make a copy of the
238 * {@code command} list. Subsequent updates to the list will
239 * be reflected in the state of the process builder. It is not
240 * checked whether {@code command} corresponds to a valid
241 * operating system command.
242 *
243 * @param command the list containing the program and its arguments
244 * @return this process builder
245 */
246 public ProcessBuilder command(List<String> command) {
247 if (command == null)
248 throw new NullPointerException();
249 COMMAND.setRelease(this, command);
250 return this;
251 }
252
253 /**
254 * Sets this process builder's operating system program and
255 * arguments. This is a convenience method that sets the command
256 * to a string list containing the same strings as the
257 * {@code command} array, in the same order. It is not
258 * checked whether {@code command} corresponds to a valid
259 * operating system command.
260 *
261 * @param command a string array containing the program and its arguments
262 * @return this process builder
263 */
264 public ProcessBuilder command(String... command) {
265 this.command = new ArrayList<>(command.length);
266 for (String arg : command)
267 this.command.add(arg);
268 return this;
269 }
270
271 /**
272 * Returns this process builder's operating system program and
273 * arguments. The returned list is <i>not</i> a copy. Subsequent
274 * updates to the list will be reflected in the state of this
275 * process builder.
276 *
277 * @return this process builder's program and its arguments
278 */
279 public List<String> command() {
280 return (List<String>) COMMAND.getAcquire(this);
281 }
282
283 /**
284 * Returns a string map view of this process builder's environment.
285 *
286 * Whenever a process builder is created, the environment is
287 * initialized to a copy of the current process environment (see
288 * {@link System#getenv()}). Subprocesses subsequently started by
289 * this object's {@link #start()} method will use this map as
290 * their environment.
291 *
292 * <p>The returned object may be modified using ordinary {@link
293 * java.util.Map Map} operations. These modifications will be
294 * visible to subprocesses started via the {@link #start()}
295 * method. Two {@code ProcessBuilder} instances always
296 * contain independent process environments, so changes to the
297 * returned map will never be reflected in any other
298 * {@code ProcessBuilder} instance or the values returned by
299 * {@link System#getenv System.getenv}.
300 *
336 *
337 * <p>When passing information to a Java subprocess,
338 * <a href=System.html#EnvironmentVSSystemProperties>system properties</a>
339 * are generally preferred over environment variables.
340 *
341 * @return this process builder's environment
342 *
343 * @throws SecurityException
344 * if a security manager exists and its
345 * {@link SecurityManager#checkPermission checkPermission}
346 * method doesn't allow access to the process environment
347 *
348 * @see Runtime#exec(String[],String[],java.io.File)
349 * @see System#getenv()
350 */
351 public Map<String,String> environment() {
352 SecurityManager security = System.getSecurityManager();
353 if (security != null)
354 security.checkPermission(new RuntimePermission("getenv.*"));
355
356 // Multiple threads may call this method without synchronization
357 for (;;) {
358 Map<String,String> environment = (Map<String,String>)
359 ENVIRONMENT.getAcquire(this);
360 if (environment != null)
361 return environment;
362 ENVIRONMENT.compareAndSet(this, null,
363 ProcessEnvironment.environment());
364 }
365 }
366
367 // Only for use by Runtime.exec(...envp...)
368 ProcessBuilder environment(String[] envp) {
369 assert environment == null;
370 if (envp != null) {
371 environment = ProcessEnvironment.emptyEnvironment(envp.length);
372 assert environment != null;
373
374 for (String envstring : envp) {
375 // Before 1.5, we blindly passed invalid envstrings
376 // to the child process.
377 // We would like to throw an exception, but do not,
378 // for compatibility with old broken code.
379
380 // Silently discard any trailing junk.
381 if (envstring.indexOf((int) '\u0000') != -1)
382 envstring = envstring.replaceFirst("\u0000.*", "");
383
384 int eqlsign =
1286 }
1287 redirects[1] = new RedirectPipeImpl(); // placeholder for new output
1288 }
1289 processes.add(builder.start(redirects));
1290 prevOutput = redirects[1];
1291 }
1292 } catch (Exception ex) {
1293 // Cleanup processes already started
1294 processes.forEach(Process::destroyForcibly);
1295 processes.forEach(p -> {
1296 try {
1297 p.waitFor(); // Wait for it to exit
1298 } catch (InterruptedException ie) {
1299 // If interrupted; continue with next Process
1300 Thread.currentThread().interrupt();
1301 }
1302 });
1303 throw ex;
1304 }
1305 return processes;
1306 }
1307
1308 // VarHandle mechanics
1309 private static final VarHandle COMMAND;
1310 private static final VarHandle ENVIRONMENT;
1311 static {
1312 try {
1313 MethodHandles.Lookup l = MethodHandles.lookup();
1314 COMMAND = l.findVarHandle(
1315 ProcessBuilder.class, "command", List.class);
1316 ENVIRONMENT = l.findVarHandle(
1317 ProcessBuilder.class, "environment", Map.class);
1318 } catch (ReflectiveOperationException e) {
1319 throw new ExceptionInInitializerError(e);
1320 }
1321 }
1322 }
|