1 /* 2 * Copyright (c) 2003, 2015, 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.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> 48 * The {@link #startPipeline startPipeline} method can be invoked to create 49 * a pipeline of new processes that send the output of each process 50 * directly to the next process. Each process has the attributes of 51 * its respective ProcessBuilder. 52 * 53 * <p>Each process builder manages these process attributes: 54 * 55 * <ul> 56 * 57 * <li>a <i>command</i>, a list of strings which signifies the 58 * external program file to be invoked and its arguments, if any. 59 * Which string lists represent a valid operating system command is 60 * system-dependent. For example, it is common for each conceptual 61 * argument to be an element in this list, but there are operating 62 * systems where programs are expected to tokenize command line 63 * strings themselves - on such a system a Java implementation might 64 * require commands to contain exactly two elements. 65 * 66 * <li>an <i>environment</i>, which is a system-dependent mapping from 67 * <i>variables</i> to <i>values</i>. The initial value is a copy of 68 * the environment of the current process (see {@link System#getenv()}). 69 * 70 * <li>a <i>working directory</i>. The default value is the current 71 * working directory of the current process, usually the directory 72 * named by the system property {@code user.dir}. 73 * 74 * <li><a name="redirect-input">a source of <i>standard input</i></a>. 75 * By default, the subprocess reads input from a pipe. Java code 76 * can access this pipe via the output stream returned by 77 * {@link Process#getOutputStream()}. However, standard input may 78 * be redirected to another source using 79 * {@link #redirectInput(Redirect) redirectInput}. 80 * In this case, {@link Process#getOutputStream()} will return a 81 * <i>null output stream</i>, for which: 82 * 83 * <ul> 84 * <li>the {@link OutputStream#write(int) write} methods always 85 * throw {@code IOException} 86 * <li>the {@link OutputStream#close() close} method does nothing 87 * </ul> 88 * 89 * <li><a name="redirect-output">a destination for <i>standard output</i> 90 * and <i>standard error</i></a>. By default, the subprocess writes standard 91 * output and standard error to pipes. Java code can access these pipes 92 * via the input streams returned by {@link Process#getOutputStream()} and 93 * {@link Process#getErrorStream()}. However, standard output and 94 * standard error may be redirected to other destinations using 95 * {@link #redirectOutput(Redirect) redirectOutput} and 96 * {@link #redirectError(Redirect) redirectError}. 97 * In this case, {@link Process#getInputStream()} and/or 98 * {@link Process#getErrorStream()} will return a <i>null input 99 * stream</i>, for which: 100 * 101 * <ul> 102 * <li>the {@link InputStream#read() read} methods always return 103 * {@code -1} 104 * <li>the {@link InputStream#available() available} method always returns 105 * {@code 0} 106 * <li>the {@link InputStream#close() close} method does nothing 107 * </ul> 108 * 109 * <li>a <i>redirectErrorStream</i> property. Initially, this property 110 * is {@code false}, meaning that the standard output and error 111 * output of a subprocess are sent to two separate streams, which can 112 * be accessed using the {@link Process#getInputStream()} and {@link 113 * Process#getErrorStream()} methods. 114 * 115 * <p>If the value is set to {@code true}, then: 116 * 117 * <ul> 118 * <li>standard error is merged with the standard output and always sent 119 * to the same destination (this makes it easier to correlate error 120 * messages with the corresponding output) 121 * <li>the common destination of standard error and standard output can be 122 * redirected using 123 * {@link #redirectOutput(Redirect) redirectOutput} 124 * <li>any redirection set by the 125 * {@link #redirectError(Redirect) redirectError} 126 * method is ignored when creating a subprocess 127 * <li>the stream returned from {@link Process#getErrorStream()} will 128 * always be a <a href="#redirect-output">null input stream</a> 129 * </ul> 130 * 131 * </ul> 132 * 133 * <p>Modifying a process builder's attributes will affect processes 134 * subsequently started by that object's {@link #start()} method, but 135 * will never affect previously started processes or the Java process 136 * itself. 137 * 138 * <p>Most error checking is performed by the {@link #start()} method. 139 * It is possible to modify the state of an object so that {@link 140 * #start()} will fail. For example, setting the command attribute to 141 * an empty list will not throw an exception unless {@link #start()} 142 * is invoked. 143 * 144 * <p><strong>Note that this class is not synchronized.</strong> 145 * If multiple threads access a {@code ProcessBuilder} instance 146 * concurrently, and at least one of the threads modifies one of the 147 * attributes structurally, it <i>must</i> be synchronized externally. 148 * 149 * <p>Starting a new process which uses the default working directory 150 * and environment is easy: 151 * 152 * <pre> {@code 153 * Process p = new ProcessBuilder("myCommand", "myArg").start(); 154 * }</pre> 155 * 156 * <p>Here is an example that starts a process with a modified working 157 * directory and environment, and redirects standard output and error 158 * to be appended to a log file: 159 * 160 * <pre> {@code 161 * ProcessBuilder pb = 162 * new ProcessBuilder("myCommand", "myArg1", "myArg2"); 163 * Map<String, String> env = pb.environment(); 164 * env.put("VAR1", "myValue"); 165 * env.remove("OTHERVAR"); 166 * env.put("VAR2", env.get("VAR1") + "suffix"); 167 * pb.directory(new File("myDir")); 168 * File log = new File("log"); 169 * pb.redirectErrorStream(true); 170 * pb.redirectOutput(Redirect.appendTo(log)); 171 * Process p = pb.start(); 172 * assert pb.redirectInput() == Redirect.PIPE; 173 * assert pb.redirectOutput().file() == log; 174 * assert p.getInputStream().read() == -1; 175 * }</pre> 176 * 177 * <p>To start a process with an explicit set of environment 178 * variables, first call {@link java.util.Map#clear() Map.clear()} 179 * before adding environment variables. 180 * 181 * <p> 182 * Unless otherwise noted, passing a {@code null} argument to a constructor 183 * or method in this class will cause a {@link NullPointerException} to be 184 * thrown. 185 * 186 * @author Martin Buchholz 187 * @since 1.5 188 */ 189 190 public final class ProcessBuilder 191 { 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 * 298 * <p>If the system does not support environment variables, an 299 * empty map is returned. 300 * 301 * <p>The returned map does not permit null keys or values. 302 * Attempting to insert or query the presence of a null key or 303 * value will throw a {@link NullPointerException}. 304 * Attempting to query the presence of a key or value which is not 305 * of type {@link String} will throw a {@link ClassCastException}. 306 * 307 * <p>The behavior of the returned map is system-dependent. A 308 * system may not allow modifications to environment variables or 309 * may forbid certain variable names or values. For this reason, 310 * attempts to modify the map may fail with 311 * {@link UnsupportedOperationException} or 312 * {@link IllegalArgumentException} 313 * if the modification is not permitted by the operating system. 314 * 315 * <p>Since the external format of environment variable names and 316 * values is system-dependent, there may not be a one-to-one 317 * mapping between them and Java's Unicode strings. Nevertheless, 318 * the map is implemented in such a way that environment variables 319 * which are not modified by Java code will have an unmodified 320 * native representation in the subprocess. 321 * 322 * <p>The returned map and its collection views may not obey the 323 * general contract of the {@link Object#equals} and 324 * {@link Object#hashCode} methods. 325 * 326 * <p>The returned map is typically case-sensitive on all platforms. 327 * 328 * <p>If a security manager exists, its 329 * {@link SecurityManager#checkPermission checkPermission} method 330 * is called with a 331 * {@link RuntimePermission}{@code ("getenv.*")} permission. 332 * This may result in a {@link SecurityException} being thrown. 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 = 379 envstring.indexOf('=', ProcessEnvironment.MIN_NAME_LENGTH); 380 // Silently ignore envstrings lacking the required `='. 381 if (eqlsign != -1) 382 environment.put(envstring.substring(0,eqlsign), 383 envstring.substring(eqlsign+1)); 384 } 385 } 386 return this; 387 } 388 389 /** 390 * Returns this process builder's working directory. 391 * 392 * Subprocesses subsequently started by this object's {@link 393 * #start()} method will use this as their working directory. 394 * The returned value may be {@code null} -- this means to use 395 * the working directory of the current Java process, usually the 396 * directory named by the system property {@code user.dir}, 397 * as the working directory of the child process. 398 * 399 * @return this process builder's working directory 400 */ 401 public File directory() { 402 return directory; 403 } 404 405 /** 406 * Sets this process builder's working directory. 407 * 408 * Subprocesses subsequently started by this object's {@link 409 * #start()} method will use this as their working directory. 410 * The argument may be {@code null} -- this means to use the 411 * working directory of the current Java process, usually the 412 * directory named by the system property {@code user.dir}, 413 * as the working directory of the child process. 414 * 415 * @param directory the new working directory 416 * @return this process builder 417 */ 418 public ProcessBuilder directory(File directory) { 419 this.directory = directory; 420 return this; 421 } 422 423 // ---------------- I/O Redirection ---------------- 424 425 /** 426 * Implements a <a href="#redirect-output">null input stream</a>. 427 */ 428 static class NullInputStream extends InputStream { 429 static final NullInputStream INSTANCE = new NullInputStream(); 430 private NullInputStream() {} 431 public int read() { return -1; } 432 public int available() { return 0; } 433 } 434 435 /** 436 * Implements a <a href="#redirect-input">null output stream</a>. 437 */ 438 static class NullOutputStream extends OutputStream { 439 static final NullOutputStream INSTANCE = new NullOutputStream(); 440 private NullOutputStream() {} 441 public void write(int b) throws IOException { 442 throw new IOException("Stream closed"); 443 } 444 } 445 446 /** 447 * Represents a source of subprocess input or a destination of 448 * subprocess output. 449 * 450 * Each {@code Redirect} instance is one of the following: 451 * 452 * <ul> 453 * <li>the special value {@link #PIPE Redirect.PIPE} 454 * <li>the special value {@link #INHERIT Redirect.INHERIT} 455 * <li>the special value {@link #DISCARD Redirect.DISCARD} 456 * <li>a redirection to read from a file, created by an invocation of 457 * {@link Redirect#from Redirect.from(File)} 458 * <li>a redirection to write to a file, created by an invocation of 459 * {@link Redirect#to Redirect.to(File)} 460 * <li>a redirection to append to a file, created by an invocation of 461 * {@link Redirect#appendTo Redirect.appendTo(File)} 462 * </ul> 463 * 464 * <p>Each of the above categories has an associated unique 465 * {@link Type Type}. 466 * 467 * @since 1.7 468 */ 469 public abstract static class Redirect { 470 private static final File NULL_FILE = new File( 471 (GetPropertyAction.privilegedGetProperty("os.name") 472 .startsWith("Windows") ? "NUL" : "/dev/null") 473 ); 474 475 /** 476 * The type of a {@link Redirect}. 477 */ 478 public enum Type { 479 /** 480 * The type of {@link Redirect#PIPE Redirect.PIPE}. 481 */ 482 PIPE, 483 484 /** 485 * The type of {@link Redirect#INHERIT Redirect.INHERIT}. 486 */ 487 INHERIT, 488 489 /** 490 * The type of redirects returned from 491 * {@link Redirect#from Redirect.from(File)}. 492 */ 493 READ, 494 495 /** 496 * The type of redirects returned from 497 * {@link Redirect#to Redirect.to(File)}. 498 */ 499 WRITE, 500 501 /** 502 * The type of redirects returned from 503 * {@link Redirect#appendTo Redirect.appendTo(File)}. 504 */ 505 APPEND 506 }; 507 508 /** 509 * Returns the type of this {@code Redirect}. 510 * @return the type of this {@code Redirect} 511 */ 512 public abstract Type type(); 513 514 /** 515 * Indicates that subprocess I/O will be connected to the 516 * current Java process over a pipe. 517 * 518 * This is the default handling of subprocess standard I/O. 519 * 520 * <p>It will always be true that 521 * <pre> {@code 522 * Redirect.PIPE.file() == null && 523 * Redirect.PIPE.type() == Redirect.Type.PIPE 524 * }</pre> 525 */ 526 public static final Redirect PIPE = new Redirect() { 527 public Type type() { return Type.PIPE; } 528 public String toString() { return type().toString(); }}; 529 530 /** 531 * Indicates that subprocess I/O source or destination will be the 532 * same as those of the current process. This is the normal 533 * behavior of most operating system command interpreters (shells). 534 * 535 * <p>It will always be true that 536 * <pre> {@code 537 * Redirect.INHERIT.file() == null && 538 * Redirect.INHERIT.type() == Redirect.Type.INHERIT 539 * }</pre> 540 */ 541 public static final Redirect INHERIT = new Redirect() { 542 public Type type() { return Type.INHERIT; } 543 public String toString() { return type().toString(); }}; 544 545 546 /** 547 * Indicates that subprocess output will be discarded. 548 * A typical implementation discards the output by writing to 549 * an operating system specific "null file". 550 * 551 * <p>It will always be true that 552 * <pre> {@code 553 * Redirect.DISCARD.file() is the filename appropriate for the operating system 554 * and may be null && 555 * Redirect.DISCARD.type() == Redirect.Type.WRITE 556 * }</pre> 557 * @since 9 558 */ 559 public static final Redirect DISCARD = new Redirect() { 560 public Type type() { return Type.WRITE; } 561 public String toString() { return type().toString(); } 562 public File file() { return NULL_FILE; } 563 boolean append() { return false; } 564 }; 565 566 /** 567 * Returns the {@link File} source or destination associated 568 * with this redirect, or {@code null} if there is no such file. 569 * 570 * @return the file associated with this redirect, 571 * or {@code null} if there is no such file 572 */ 573 public File file() { return null; } 574 575 /** 576 * When redirected to a destination file, indicates if the output 577 * is to be written to the end of the file. 578 */ 579 boolean append() { 580 throw new UnsupportedOperationException(); 581 } 582 583 /** 584 * Returns a redirect to read from the specified file. 585 * 586 * <p>It will always be true that 587 * <pre> {@code 588 * Redirect.from(file).file() == file && 589 * Redirect.from(file).type() == Redirect.Type.READ 590 * }</pre> 591 * 592 * @param file The {@code File} for the {@code Redirect}. 593 * @return a redirect to read from the specified file 594 */ 595 public static Redirect from(final File file) { 596 if (file == null) 597 throw new NullPointerException(); 598 return new Redirect() { 599 public Type type() { return Type.READ; } 600 public File file() { return file; } 601 public String toString() { 602 return "redirect to read from file \"" + file + "\""; 603 } 604 }; 605 } 606 607 /** 608 * Returns a redirect to write to the specified file. 609 * If the specified file exists when the subprocess is started, 610 * its previous contents will be discarded. 611 * 612 * <p>It will always be true that 613 * <pre> {@code 614 * Redirect.to(file).file() == file && 615 * Redirect.to(file).type() == Redirect.Type.WRITE 616 * }</pre> 617 * 618 * @param file The {@code File} for the {@code Redirect}. 619 * @return a redirect to write to the specified file 620 */ 621 public static Redirect to(final File file) { 622 if (file == null) 623 throw new NullPointerException(); 624 return new Redirect() { 625 public Type type() { return Type.WRITE; } 626 public File file() { return file; } 627 public String toString() { 628 return "redirect to write to file \"" + file + "\""; 629 } 630 boolean append() { return false; } 631 }; 632 } 633 634 /** 635 * Returns a redirect to append to the specified file. 636 * Each write operation first advances the position to the 637 * end of the file and then writes the requested data. 638 * Whether the advancement of the position and the writing 639 * of the data are done in a single atomic operation is 640 * system-dependent and therefore unspecified. 641 * 642 * <p>It will always be true that 643 * <pre> {@code 644 * Redirect.appendTo(file).file() == file && 645 * Redirect.appendTo(file).type() == Redirect.Type.APPEND 646 * }</pre> 647 * 648 * @param file The {@code File} for the {@code Redirect}. 649 * @return a redirect to append to the specified file 650 */ 651 public static Redirect appendTo(final File file) { 652 if (file == null) 653 throw new NullPointerException(); 654 return new Redirect() { 655 public Type type() { return Type.APPEND; } 656 public File file() { return file; } 657 public String toString() { 658 return "redirect to append to file \"" + file + "\""; 659 } 660 boolean append() { return true; } 661 }; 662 } 663 664 /** 665 * Compares the specified object with this {@code Redirect} for 666 * equality. Returns {@code true} if and only if the two 667 * objects are identical or both objects are {@code Redirect} 668 * instances of the same type associated with non-null equal 669 * {@code File} instances. 670 */ 671 public boolean equals(Object obj) { 672 if (obj == this) 673 return true; 674 if (! (obj instanceof Redirect)) 675 return false; 676 Redirect r = (Redirect) obj; 677 if (r.type() != this.type()) 678 return false; 679 assert this.file() != null; 680 return this.file().equals(r.file()); 681 } 682 683 /** 684 * Returns a hash code value for this {@code Redirect}. 685 * @return a hash code value for this {@code Redirect} 686 */ 687 public int hashCode() { 688 File file = file(); 689 if (file == null) 690 return super.hashCode(); 691 else 692 return file.hashCode(); 693 } 694 695 /** 696 * No public constructors. Clients must use predefined 697 * static {@code Redirect} instances or factory methods. 698 */ 699 private Redirect() {} 700 } 701 702 /** 703 * Private implementation subclass of Redirect that holds a FileDescriptor for the 704 * output of a previously started Process. 705 * The FileDescriptor is used as the standard input of the next Process 706 * to be started. 707 */ 708 static class RedirectPipeImpl extends Redirect { 709 final FileDescriptor fd; 710 711 RedirectPipeImpl() { 712 this.fd = new FileDescriptor(); 713 } 714 @Override 715 public Type type() { return Type.PIPE; } 716 717 @Override 718 public String toString() { return type().toString();} 719 720 FileDescriptor getFd() { return fd; } 721 } 722 723 /** 724 * Return the array of redirects, creating the default as needed. 725 * @return the array of redirects 726 */ 727 private Redirect[] redirects() { 728 if (redirects == null) { 729 redirects = new Redirect[] { 730 Redirect.PIPE, Redirect.PIPE, Redirect.PIPE 731 }; 732 } 733 return redirects; 734 } 735 736 /** 737 * Sets this process builder's standard input source. 738 * 739 * Subprocesses subsequently started by this object's {@link #start()} 740 * method obtain their standard input from this source. 741 * 742 * <p>If the source is {@link Redirect#PIPE Redirect.PIPE} 743 * (the initial value), then the standard input of a 744 * subprocess can be written to using the output stream 745 * returned by {@link Process#getOutputStream()}. 746 * If the source is set to any other value, then 747 * {@link Process#getOutputStream()} will return a 748 * <a href="#redirect-input">null output stream</a>. 749 * 750 * @param source the new standard input source 751 * @return this process builder 752 * @throws IllegalArgumentException 753 * if the redirect does not correspond to a valid source 754 * of data, that is, has type 755 * {@link Redirect.Type#WRITE WRITE} or 756 * {@link Redirect.Type#APPEND APPEND} 757 * @since 1.7 758 */ 759 public ProcessBuilder redirectInput(Redirect source) { 760 if (source.type() == Redirect.Type.WRITE || 761 source.type() == Redirect.Type.APPEND) 762 throw new IllegalArgumentException( 763 "Redirect invalid for reading: " + source); 764 redirects()[0] = source; 765 return this; 766 } 767 768 /** 769 * Sets this process builder's standard output destination. 770 * 771 * Subprocesses subsequently started by this object's {@link #start()} 772 * method send their standard output to this destination. 773 * 774 * <p>If the destination is {@link Redirect#PIPE Redirect.PIPE} 775 * (the initial value), then the standard output of a subprocess 776 * can be read using the input stream returned by {@link 777 * Process#getInputStream()}. 778 * If the destination is set to any other value, then 779 * {@link Process#getInputStream()} will return a 780 * <a href="#redirect-output">null input stream</a>. 781 * 782 * @param destination the new standard output destination 783 * @return this process builder 784 * @throws IllegalArgumentException 785 * if the redirect does not correspond to a valid 786 * destination of data, that is, has type 787 * {@link Redirect.Type#READ READ} 788 * @since 1.7 789 */ 790 public ProcessBuilder redirectOutput(Redirect destination) { 791 if (destination.type() == Redirect.Type.READ) 792 throw new IllegalArgumentException( 793 "Redirect invalid for writing: " + destination); 794 redirects()[1] = destination; 795 return this; 796 } 797 798 /** 799 * Sets this process builder's standard error destination. 800 * 801 * Subprocesses subsequently started by this object's {@link #start()} 802 * method send their standard error to this destination. 803 * 804 * <p>If the destination is {@link Redirect#PIPE Redirect.PIPE} 805 * (the initial value), then the error output of a subprocess 806 * can be read using the input stream returned by {@link 807 * Process#getErrorStream()}. 808 * If the destination is set to any other value, then 809 * {@link Process#getErrorStream()} will return a 810 * <a href="#redirect-output">null input stream</a>. 811 * 812 * <p>If the {@link #redirectErrorStream() redirectErrorStream} 813 * attribute has been set {@code true}, then the redirection set 814 * by this method has no effect. 815 * 816 * @param destination the new standard error destination 817 * @return this process builder 818 * @throws IllegalArgumentException 819 * if the redirect does not correspond to a valid 820 * destination of data, that is, has type 821 * {@link Redirect.Type#READ READ} 822 * @since 1.7 823 */ 824 public ProcessBuilder redirectError(Redirect destination) { 825 if (destination.type() == Redirect.Type.READ) 826 throw new IllegalArgumentException( 827 "Redirect invalid for writing: " + destination); 828 redirects()[2] = destination; 829 return this; 830 } 831 832 /** 833 * Sets this process builder's standard input source to a file. 834 * 835 * <p>This is a convenience method. An invocation of the form 836 * {@code redirectInput(file)} 837 * behaves in exactly the same way as the invocation 838 * {@link #redirectInput(Redirect) redirectInput} 839 * {@code (Redirect.from(file))}. 840 * 841 * @param file the new standard input source 842 * @return this process builder 843 * @since 1.7 844 */ 845 public ProcessBuilder redirectInput(File file) { 846 return redirectInput(Redirect.from(file)); 847 } 848 849 /** 850 * Sets this process builder's standard output destination to a file. 851 * 852 * <p>This is a convenience method. An invocation of the form 853 * {@code redirectOutput(file)} 854 * behaves in exactly the same way as the invocation 855 * {@link #redirectOutput(Redirect) redirectOutput} 856 * {@code (Redirect.to(file))}. 857 * 858 * @param file the new standard output destination 859 * @return this process builder 860 * @since 1.7 861 */ 862 public ProcessBuilder redirectOutput(File file) { 863 return redirectOutput(Redirect.to(file)); 864 } 865 866 /** 867 * Sets this process builder's standard error destination to a file. 868 * 869 * <p>This is a convenience method. An invocation of the form 870 * {@code redirectError(file)} 871 * behaves in exactly the same way as the invocation 872 * {@link #redirectError(Redirect) redirectError} 873 * {@code (Redirect.to(file))}. 874 * 875 * @param file the new standard error destination 876 * @return this process builder 877 * @since 1.7 878 */ 879 public ProcessBuilder redirectError(File file) { 880 return redirectError(Redirect.to(file)); 881 } 882 883 /** 884 * Returns this process builder's standard input source. 885 * 886 * Subprocesses subsequently started by this object's {@link #start()} 887 * method obtain their standard input from this source. 888 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 889 * 890 * @return this process builder's standard input source 891 * @since 1.7 892 */ 893 public Redirect redirectInput() { 894 return (redirects == null) ? Redirect.PIPE : redirects[0]; 895 } 896 897 /** 898 * Returns this process builder's standard output destination. 899 * 900 * Subprocesses subsequently started by this object's {@link #start()} 901 * method redirect their standard output to this destination. 902 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 903 * 904 * @return this process builder's standard output destination 905 * @since 1.7 906 */ 907 public Redirect redirectOutput() { 908 return (redirects == null) ? Redirect.PIPE : redirects[1]; 909 } 910 911 /** 912 * Returns this process builder's standard error destination. 913 * 914 * Subprocesses subsequently started by this object's {@link #start()} 915 * method redirect their standard error to this destination. 916 * The initial value is {@link Redirect#PIPE Redirect.PIPE}. 917 * 918 * @return this process builder's standard error destination 919 * @since 1.7 920 */ 921 public Redirect redirectError() { 922 return (redirects == null) ? Redirect.PIPE : redirects[2]; 923 } 924 925 /** 926 * Sets the source and destination for subprocess standard I/O 927 * to be the same as those of the current Java process. 928 * 929 * <p>This is a convenience method. An invocation of the form 930 * <pre> {@code 931 * pb.inheritIO() 932 * }</pre> 933 * behaves in exactly the same way as the invocation 934 * <pre> {@code 935 * pb.redirectInput(Redirect.INHERIT) 936 * .redirectOutput(Redirect.INHERIT) 937 * .redirectError(Redirect.INHERIT) 938 * }</pre> 939 * 940 * This gives behavior equivalent to most operating system 941 * command interpreters, or the standard C library function 942 * {@code system()}. 943 * 944 * @return this process builder 945 * @since 1.7 946 */ 947 public ProcessBuilder inheritIO() { 948 Arrays.fill(redirects(), Redirect.INHERIT); 949 return this; 950 } 951 952 /** 953 * Tells whether this process builder merges standard error and 954 * standard output. 955 * 956 * <p>If this property is {@code true}, then any error output 957 * generated by subprocesses subsequently started by this object's 958 * {@link #start()} method will be merged with the standard 959 * output, so that both can be read using the 960 * {@link Process#getInputStream()} method. This makes it easier 961 * to correlate error messages with the corresponding output. 962 * The initial value is {@code false}. 963 * 964 * @return this process builder's {@code redirectErrorStream} property 965 */ 966 public boolean redirectErrorStream() { 967 return redirectErrorStream; 968 } 969 970 /** 971 * Sets this process builder's {@code redirectErrorStream} property. 972 * 973 * <p>If this property is {@code true}, then any error output 974 * generated by subprocesses subsequently started by this object's 975 * {@link #start()} method will be merged with the standard 976 * output, so that both can be read using the 977 * {@link Process#getInputStream()} method. This makes it easier 978 * to correlate error messages with the corresponding output. 979 * The initial value is {@code false}. 980 * 981 * @param redirectErrorStream the new property value 982 * @return this process builder 983 */ 984 public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) { 985 this.redirectErrorStream = redirectErrorStream; 986 return this; 987 } 988 989 /** 990 * Starts a new process using the attributes of this process builder. 991 * 992 * <p>The new process will 993 * invoke the command and arguments given by {@link #command()}, 994 * in a working directory as given by {@link #directory()}, 995 * with a process environment as given by {@link #environment()}. 996 * 997 * <p>This method checks that the command is a valid operating 998 * system command. Which commands are valid is system-dependent, 999 * but at the very least the command must be a non-empty list of 1000 * non-null strings. 1001 * 1002 * <p>A minimal set of system dependent environment variables may 1003 * be required to start a process on some operating systems. 1004 * As a result, the subprocess may inherit additional environment variable 1005 * settings beyond those in the process builder's {@link #environment()}. 1006 * 1007 * <p>If there is a security manager, its 1008 * {@link SecurityManager#checkExec checkExec} 1009 * method is called with the first component of this object's 1010 * {@code command} array as its argument. This may result in 1011 * a {@link SecurityException} being thrown. 1012 * 1013 * <p>Starting an operating system process is highly system-dependent. 1014 * Among the many things that can go wrong are: 1015 * <ul> 1016 * <li>The operating system program file was not found. 1017 * <li>Access to the program file was denied. 1018 * <li>The working directory does not exist. 1019 * <li>Invalid character in command argument, such as NUL. 1020 * </ul> 1021 * 1022 * <p>In such cases an exception will be thrown. The exact nature 1023 * of the exception is system-dependent, but it will always be a 1024 * subclass of {@link IOException}. 1025 * 1026 * <p>If the operating system does not support the creation of 1027 * processes, an {@link UnsupportedOperationException} will be thrown. 1028 * 1029 * <p>Subsequent modifications to this process builder will not 1030 * affect the returned {@link Process}. 1031 * 1032 * @return a new {@link Process} object for managing the subprocess 1033 * 1034 * @throws NullPointerException 1035 * if an element of the command list is null 1036 * 1037 * @throws IndexOutOfBoundsException 1038 * if the command is an empty list (has size {@code 0}) 1039 * 1040 * @throws SecurityException 1041 * if a security manager exists and 1042 * <ul> 1043 * 1044 * <li>its 1045 * {@link SecurityManager#checkExec checkExec} 1046 * method doesn't allow creation of the subprocess, or 1047 * 1048 * <li>the standard input to the subprocess was 1049 * {@linkplain #redirectInput redirected from a file} 1050 * and the security manager's 1051 * {@link SecurityManager#checkRead(String) checkRead} method 1052 * denies read access to the file, or 1053 * 1054 * <li>the standard output or standard error of the 1055 * subprocess was 1056 * {@linkplain #redirectOutput redirected to a file} 1057 * and the security manager's 1058 * {@link SecurityManager#checkWrite(String) checkWrite} method 1059 * denies write access to the file 1060 * 1061 * </ul> 1062 * 1063 * @throws UnsupportedOperationException 1064 * If the operating system does not support the creation of processes. 1065 * 1066 * @throws IOException if an I/O error occurs 1067 * 1068 * @see Runtime#exec(String[], String[], java.io.File) 1069 */ 1070 public Process start() throws IOException { 1071 return start(redirects); 1072 } 1073 1074 /** 1075 * Start a new Process using an explicit array of redirects. 1076 * See {@link #start} for details of starting each Process. 1077 * 1078 * @param redirect array of redirects for stdin, stdout, stderr 1079 * @return the new Process 1080 * @throws IOException if an I/O error occurs 1081 */ 1082 private Process start(Redirect[] redirects) throws IOException { 1083 // Must convert to array first -- a malicious user-supplied 1084 // list might try to circumvent the security check. 1085 String[] cmdarray = command.toArray(new String[command.size()]); 1086 cmdarray = cmdarray.clone(); 1087 1088 for (String arg : cmdarray) 1089 if (arg == null) 1090 throw new NullPointerException(); 1091 // Throws IndexOutOfBoundsException if command is empty 1092 String prog = cmdarray[0]; 1093 1094 SecurityManager security = System.getSecurityManager(); 1095 if (security != null) 1096 security.checkExec(prog); 1097 1098 String dir = directory == null ? null : directory.toString(); 1099 1100 for (int i = 1; i < cmdarray.length; i++) { 1101 if (cmdarray[i].indexOf('\u0000') >= 0) { 1102 throw new IOException("invalid null character in command"); 1103 } 1104 } 1105 1106 try { 1107 return ProcessImpl.start(cmdarray, 1108 environment, 1109 dir, 1110 redirects, 1111 redirectErrorStream); 1112 } catch (IOException | IllegalArgumentException e) { 1113 String exceptionInfo = ": " + e.getMessage(); 1114 Throwable cause = e; 1115 if ((e instanceof IOException) && security != null) { 1116 // Can not disclose the fail reason for read-protected files. 1117 try { 1118 security.checkRead(prog); 1119 } catch (SecurityException se) { 1120 exceptionInfo = ""; 1121 cause = se; 1122 } 1123 } 1124 // It's much easier for us to create a high-quality error 1125 // message than the low-level C code which found the problem. 1126 throw new IOException( 1127 "Cannot run program \"" + prog + "\"" 1128 + (dir == null ? "" : " (in directory \"" + dir + "\")") 1129 + exceptionInfo, 1130 cause); 1131 } 1132 } 1133 1134 /** 1135 * Starts a Process for each ProcessBuilder, creating a pipeline of 1136 * processes linked by their standard output and standard input streams. 1137 * The attributes of each ProcessBuilder are used to start the respective 1138 * process except that as each process is started, its standard output 1139 * is directed to the standard input of the next. The redirects for standard 1140 * input of the first process and standard output of the last process are 1141 * initialized using the redirect settings of the respective ProcessBuilder. 1142 * All other {@code ProcessBuilder} redirects should be 1143 * {@link Redirect#PIPE Redirect.PIPE}. 1144 * <p> 1145 * All input and output streams between the intermediate processes are 1146 * not accessible. 1147 * The {@link Process#getOutputStream standard input} of all processes 1148 * except the first process are <i>null output streams</i> 1149 * The {@link Process#getInputStream standard output} of all processes 1150 * except the last process are <i>null input streams</i>. 1151 * <p> 1152 * The {@link #redirectErrorStream} of each ProcessBuilder applies to the 1153 * respective process. If set to {@code true}, the error stream is written 1154 * to the same stream as standard output. 1155 * <p> 1156 * If starting any of the processes throws an Exception, all processes 1157 * are forcibly destroyed. 1158 * <p> 1159 * The {@code startPipeline} method performs the same checks on 1160 * each ProcessBuilder as does the {@link #start} method. The new process 1161 * will invoke the command and arguments given by {@link #command()}, 1162 * in a working directory as given by {@link #directory()}, 1163 * with a process environment as given by {@link #environment()}. 1164 * <p> 1165 * This method checks that the command is a valid operating 1166 * system command. Which commands are valid is system-dependent, 1167 * but at the very least the command must be a non-empty list of 1168 * non-null strings. 1169 * <p> 1170 * A minimal set of system dependent environment variables may 1171 * be required to start a process on some operating systems. 1172 * As a result, the subprocess may inherit additional environment variable 1173 * settings beyond those in the process builder's {@link #environment()}. 1174 * <p> 1175 * If there is a security manager, its 1176 * {@link SecurityManager#checkExec checkExec} 1177 * method is called with the first component of this object's 1178 * {@code command} array as its argument. This may result in 1179 * a {@link SecurityException} being thrown. 1180 * <p> 1181 * Starting an operating system process is highly system-dependent. 1182 * Among the many things that can go wrong are: 1183 * <ul> 1184 * <li>The operating system program file was not found. 1185 * <li>Access to the program file was denied. 1186 * <li>The working directory does not exist. 1187 * <li>Invalid character in command argument, such as NUL. 1188 * </ul> 1189 * <p> 1190 * In such cases an exception will be thrown. The exact nature 1191 * of the exception is system-dependent, but it will always be a 1192 * subclass of {@link IOException}. 1193 * <p> 1194 * If the operating system does not support the creation of 1195 * processes, an {@link UnsupportedOperationException} will be thrown. 1196 * <p> 1197 * Subsequent modifications to this process builder will not 1198 * affect the returned {@link Process}. 1199 * @apiNote 1200 * For example to count the unique imports for all the files in a file hierarchy 1201 * on a Unix compatible platform: 1202 * <pre>{@code 1203 * String directory = "/home/duke/src"; 1204 * ProcessBuilder[] builders = { 1205 * new ProcessBuilder("find", directory, "-type", "f"), 1206 new ProcessBuilder("xargs", "grep", "-h", "^import "), 1207 new ProcessBuilder("awk", "{print $2;}"), 1208 new ProcessBuilder("sort", "-u")}; 1209 * List<Process> processes = ProcessBuilder.startPipeline( 1210 * Arrays.asList(builders)); 1211 * Process last = processes.get(processes.size()-1); 1212 * try (InputStream is = last.getInputStream(); 1213 * Reader isr = new InputStreamReader(is); 1214 * BufferedReader r = new BufferedReader(isr)) { 1215 * long count = r.lines().count(); 1216 * } 1217 * }</pre> 1218 * 1219 * @param builders a List of ProcessBuilders 1220 * @return a {@code List<Process>}es started from the corresponding 1221 * ProcessBuilder 1222 * @throws IllegalArgumentException any of the redirects except the 1223 * standard input of the first builder and the standard output of 1224 * the last builder are not {@link Redirect#PIPE}. 1225 * @throws NullPointerException 1226 * if an element of the command list is null or 1227 * if an element of the ProcessBuilder list is null or 1228 * the builders argument is null 1229 * @throws IndexOutOfBoundsException 1230 * if the command is an empty list (has size {@code 0}) 1231 * @throws SecurityException 1232 * if a security manager exists and 1233 * <ul> 1234 * <li>its 1235 * {@link SecurityManager#checkExec checkExec} 1236 * method doesn't allow creation of the subprocess, or 1237 * <li>the standard input to the subprocess was 1238 * {@linkplain #redirectInput redirected from a file} 1239 * and the security manager's 1240 * {@link SecurityManager#checkRead(String) checkRead} method 1241 * denies read access to the file, or 1242 * <li>the standard output or standard error of the 1243 * subprocess was 1244 * {@linkplain #redirectOutput redirected to a file} 1245 * and the security manager's 1246 * {@link SecurityManager#checkWrite(String) checkWrite} method 1247 * denies write access to the file 1248 * </ul> 1249 * 1250 * @throws UnsupportedOperationException 1251 * If the operating system does not support the creation of processes 1252 * 1253 * @throws IOException if an I/O error occurs 1254 * @since 9 1255 */ 1256 public static List<Process> startPipeline(List<ProcessBuilder> builders) throws IOException { 1257 // Accumulate and check the builders 1258 final int numBuilders = builders.size(); 1259 List<Process> processes = new ArrayList<>(numBuilders); 1260 try { 1261 Redirect prevOutput = null; 1262 for (int index = 0; index < builders.size(); index++) { 1263 ProcessBuilder builder = builders.get(index); 1264 Redirect[] redirects = builder.redirects(); 1265 if (index > 0) { 1266 // check the current Builder to see if it can take input from the previous 1267 if (builder.redirectInput() != Redirect.PIPE) { 1268 throw new IllegalArgumentException("builder redirectInput()" + 1269 " must be PIPE except for the first builder: " 1270 + builder.redirectInput()); 1271 } 1272 redirects[0] = prevOutput; 1273 } 1274 if (index < numBuilders - 1) { 1275 // check all but the last stage has output = PIPE 1276 if (builder.redirectOutput() != Redirect.PIPE) { 1277 throw new IllegalArgumentException("builder redirectOutput()" + 1278 " must be PIPE except for the last builder: " 1279 + builder.redirectOutput()); 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 }