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