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