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