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