1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package java.lang; 18 19import java.io.File; 20import java.io.IOException; 21import java.util.ArrayList; 22import java.util.List; 23import java.util.Map; 24 25/** 26 * Creates operating system processes. 27 * 28 * @since 1.5 29 */ 30public final class ProcessBuilder { 31 32 private List<String> command; 33 34 private File directory; 35 36 private Map<String, String> environment; 37 38 private boolean redirectErrorStream; 39 40 /** 41 * Constructs a new {@code ProcessBuilder} instance with the specified 42 * operating system program and its arguments. 43 * 44 * @param command 45 * the requested operating system program and its arguments. 46 */ 47 public ProcessBuilder(String... command) { 48 this(toList(command)); 49 } 50 51 /** 52 * Constructs a new {@code ProcessBuilder} instance with the specified 53 * operating system program and its arguments. Note that the list passed to 54 * this constructor is not copied, so any subsequent updates to it are 55 * reflected in this instance's state. 56 * 57 * @param command 58 * the requested operating system program and its arguments. 59 * @throws NullPointerException 60 * if {@code command} is {@code null}. 61 */ 62 public ProcessBuilder(List<String> command) { 63 super(); 64 if (command == null) { 65 throw new NullPointerException(); 66 } 67 this.command = command; 68 // BEGIN android-changed 69 this.environment = System.getenv(); 70 // END android-changed 71 } 72 73 /** 74 * Returns this process builder's current program and arguments. Note that 75 * the returned list is not a copy and modifications to it will change the 76 * state of this instance. 77 * 78 * @return this process builder's program and arguments. 79 */ 80 public List<String> command() { 81 return command; 82 } 83 84 /** 85 * Changes the program and arguments of this process builder. 86 * 87 * @param command 88 * the new operating system program and its arguments. 89 * @return this process builder instance. 90 */ 91 public ProcessBuilder command(String... command) { 92 return command(toList(command)); 93 } 94 95 /** 96 * Changes the program and arguments of this process builder. Note that the 97 * list passed to this method is not copied, so any subsequent updates to it 98 * are reflected in this instance's state. 99 * 100 * @param command 101 * the new operating system program and its arguments. 102 * @return this process builder instance. 103 * @throws NullPointerException 104 * if {@code command} is {@code null}. 105 */ 106 public ProcessBuilder command(List<String> command) { 107 if (command == null) { 108 throw new NullPointerException(); 109 } 110 this.command = command; 111 return this; 112 } 113 114 /** 115 * Returns the working directory of this process builder. If {@code null} is 116 * returned, then the working directory of the Java process is used when a 117 * process is started. 118 * 119 * @return the current working directory, may be {@code null}. 120 */ 121 public File directory() { 122 return directory; 123 } 124 125 /** 126 * Changes the working directory of this process builder. If the specified 127 * directory is {@code null}, then the working directory of the Java 128 * process is used when a process is started. 129 * 130 * @param directory 131 * the new working directory for this process builder. 132 * @return this process builder instance. 133 */ 134 public ProcessBuilder directory(File directory) { 135 this.directory = directory; 136 return this; 137 } 138 139 /** 140 * Returns this process builder's current environment. When a process 141 * builder instance is created, the environment is populated with a copy of 142 * the environment, as returned by {@link System#getenv()}. Note that the 143 * map returned by this method is not a copy and any changes made to it are 144 * reflected in this instance's state. 145 * 146 * @return the map containing this process builder's environment variables. 147 */ 148 public Map<String, String> environment() { 149 return environment; 150 } 151 152 /** 153 * Indicates whether the standard error should be redirected to standard 154 * output. If redirected, the {@link Process#getErrorStream()} will always 155 * return end of stream and standard error is written to 156 * {@link Process#getInputStream()}. 157 * 158 * @return {@code true} if the standard error is redirected; {@code false} 159 * otherwise. 160 */ 161 public boolean redirectErrorStream() { 162 return redirectErrorStream; 163 } 164 165 /** 166 * Changes the state of whether or not standard error is redirected to 167 * standard output. 168 * 169 * @param redirectErrorStream 170 * {@code true} to redirect standard error, {@code false} 171 * otherwise. 172 * @return this process builder instance. 173 */ 174 public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) { 175 this.redirectErrorStream = redirectErrorStream; 176 return this; 177 } 178 179 /** 180 * Starts a new process based on the current state of this process builder. 181 * 182 * @return the new {@code Process} instance. 183 * @throws NullPointerException 184 * if any of the elements of {@link #command()} is {@code null}. 185 * @throws IndexOutOfBoundsException 186 * if {@link #command()} is empty. 187 * @throws SecurityException 188 * if {@link SecurityManager#checkExec(String)} doesn't allow 189 * process creation. 190 * @throws IOException 191 * if an I/O error happens. 192 */ 193 public Process start() throws IOException { 194 // BEGIN android-changed: push responsibility for argument checking into ProcessManager 195 String[] cmdArray = command.toArray(new String[command.size()]); 196 String[] envArray = new String[environment.size()]; 197 int i = 0; 198 for (Map.Entry<String, String> entry : environment.entrySet()) { 199 envArray[i++] = entry.getKey() + "=" + entry.getValue(); //$NON-NLS-1$ 200 } 201 return ProcessManager.getInstance().exec(cmdArray, envArray, directory, redirectErrorStream); 202 // END android-changed 203 } 204 205 private static List<String> toList(String[] strings) { 206 ArrayList<String> arrayList = new ArrayList<String>(strings.length); 207 for (String string : strings) { 208 arrayList.add(string); 209 } 210 return arrayList; 211 } 212} 213