1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.util.Arrays; 33 import java.util.ArrayList; 34 import java.util.List; 35 import java.util.Map; 36 37 /** 38 * This class is used to create operating system processes. 39 * 40 * <p>Each {@code ProcessBuilder} instance manages a collection 41 * of process attributes. The {@link #start()} method creates a new 42 * {@link Process} instance with those attributes. The {@link 43 * #start()} method can be invoked repeatedly from the same instance 44 * to create new subprocesses with identical or related attributes. 45 * 46 * <p>Each process builder manages these process attributes: 47 * 48 * <ul> 49 * 50 * <li>a <i>command</i>, a list of strings which signifies the 51 * external program file to be invoked and its arguments, if any. 52 * Which string lists represent a valid operating system command is 53 * system-dependent. For example, it is common for each conceptual 54 * argument to be an element in this list, but there are operating 55 * systems where programs are expected to tokenize command line 56 * strings themselves - on such a system a Java implementation might 57 * require commands to contain exactly two elements. 58 * 59 * <li>an <i>environment</i>, which is a system-dependent mapping from 60 * <i>variables</i> to <i>values</i>. The initial value is a copy of 61 * the environment of the current process (see {@link System#getenv()}). 62 * 63 * <li>a <i>working directory</i>. The default value is the current 64 * working directory of the current process, usually the directory 65 * named by the system property {@code user.dir}. 66 * 67 * <li><a name="redirect-input">a source of <i>standard input</i></a>. 68 * By default, the subprocess reads input from a pipe. Java code 69 * can access this pipe via the output stream returned by 70 * {@link Process#getOutputStream()}. However, standard input may 71 * be redirected to another source using 72 * {@link #redirectInput(Redirect) redirectInput}. 73 * In this case, {@link Process#getOutputStream()} will return a 74 * <i>null output stream</i>, for which: 75 * 76 * <ul> 77 * <li>the {@link OutputStream#write(int) write} methods always 78 * throw {@code IOException} 79 * <li>the {@link OutputStream#close() close} method does nothing 80 * </ul> 81 * 82 * <li><a name="redirect-output">a destination for <i>standard output</i> 83 * and <i>standard error</i></a>. By default, the subprocess writes standard 84 * output and standard error to pipes. Java code can access these pipes 85 * via the input streams returned by {@link Process#getInputStream()} and 86 * {@link Process#getErrorStream()}. However, standard output and 87 * standard error may be redirected to other destinations using 88 * {@link #redirectOutput(Redirect) redirectOutput} and 89 * {@link #redirectError(Redirect) redirectError}. 90 * In this case, {@link Process#getInputStream()} and/or 91 * {@link Process#getErrorStream()} will return a <i>null input 92 * stream</i>, for which: 93 * 94 * <ul> 95 * <li>the {@link InputStream#read() read} methods always return 96 * {@code -1} 97 * <li>the {@link InputStream#available() available} method always returns 98 * {@code 0} 99 * <li>the {@link InputStream#close() close} method does nothing 100 * </ul> 101 * 102 * <li>a <i>redirectErrorStream</i> property. Initially, this property 103 * is {@code false}, meaning that the standard output and error 104 * output of a subprocess are sent to two separate streams, which can 105 * be accessed using the {@link Process#getInputStream()} and {@link 106 * Process#getErrorStream()} methods. 107 * 108 * <p>If the value is set to {@code true}, then: 109 * 110 * <ul> 111 * <li>standard error is merged with the standard output and always sent 112 * to the same destination (this makes it easier to correlate error 113 * messages with the corresponding output) 114 * <li>the common destination of standard error and standard output can be 115 * redirected using 116 * {@link #redirectOutput(Redirect) redirectOutput} 117 * <li>any redirection set by the 118 * {@link #redirectError(Redirect) redirectError} 119 * method is ignored when creating a subprocess 120 * <li>the stream returned from {@link Process#getErrorStream()} will 121 * always be a <a href="#redirect-output">null input stream</a> 122 * </ul> 123 * 124 * </ul> 125 * 126 * <p>Modifying a process builder's attributes will affect processes 127 * subsequently started by that object's {@link #start()} method, but 128 * will never affect previously started processes or the Java process 129 * itself. 130 * 131 * <p>Most error checking is performed by the {@link #start()} method. 132 * It is possible to modify the state of an object so that {@link 133 * #start()} will fail. For example, setting the command attribute to 134 * an empty list will not throw an exception unless {@link #start()} 135 * is invoked. 136 * 137 * <p><strong>Note that this class is not synchronized.</strong> 138 * If multiple threads access a {@code ProcessBuilder} instance 139 * concurrently, and at least one of the threads modifies one of the 140 * attributes structurally, it <i>must</i> be synchronized externally. 141 * 142 * <p>Starting a new process which uses the default working directory 143 * and environment is easy: 144 * 145 * <pre> {@code 146 * Process p = new ProcessBuilder("myCommand", "myArg").start(); 147 * }</pre> 148 * 149 * <p>Here is an example that starts a process with a modified working 150 * directory and environment, and redirects standard output and error 151 * to be appended to a log file: 152 * 153 * <pre> {@code 154 * ProcessBuilder pb = 155 * new ProcessBuilder("myCommand", "myArg1", "myArg2"); 156 * Map<String, String> env = pb.environment(); 157 * env.put("VAR1", "myValue"); 158 * env.remove("OTHERVAR"); 159 * env.put("VAR2", env.get("VAR1") + "suffix"); 160 * pb.directory(new File("myDir")); 161 * File log = new File("log"); 162 * pb.redirectErrorStream(true); 163 * pb.redirectOutput(Redirect.appendTo(log)); 164 * Process p = pb.start(); 165 * assert pb.redirectInput() == Redirect.PIPE; 166 * assert pb.redirectOutput().file() == log; 167 * assert p.getInputStream().read() == -1; 168 * }</pre> 169 * 170 * <p>To start a process with an explicit set of environment 171 * variables, first call {@link java.util.Map#clear() Map.clear()} 172 * before adding environment variables. 173 * 174 * @author Martin Buchholz 175 * @since 1.5 176 */ 177 178 public final class ProcessBuilder 179 { 180 private List<String> command; 181 private File directory; 182 private Map<String,String> environment; 183 private boolean redirectErrorStream; 184 private Redirect[] redirects; 185 186 /** 187 * Constructs a process builder with the specified operating 188 * system program and arguments. This constructor does <i>not</i> 189 * make a copy of the {@code command} list. Subsequent 190 * updates to the list will be reflected in the state of the 191 * process builder. It is not checked whether 192 * {@code command} corresponds to a valid operating system 193 * command. 194 * 195 * @param command the list containing the program and its arguments 196 * @throws NullPointerException if the argument is null 197 */ ProcessBuilder(List<String> command)198 public ProcessBuilder(List<String> command) { 199 if (command == null) 200 throw new NullPointerException(); 201 this.command = command; 202 } 203 204 /** 205 * Constructs a process builder with the specified operating 206 * system program and arguments. This is a convenience 207 * constructor that sets the process builder's command to a string 208 * list containing the same strings as the {@code command} 209 * array, in the same order. It is not checked whether 210 * {@code command} corresponds to a valid operating system 211 * command. 212 * 213 * @param command a string array containing the program and its arguments 214 */ ProcessBuilder(String... command)215 public ProcessBuilder(String... command) { 216 this.command = new ArrayList<>(command.length); 217 for (String arg : command) 218 this.command.add(arg); 219 } 220 221 /** 222 * Sets this process builder's operating system program and 223 * arguments. This method does <i>not</i> make a copy of the 224 * {@code command} list. Subsequent updates to the list will 225 * be reflected in the state of the process builder. It is not 226 * checked whether {@code command} corresponds to a valid 227 * operating system command. 228 * 229 * @param command the list containing the program and its arguments 230 * @return this process builder 231 * 232 * @throws NullPointerException if the argument is null 233 */ command(List<String> command)234 public ProcessBuilder command(List<String> command) { 235 if (command == null) 236 throw new NullPointerException(); 237 this.command = command; 238 return this; 239 } 240 241 /** 242 * Sets this process builder's operating system program and 243 * arguments. This is a convenience method that sets the command 244 * to a string list containing the same strings as the 245 * {@code command} array, in the same order. It is not 246 * checked whether {@code command} corresponds to a valid 247 * operating system command. 248 * 249 * @param command a string array containing the program and its arguments 250 * @return this process builder 251 */ command(String... command)252 public ProcessBuilder command(String... command) { 253 this.command = new ArrayList<>(command.length); 254 for (String arg : command) 255 this.command.add(arg); 256 return this; 257 } 258 259 /** 260 * Returns this process builder's operating system program and 261 * arguments. The returned list is <i>not</i> a copy. Subsequent 262 * updates to the list will be reflected in the state of this 263 * process builder. 264 * 265 * @return this process builder's program and its arguments 266 */ command()267 public List<String> command() { 268 return command; 269 } 270 271 /** 272 * Returns a string map view of this process builder's environment. 273 * 274 * Whenever a process builder is created, the environment is 275 * initialized to a copy of the current process environment (see 276 * {@link System#getenv()}). Subprocesses subsequently started by 277 * this object's {@link #start()} method will use this map as 278 * their environment. 279 * 280 * <p>The returned object may be modified using ordinary {@link 281 * java.util.Map Map} operations. These modifications will be 282 * visible to subprocesses started via the {@link #start()} 283 * method. Two {@code ProcessBuilder} instances always 284 * contain independent process environments, so changes to the 285 * returned map will never be reflected in any other 286 * {@code ProcessBuilder} instance or the values returned by 287 * {@link System#getenv System.getenv}. 288 * 289 * <p>If the system does not support environment variables, an 290 * empty map is returned. 291 * 292 * <p>The returned map does not permit null keys or values. 293 * Attempting to insert or query the presence of a null key or 294 * value will throw a {@link NullPointerException}. 295 * Attempting to query the presence of a key or value which is not 296 * of type {@link String} will throw a {@link ClassCastException}. 297 * 298 * <p>The behavior of the returned map is system-dependent. A 299 * system may not allow modifications to environment variables or 300 * may forbid certain variable names or values. For this reason, 301 * attempts to modify the map may fail with 302 * {@link UnsupportedOperationException} or 303 * {@link IllegalArgumentException} 304 * if the modification is not permitted by the operating system. 305 * 306 * <p>Since the external format of environment variable names and 307 * values is system-dependent, there may not be a one-to-one 308 * mapping between them and Java's Unicode strings. Nevertheless, 309 * the map is implemented in such a way that environment variables 310 * which are not modified by Java code will have an unmodified 311 * native representation in the subprocess. 312 * 313 * <p>The returned map and its collection views may not obey the 314 * general contract of the {@link Object#equals} and 315 * {@link Object#hashCode} methods. 316 * 317 * <p>The returned map is typically case-sensitive on all platforms. 318 * 319 * <p>If a security manager exists, its 320 * {@link SecurityManager#checkPermission checkPermission} method 321 * is called with a 322 * {@link RuntimePermission}{@code ("getenv.*")} permission. 323 * This may result in a {@link SecurityException} being thrown. 324 * 325 * <p>When passing information to a Java subprocess, 326 * <a href=System.html#EnvironmentVSSystemProperties>system properties</a> 327 * are generally preferred over environment variables. 328 * 329 * @return this process builder's environment 330 * 331 * @throws SecurityException 332 * if a security manager exists and its 333 * {@link SecurityManager#checkPermission checkPermission} 334 * method doesn't allow access to the process environment 335 * 336 * @see Runtime#exec(String[],String[],java.io.File) 337 * @see System#getenv() 338 */ environment()339 public Map<String,String> environment() { 340 SecurityManager security = System.getSecurityManager(); 341 if (security != null) 342 security.checkPermission(new RuntimePermission("getenv.*")); 343 344 if (environment == null) 345 environment = ProcessEnvironment.environment(); 346 347 assert environment != null; 348 349 return environment; 350 } 351 352 // Only for use by Runtime.exec(...envp...) environment(String[] envp)353 ProcessBuilder environment(String[] envp) { 354 assert environment == null; 355 if (envp != null) { 356 environment = ProcessEnvironment.emptyEnvironment(envp.length); 357 assert environment != null; 358 359 for (String envstring : envp) { 360 // Before 1.5, we blindly passed invalid envstrings 361 // to the child process. 362 // We would like to throw an exception, but do not, 363 // for compatibility with old broken code. 364 365 // Silently discard any trailing junk. 366 if (envstring.indexOf((int) '\u0000') != -1) 367 envstring = envstring.replaceFirst("\u0000.*", ""); 368 369 int eqlsign = 370 envstring.indexOf('=', ProcessEnvironment.MIN_NAME_LENGTH); 371 // Silently ignore envstrings lacking the required `='. 372 if (eqlsign != -1) 373 environment.put(envstring.substring(0,eqlsign), 374 envstring.substring(eqlsign+1)); 375 } 376 } 377 return this; 378 } 379 380 /** 381 * Returns this process builder's working directory. 382 * 383 * Subprocesses subsequently started by this object's {@link 384 * #start()} method will use this as their working directory. 385 * The returned value may be {@code null} -- this means to use 386 * the working directory of the current Java process, usually the 387 * directory named by the system property {@code user.dir}, 388 * as the working directory of the child process. 389 * 390 * @return this process builder's working directory 391 */ directory()392 public File directory() { 393 return directory; 394 } 395 396 /** 397 * Sets this process builder's working directory. 398 * 399 * Subprocesses subsequently started by this object's {@link 400 * #start()} method will use this as their working directory. 401 * The argument may be {@code null} -- this means to use the 402 * working directory of the current Java process, usually the 403 * directory named by the system property {@code user.dir}, 404 * as the working directory of the child process. 405 * 406 * @param directory the new working directory 407 * @return this process builder 408 */ directory(File directory)409 public ProcessBuilder directory(File directory) { 410 this.directory = directory; 411 return this; 412 } 413 414 // ---------------- I/O Redirection ---------------- 415 416 /** 417 * Implements a <a href="#redirect-output">null input stream</a>. 418 */ 419 static class NullInputStream extends InputStream { 420 static final NullInputStream INSTANCE = new NullInputStream(); NullInputStream()421 private NullInputStream() {} read()422 public int read() { return -1; } available()423 public int available() { return 0; } 424 } 425 426 /** 427 * Implements a <a href="#redirect-input">null output stream</a>. 428 */ 429 static class NullOutputStream extends OutputStream { 430 static final NullOutputStream INSTANCE = new NullOutputStream(); NullOutputStream()431 private NullOutputStream() {} write(int b)432 public void write(int b) throws IOException { 433 throw new IOException("Stream closed"); 434 } 435 } 436 437 /** 438 * Represents a source of subprocess input or a destination of 439 * subprocess output. 440 * 441 * Each {@code Redirect} instance is one of the following: 442 * 443 * <ul> 444 * <li>the special value {@link #PIPE Redirect.PIPE} 445 * <li>the special value {@link #INHERIT Redirect.INHERIT} 446 * <li>a redirection to read from a file, created by an invocation of 447 * {@link Redirect#from Redirect.from(File)} 448 * <li>a redirection to write to a file, created by an invocation of 449 * {@link Redirect#to Redirect.to(File)} 450 * <li>a redirection to append to a file, created by an invocation of 451 * {@link Redirect#appendTo Redirect.appendTo(File)} 452 * </ul> 453 * 454 * <p>Each of the above categories has an associated unique 455 * {@link Type Type}. 456 * 457 * @since 1.7 458 */ 459 public static abstract class Redirect { 460 /** 461 * The type of a {@link Redirect}. 462 */ 463 public enum Type { 464 /** 465 * The type of {@link Redirect#PIPE Redirect.PIPE}. 466 */ 467 PIPE, 468 469 /** 470 * The type of {@link Redirect#INHERIT Redirect.INHERIT}. 471 */ 472 INHERIT, 473 474 /** 475 * The type of redirects returned from 476 * {@link Redirect#from Redirect.from(File)}. 477 */ 478 READ, 479 480 /** 481 * The type of redirects returned from 482 * {@link Redirect#to Redirect.to(File)}. 483 */ 484 WRITE, 485 486 /** 487 * The type of redirects returned from 488 * {@link Redirect#appendTo Redirect.appendTo(File)}. 489 */ 490 APPEND 491 }; 492 493 /** 494 * Returns the type of this {@code Redirect}. 495 * @return the type of this {@code Redirect} 496 */ type()497 public abstract Type type(); 498 499 /** 500 * Indicates that subprocess I/O will be connected to the 501 * current Java process over a pipe. 502 * 503 * This is the default handling of subprocess standard I/O. 504 * 505 * <p>It will always be true that 506 * <pre> {@code 507 * Redirect.PIPE.file() == null && 508 * Redirect.PIPE.type() == Redirect.Type.PIPE 509 * }</pre> 510 */ 511 public static final Redirect PIPE = new Redirect() { 512 public Type type() { return Type.PIPE; } 513 public String toString() { return type().toString(); }}; 514 515 /** 516 * Indicates that subprocess I/O source or destination will be the 517 * same as those of the current process. This is the normal 518 * behavior of most operating system command interpreters (shells). 519 * 520 * <p>It will always be true that 521 * <pre> {@code 522 * Redirect.INHERIT.file() == null && 523 * Redirect.INHERIT.type() == Redirect.Type.INHERIT 524 * }</pre> 525 */ 526 public static final Redirect INHERIT = new Redirect() { 527 public Type type() { return Type.INHERIT; } 528 public String toString() { return type().toString(); }}; 529 530 /** 531 * Returns the {@link File} source or destination associated 532 * with this redirect, or {@code null} if there is no such file. 533 * 534 * @return the file associated with this redirect, 535 * or {@code null} if there is no such file 536 */ file()537 public File file() { return null; } 538 539 /** 540 * When redirected to a destination file, indicates if the output 541 * is to be written to the end of the file. 542 */ append()543 boolean append() { 544 throw new UnsupportedOperationException(); 545 } 546 547 /** 548 * Returns a redirect to read from the specified file. 549 * 550 * <p>It will always be true that 551 * <pre> {@code 552 * Redirect.from(file).file() == file && 553 * Redirect.from(file).type() == Redirect.Type.READ 554 * }</pre> 555 * 556 * @param file The {@code File} for the {@code Redirect}. 557 * @throws NullPointerException if the specified file is null 558 * @return a redirect to read from the specified file 559 */ from(final File file)560 public static Redirect from(final File file) { 561 if (file == null) 562 throw new NullPointerException(); 563 return new Redirect() { 564 public Type type() { return Type.READ; } 565 public File file() { return file; } 566 public String toString() { 567 return "redirect to read from file \"" + file + "\""; 568 } 569 }; 570 } 571 572 /** 573 * Returns a redirect to write to the specified file. 574 * If the specified file exists when the subprocess is started, 575 * its previous contents will be discarded. 576 * 577 * <p>It will always be true that 578 * <pre> {@code 579 * Redirect.to(file).file() == file && 580 * Redirect.to(file).type() == Redirect.Type.WRITE 581 * }</pre> 582 * 583 * @param file The {@code File} for the {@code Redirect}. 584 * @throws NullPointerException if the specified file is null 585 * @return a redirect to write to the specified file 586 */ to(final File file)587 public static Redirect to(final File file) { 588 if (file == null) 589 throw new NullPointerException(); 590 return new Redirect() { 591 public Type type() { return Type.WRITE; } 592 public File file() { return file; } 593 public String toString() { 594 return "redirect to write to file \"" + file + "\""; 595 } 596 boolean append() { return false; } 597 }; 598 } 599 600 /** 601 * Returns a redirect to append to the specified file. 602 * Each write operation first advances the position to the 603 * end of the file and then writes the requested data. 604 * Whether the advancement of the position and the writing 605 * of the data are done in a single atomic operation is 606 * system-dependent and therefore unspecified. 607 * 608 * <p>It will always be true that 609 * <pre> {@code 610 * Redirect.appendTo(file).file() == file && 611 * Redirect.appendTo(file).type() == Redirect.Type.APPEND 612 * }</pre> 613 * 614 * @param file The {@code File} for the {@code Redirect}. 615 * @throws NullPointerException if the specified file is null 616 * @return a redirect to append to the specified file 617 */ 618 public static Redirect appendTo(final File file) { 619 if (file == null) 620 throw new NullPointerException(); 621 return new Redirect() { 622 public Type type() { return Type.APPEND; } 623 public File file() { return file; } 624 public String toString() { 625 return "redirect to append to file \"" + file + "\""; 626 } 627 boolean append() { return true; } 628 }; 629 } 630 631 /** 632 * Compares the specified object with this {@code Redirect} for 633 * equality. Returns {@code true} if and only if the two 634 * objects are identical or both objects are {@code Redirect} 635 * instances of the same type associated with non-null equal 636 * {@code File} instances. 637 */ 638 public boolean equals(Object obj) { 639 if (obj == this) 640 return true; 641 if (! (obj instanceof Redirect)) 642 return false; 643 Redirect r = (Redirect) obj; 644 if (r.type() != this.type()) 645 return false; 646 assert this.file() != null; 647 return this.file().equals(r.file()); 648 } 649 650 /** 651 * Returns a hash code value for this {@code Redirect}. 652 * @return a hash code value for this {@code Redirect} 653 */ 654 public int hashCode() { 655 File file = file(); 656 if (file == null) 657 return super.hashCode(); 658 else 659 return file.hashCode(); 660 } 661 662 /** 663 * No public constructors. Clients must use predefined 664 * static {@code Redirect} instances or factory methods. 665 */ 666 private Redirect() {} 667 } 668 669 private Redirect[] redirects() { 670 if (redirects == null) 671 redirects = new Redirect[] { 672 Redirect.PIPE, Redirect.PIPE, Redirect.PIPE 673 }; 674 return redirects; 675 } 676 677 /** 678 * Sets this process builder's standard input source. 679 * 680 * Subprocesses subsequently started by this object's {@link #start()} 681 * method obtain their standard input from this source. 682 * 683 * <p>If the source is {@link Redirect#PIPE Redirect.PIPE} 684 * (the initial value), then the standard input of a 685 * subprocess can be written to using the output stream 686 * returned by {@link Process#getOutputStream()}. 687 * If the source is set to any other value, then 688 * {@link Process#getOutputStream()} will return a 689 * <a href="#redirect-input">null output stream</a>. 690 * 691 * @param source the new standard input source 692 * @return this process builder 693 * @throws IllegalArgumentException 694 * if the redirect does not correspond to a valid source 695 * of data, that is, has type 696 * {@link Redirect.Type#WRITE WRITE} or 697 * {@link Redirect.Type#APPEND APPEND} 698 * @since 1.7 699 */ 700 public ProcessBuilder redirectInput(Redirect source) { 701 if (source.type() == Redirect.Type.WRITE || 702 source.type() == Redirect.Type.APPEND) 703 throw new IllegalArgumentException( 704 "Redirect invalid for reading: " + source); 705 redirects()[0] = source; 706 return this; 707 } 708 709 /** 710 * Sets this process builder's standard output destination. 711 * 712 * Subprocesses subsequently started by this object's {@link #start()} 713 * method send their standard output to this destination. 714 * 715 * <p>If the destination is {@link Redirect#PIPE Redirect.PIPE} 716 * (the initial value), then the standard output of a subprocess 717 * can be read using the input stream returned by {@link 718 * Process#getInputStream()}. 719 * If the destination is set to any other value, then 720 * {@link Process#getInputStream()} will return a 721 * <a href="#redirect-output">null input stream</a>. 722 * 723 * @param destination the new standard output destination 724 * @return this process builder 725 * @throws IllegalArgumentException 726 * if the redirect does not correspond to a valid 727 * destination of data, that is, has type 728 * {@link Redirect.Type#READ READ} 729 * @since 1.7 730 */ 731 public ProcessBuilder redirectOutput(Redirect destination) { 732 if (destination.type() == Redirect.Type.READ) 733 throw new IllegalArgumentException( 734 "Redirect invalid for writing: " + destination); 735 redirects()[1] = destination; 736 return this; 737 } 738 739 /** 740 * Sets this process builder's standard error destination. 741 * 742 * Subprocesses subsequently started by this object's {@link #start()} 743 * method send their standard error to this destination. 744 * 745 * <p>If the destination is {@link Redirect#PIPE Redirect.PIPE} 746 * (the initial value), then the error output of a subprocess 747 * can be read using the input stream returned by {@link 748 * Process#getErrorStream()}. 749 * If the destination is set to any other value, then 750 * {@link Process#getErrorStream()} will return a 751 * <a href="#redirect-output">null input stream</a>. 752 * 753 * <p>If the {@link #redirectErrorStream redirectErrorStream} 754 * attribute has been set {@code true}, then the redirection set 755 * by this method has no effect. 756 * 757 * @param destination the new standard error destination 758 * @return this process builder 759 * @throws IllegalArgumentException 760 * if the redirect does not correspond to a valid 761 * destination of data, that is, has type 762 * {@link Redirect.Type#READ READ} 763 * @since 1.7 764 */ 765 public ProcessBuilder redirectError(Redirect destination) { 766 if (destination.type() == Redirect.Type.READ) 767 throw new IllegalArgumentException( 768 "Redirect invalid for writing: " + destination); 769 redirects()[2] = destination; 770 return this; 771 } 772 773 /** 774 * Sets this process builder's standard input source to a file. 775 * 776 * <p>This is a convenience method. An invocation of the form 777 * {@code redirectInput(file)} 778 * behaves in exactly the same way as the invocation 779 * {@link #redirectInput(Redirect) redirectInput} 780 * {@code (Redirect.from(file))}. 781 * 782 * @param file the new standard input source 783 * @return this process builder 784 * @since 1.7 785 */ 786 public ProcessBuilder redirectInput(File file) { 787 return redirectInput(Redirect.from(file)); 788 } 789 790 /** 791 * Sets this process builder's standard output destination to a file. 792 * 793 * <p>This is a convenience method. An invocation of the form 794 * {@code redirectOutput(file)} 795 * behaves in exactly the same way as the invocation 796 * {@link #redirectOutput(Redirect) redirectOutput} 797 * {@code (Redirect.to(file))}. 798 * 799 * @param file the new standard output destination 800 * @return this process builder 801 * @since 1.7 802 */ 803 public ProcessBuilder redirectOutput(File file) { 804 return redirectOutput(Redirect.to(file)); 805 } 806 807 /** 808 * Sets this process builder's standard error destination to a file. 809 * 810 * <p>This is a convenience method. An invocation of the form 811 * {@code redirectError(file)} 812 * behaves in exactly the same way as the invocation 813 * {@link #redirectError(Redirect) redirectError} 814 * {@code (Redirect.to(file))}. 815 * 816 * @param file the new standard error destination 817 * @return this process builder 818 * @since 1.7 819 */ 820 public ProcessBuilder redirectError(File file) { 821 return redirectError(Redirect.to(file)); 822 } 823 824 /** 825 * Returns this process builder's standard input source. 826 * 827 * Subprocesses subsequently started by this object's {@link #start()} 828 * method obtain their standard input from this source. 829 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 830 * 831 * @return this process builder's standard input source 832 * @since 1.7 833 */ 834 public Redirect redirectInput() { 835 return (redirects == null) ? Redirect.PIPE : redirects[0]; 836 } 837 838 /** 839 * Returns this process builder's standard output destination. 840 * 841 * Subprocesses subsequently started by this object's {@link #start()} 842 * method redirect their standard output to this destination. 843 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 844 * 845 * @return this process builder's standard output destination 846 * @since 1.7 847 */ 848 public Redirect redirectOutput() { 849 return (redirects == null) ? Redirect.PIPE : redirects[1]; 850 } 851 852 /** 853 * Returns this process builder's standard error destination. 854 * 855 * Subprocesses subsequently started by this object's {@link #start()} 856 * method redirect their standard error to this destination. 857 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 858 * 859 * @return this process builder's standard error destination 860 * @since 1.7 861 */ 862 public Redirect redirectError() { 863 return (redirects == null) ? Redirect.PIPE : redirects[2]; 864 } 865 866 /** 867 * Sets the source and destination for subprocess standard I/O 868 * to be the same as those of the current Java process. 869 * 870 * <p>This is a convenience method. An invocation of the form 871 * <pre> {@code 872 * pb.inheritIO() 873 * }</pre> 874 * behaves in exactly the same way as the invocation 875 * <pre> {@code 876 * pb.redirectInput(Redirect.INHERIT) 877 * .redirectOutput(Redirect.INHERIT) 878 * .redirectError(Redirect.INHERIT) 879 * }</pre> 880 * 881 * This gives behavior equivalent to most operating system 882 * command interpreters, or the standard C library function 883 * {@code system()}. 884 * 885 * @return this process builder 886 * @since 1.7 887 */ 888 public ProcessBuilder inheritIO() { 889 Arrays.fill(redirects(), Redirect.INHERIT); 890 return this; 891 } 892 893 /** 894 * Tells whether this process builder merges standard error and 895 * standard output. 896 * 897 * <p>If this property is {@code true}, then any error output 898 * generated by subprocesses subsequently started by this object's 899 * {@link #start()} method will be merged with the standard 900 * output, so that both can be read using the 901 * {@link Process#getInputStream()} method. This makes it easier 902 * to correlate error messages with the corresponding output. 903 * The initial value is {@code false}. 904 * 905 * @return this process builder's {@code redirectErrorStream} property 906 */ 907 public boolean redirectErrorStream() { 908 return redirectErrorStream; 909 } 910 911 /** 912 * Sets this process builder's {@code redirectErrorStream} property. 913 * 914 * <p>If this property is {@code true}, then any error output 915 * generated by subprocesses subsequently started by this object's 916 * {@link #start()} method will be merged with the standard 917 * output, so that both can be read using the 918 * {@link Process#getInputStream()} method. This makes it easier 919 * to correlate error messages with the corresponding output. 920 * The initial value is {@code false}. 921 * 922 * @param redirectErrorStream the new property value 923 * @return this process builder 924 */ 925 public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) { 926 this.redirectErrorStream = redirectErrorStream; 927 return this; 928 } 929 930 /** 931 * Starts a new process using the attributes of this process builder. 932 * 933 * <p>The new process will 934 * invoke the command and arguments given by {@link #command()}, 935 * in a working directory as given by {@link #directory()}, 936 * with a process environment as given by {@link #environment()}. 937 * 938 * <p>This method checks that the command is a valid operating 939 * system command. Which commands are valid is system-dependent, 940 * but at the very least the command must be a non-empty list of 941 * non-null strings. 942 * 943 * <p>A minimal set of system dependent environment variables may 944 * be required to start a process on some operating systems. 945 * As a result, the subprocess may inherit additional environment variable 946 * settings beyond those in the process builder's {@link #environment()}. 947 * 948 * <p>If there is a security manager, its 949 * {@link SecurityManager#checkExec checkExec} 950 * method is called with the first component of this object's 951 * {@code command} array as its argument. This may result in 952 * a {@link SecurityException} being thrown. 953 * 954 * <p>Starting an operating system process is highly system-dependent. 955 * Among the many things that can go wrong are: 956 * <ul> 957 * <li>The operating system program file was not found. 958 * <li>Access to the program file was denied. 959 * <li>The working directory does not exist. 960 * </ul> 961 * 962 * <p>In such cases an exception will be thrown. The exact nature 963 * of the exception is system-dependent, but it will always be a 964 * subclass of {@link IOException}. 965 * 966 * <p>Subsequent modifications to this process builder will not 967 * affect the returned {@link Process}. 968 * 969 * @return a new {@link Process} object for managing the subprocess 970 * 971 * @throws NullPointerException 972 * if an element of the command list is null 973 * 974 * @throws IndexOutOfBoundsException 975 * if the command is an empty list (has size {@code 0}) 976 * 977 * @throws SecurityException 978 * if a security manager exists and 979 * <ul> 980 * 981 * <li>its 982 * {@link SecurityManager#checkExec checkExec} 983 * method doesn't allow creation of the subprocess, or 984 * 985 * <li>the standard input to the subprocess was 986 * {@linkplain #redirectInput redirected from a file} 987 * and the security manager's 988 * {@link SecurityManager#checkRead checkRead} method 989 * denies read access to the file, or 990 * 991 * <li>the standard output or standard error of the 992 * subprocess was 993 * {@linkplain #redirectOutput redirected to a file} 994 * and the security manager's 995 * {@link SecurityManager#checkWrite checkWrite} method 996 * denies write access to the file 997 * 998 * </ul> 999 * 1000 * @throws IOException if an I/O error occurs 1001 * 1002 * @see Runtime#exec(String[], String[], java.io.File) 1003 */ 1004 public Process start() throws IOException { 1005 // Must convert to array first -- a malicious user-supplied 1006 // list might try to circumvent the security check. 1007 String[] cmdarray = command.toArray(new String[command.size()]); 1008 cmdarray = cmdarray.clone(); 1009 1010 for (String arg : cmdarray) 1011 if (arg == null) 1012 throw new NullPointerException(); 1013 // Throws IndexOutOfBoundsException if command is empty 1014 String prog = cmdarray[0]; 1015 1016 SecurityManager security = System.getSecurityManager(); 1017 if (security != null) 1018 security.checkExec(prog); 1019 1020 String dir = directory == null ? null : directory.toString(); 1021 1022 for (int i = 1; i < cmdarray.length; i++) { 1023 if (cmdarray[i].indexOf('\u0000') >= 0) { 1024 throw new IOException("invalid null character in command"); 1025 } 1026 } 1027 1028 try { 1029 return ProcessImpl.start(cmdarray, 1030 environment, 1031 dir, 1032 redirects, 1033 redirectErrorStream); 1034 } catch (IOException | IllegalArgumentException e) { 1035 String exceptionInfo = ": " + e.getMessage(); 1036 Throwable cause = e; 1037 if ((e instanceof IOException) && security != null) { 1038 // Can not disclose the fail reason for read-protected files. 1039 try { 1040 security.checkRead(prog); 1041 } catch (SecurityException se) { 1042 exceptionInfo = ""; 1043 cause = se; 1044 } 1045 } 1046 // It's much easier for us to create a high-quality error 1047 // message than the low-level C code which found the problem. 1048 throw new IOException( 1049 "Cannot run program \"" + prog + "\"" 1050 + (dir == null ? "" : " (in directory \"" + dir + "\")") 1051 + exceptionInfo, 1052 cause); 1053 } 1054 } 1055 } 1056