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