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