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