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