ProcessBuilder.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* ProcessBuilder.java - Represent spawned system process
  2. Copyright (C) 2005 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.lang;
  32. import java.io.File;
  33. import java.io.IOException;
  34. import java.util.Arrays;
  35. import java.util.List;
  36. import java.util.Map;
  37. /**
  38. * <p>
  39. * This class is used to construct new operating system processes.
  40. * A <code>ProcessBuilder</code> instance basically represent a
  41. * template for a new process. Actual processes are generated from
  42. * this template via use of the <code>start()</code> method, which
  43. * may be invoked multiple times, with each invocation spawning a
  44. * new process with the current attributes of the
  45. * <code>ProcessBuilder</code> object. Each spawned process is
  46. * independent of the <code>ProcessBuilder</code> object, and is
  47. * unaffected by changes in its attributes.
  48. * </p>
  49. * <p>
  50. * The following attributes define a process:
  51. * </p>
  52. * <ul>
  53. * <li>The <emphasis>working directory</emphasis>; the activities of a
  54. * process begin with the current directory set to this. By default,
  55. * this is the working directory of the current process, as defined
  56. * by the <code>user.dir</code> property.</li>
  57. * <li>The <emphasis>command</emphasis> which invokes the process. This
  58. * usually consists of the name of the program binary followed by an
  59. * arbitrary number of arguments. For example, <code>find -type f</code>
  60. * invokes the <code>find</code> binary with the arguments "-type" and "f".
  61. * The command is provided a list, the elements of which are defined in a
  62. * system dependent manner; the layout is affected by expected operating
  63. * system conventions. A common method is to split the command on each
  64. * space within the string. Thus, <code>find -type f</code> forms a
  65. * three element list. However, in some cases, the expectation is that
  66. * this split is performed by the program itself; thus, the list consists
  67. * of only two elements (the program name and its arguments).</li>
  68. * <li>The <emphasis>environment map</emphasis>, which links environment
  69. * variables to their corresponding values. The initial contents of the map
  70. * are the current environment values i.e. it contains the contents of the
  71. * map returned by <code>System.getenv()</code>.</li>
  72. * <li>The <emphasis>redirection flag</emphasis>, which specifies whether
  73. * or not the contents of the error stream should be redirected to standard
  74. * output. By default, this is false, and there are two output streams, one
  75. * for normal data ({@link Process#getOutputStream()}) and one for error data
  76. * ({@link Process#getErrorStream()}). When set to true, the two are merged,
  77. * which simplifies the interleaving of the two streams. Data is read using
  78. * the stream returned by {@link Process#getOutputStream()}, and the
  79. * stream returned by {@link Process#getErrorStream()} throws an immediate
  80. * end-of-file exception.</li>
  81. * </ul>
  82. * <p>
  83. * All checks on attribute validity are delayed until <code>start()</code>
  84. * is called. <code>ProcessBuilder</code> objects are <strong>not
  85. * synchronized</strong>; the user must provide external synchronization
  86. * where multiple threads may interact with the same
  87. * <code>ProcessBuilder</code> object.
  88. * </p>
  89. *
  90. * @author Tom Tromey (tromey@redhat.com)
  91. * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  92. * @see Process
  93. * @see System#getenv()
  94. * @since 1.5
  95. */
  96. public final class ProcessBuilder
  97. {
  98. /**
  99. * The working directory of the process.
  100. */
  101. private File directory = new File(System.getProperty("user.dir"));
  102. /**
  103. * The command line syntax for invoking the process.
  104. */
  105. private List<String> command;
  106. /**
  107. * The mapping of environment variables to values.
  108. */
  109. private Map<String, String> environment =
  110. new System.EnvironmentMap(System.getenv());
  111. /**
  112. * A flag indicating whether to redirect the error stream to standard
  113. * output.
  114. */
  115. private boolean redirect = false;
  116. /**
  117. * Constructs a new <code>ProcessBuilder</code> with the specified
  118. * command being used to invoke the process. The list is used directly;
  119. * external changes are reflected in the <code>ProcessBuilder</code>.
  120. *
  121. * @param command the name of the program followed by its arguments.
  122. */
  123. public ProcessBuilder(List<String> command)
  124. {
  125. this.command = command;
  126. }
  127. /**
  128. * Constructs a new <code>ProcessBuilder</code> with the specified
  129. * command being used to invoke the process. This constructor
  130. * simplifies creating a new <code>ProcessBuilder</code> by
  131. * converting the provided series of constructor arguments into a
  132. * list of command-line arguments.
  133. *
  134. * @param command the name of the program followed by its arguments.
  135. */
  136. public ProcessBuilder(String... command)
  137. {
  138. this.command = Arrays.asList(command);
  139. }
  140. /**
  141. * Returns the current command line, used to invoke the process.
  142. * The return value is simply a reference to the list of command
  143. * line arguments used by the <code>ProcessBuilder</code> object;
  144. * any changes made to it will be reflected in the operation of
  145. * the <code>ProcessBuilder</code>.
  146. *
  147. * @return the list of command-line arguments.
  148. */
  149. public List<String> command()
  150. {
  151. return command;
  152. }
  153. /**
  154. * Sets the command-line arguments to those specified. The list is
  155. * used directly; external changes are reflected in the
  156. * <code>ProcessBuilder</code>.
  157. *
  158. * @param command the name of the program followed by its arguments.
  159. * @return a reference to this process builder.
  160. */
  161. public ProcessBuilder command(List<String> command)
  162. {
  163. this.command = command;
  164. return this;
  165. }
  166. /**
  167. * Sets the command-line arguments to those specified.
  168. * This simplifies modifying the arguments by converting
  169. * the provided series of constructor arguments into a
  170. * list of command-line arguments.
  171. *
  172. * @param command the name of the program followed by its arguments.
  173. * @return a reference to this process builder.
  174. */
  175. public ProcessBuilder command(String... command)
  176. {
  177. this.command = Arrays.asList(command);
  178. return this;
  179. }
  180. /**
  181. * Returns the working directory of the process. The
  182. * returned value may be <code>null</code>; this
  183. * indicates that the default behaviour of using the
  184. * working directory of the current process should
  185. * be adopted.
  186. *
  187. * @return the working directory.
  188. */
  189. public File directory()
  190. {
  191. return directory;
  192. }
  193. /**
  194. * Sets the working directory to that specified.
  195. * The supplied argument may be <code>null</code>,
  196. * which indicates the default value should be used.
  197. * The default is the working directory of the current
  198. * process.
  199. *
  200. * @param directory the new working directory.
  201. * @return a reference to this process builder.
  202. */
  203. public ProcessBuilder directory(File directory)
  204. {
  205. this.directory = directory;
  206. return this;
  207. }
  208. /**
  209. * <p>
  210. * Returns the system environment variables of the process.
  211. * If the underlying system does not support environment variables,
  212. * an empty map is returned.
  213. * </p>
  214. * <p>
  215. * The returned map does not accept queries using
  216. * null keys or values, or those of a type other than
  217. * <code>String</code>. Attempts to pass in a null value will
  218. * throw a <code>NullPointerException</code>. Types other than
  219. * <code>String</code> throw a <code>ClassCastException</code>.
  220. * </p>
  221. * <p>
  222. * As the returned map is generated using data from the underlying
  223. * platform, it may not comply with the <code>equals()</code>
  224. * and <code>hashCode()</code> contracts. It is also likely that
  225. * the keys of this map will be case-sensitive.
  226. * </p>
  227. * <p>
  228. * Modification of the map is reliant on the underlying platform;
  229. * some may not allow any changes to the environment variables or
  230. * may prevent certain values being used. Attempts to do so will
  231. * throw an <code>UnsupportedOperationException</code> or
  232. * <code>IllegalArgumentException</code>, respectively.
  233. * </p>
  234. * <p>
  235. * Use of this method may require a security check for the
  236. * RuntimePermission "getenv.*".
  237. * </p>
  238. *
  239. * @return a map of the system environment variables for the process.
  240. * @throws SecurityException if the checkPermission method of
  241. * an installed security manager prevents access to
  242. * the system environment variables.
  243. * @since 1.5
  244. */
  245. public Map<String, String> environment()
  246. {
  247. return environment;
  248. }
  249. /**
  250. * Returns true if the output stream and error stream of the
  251. * process will be merged to form one composite stream. The
  252. * default return value is <code>false</code>.
  253. *
  254. * @return true if the output stream and error stream are to
  255. * be merged.
  256. */
  257. public boolean redirectErrorStream()
  258. {
  259. return redirect;
  260. }
  261. /**
  262. * Sets the error stream redirection flag. If set, the output
  263. * and error streams are merged to form one composite stream.
  264. *
  265. * @param redirect the new value of the redirection flag.
  266. * @return a reference to this process builder.
  267. */
  268. public ProcessBuilder redirectErrorStream(boolean redirect)
  269. {
  270. this.redirect = redirect;
  271. return this;
  272. }
  273. /**
  274. * <p>
  275. * Starts execution of a new process, based on the attributes of
  276. * this <code>ProcessBuilder</code> object. This is the point
  277. * at which the command-line arguments are checked. The list
  278. * must be non-empty and contain only non-null string objects.
  279. * The other attributes have default values which are used in
  280. * cases where their values are not explicitly specified.
  281. * </p>
  282. * <p>
  283. * If a security manager is in place, then the
  284. * {@link SecurityManager#checkExec()} method is called to
  285. * ensure that permission is given to execute the process.
  286. * </p>
  287. * <p>
  288. * The execution of the process is system-dependent. Various
  289. * exceptions may result, due to problems at the operating system
  290. * level. These are all returned as a form of {@link IOException}.
  291. * </p>
  292. *
  293. * @return a <code>Process</code> object, representing the spawned
  294. * subprocess.
  295. * @throws IOException if a problem occurs with executing the process
  296. * at the operating system level.
  297. * @throws IndexOutOfBoundsException if the command to execute is
  298. * actually an empty list.
  299. * @throws NullPointerException if the command to execute is null
  300. * or the list contains null elements.
  301. * @throws SecurityException if a security manager exists and prevents
  302. * execution of the subprocess.
  303. */
  304. public Process start() throws IOException
  305. {
  306. SecurityManager sm = SecurityManager.current; // Be thread-safe!
  307. if (sm != null)
  308. sm.checkExec(command.get(0));
  309. return VMProcess.exec(command, environment, directory, redirect);
  310. }
  311. }