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