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