PageRenderTime 82ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/test/java/lang/ProcessBuilder/Basic.java

https://bitbucket.org/psandoz/lambda-jdk-pipeline-patches
Java | 2402 lines | 1841 code | 255 blank | 306 comment | 165 complexity | 30d7ab59d50525b8d5bb7f5c6c06e843 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation.
  8. *
  9. * This code is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * version 2 for more details (a copy is included in the LICENSE file that
  13. * accompanied this code).
  14. *
  15. * You should have received a copy of the GNU General Public License version
  16. * 2 along with this work; if not, write to the Free Software Foundation,
  17. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20. * or visit www.oracle.com if you need additional information or have any
  21. * questions.
  22. */
  23. /*
  24. * @test
  25. * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
  26. * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
  27. * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
  28. * 4947220 7018606 7034570 4244896
  29. * @summary Basic tests for Process and Environment Variable code
  30. * @run main/othervm/timeout=300 Basic
  31. * @author Martin Buchholz
  32. */
  33. import java.lang.ProcessBuilder.Redirect;
  34. import static java.lang.ProcessBuilder.Redirect.*;
  35. import java.io.*;
  36. import java.util.*;
  37. import java.util.concurrent.CountDownLatch;
  38. import java.util.concurrent.TimeUnit;
  39. import java.security.*;
  40. import java.util.regex.Pattern;
  41. import java.util.regex.Matcher;
  42. import static java.lang.System.getenv;
  43. import static java.lang.System.out;
  44. import static java.lang.Boolean.TRUE;
  45. import static java.util.AbstractMap.SimpleImmutableEntry;
  46. public class Basic {
  47. /* used for Windows only */
  48. static final String systemRoot = System.getenv("SystemRoot");
  49. /* used for Mac OS X only */
  50. static final String cfUserTextEncoding = System.getenv("__CF_USER_TEXT_ENCODING");
  51. private static String commandOutput(Reader r) throws Throwable {
  52. StringBuilder sb = new StringBuilder();
  53. int c;
  54. while ((c = r.read()) > 0)
  55. if (c != '\r')
  56. sb.append((char) c);
  57. return sb.toString();
  58. }
  59. private static String commandOutput(Process p) throws Throwable {
  60. check(p.getInputStream() == p.getInputStream());
  61. check(p.getOutputStream() == p.getOutputStream());
  62. check(p.getErrorStream() == p.getErrorStream());
  63. Reader r = new InputStreamReader(p.getInputStream(),"UTF-8");
  64. String output = commandOutput(r);
  65. equal(p.waitFor(), 0);
  66. equal(p.exitValue(), 0);
  67. return output;
  68. }
  69. private static String commandOutput(ProcessBuilder pb) {
  70. try {
  71. return commandOutput(pb.start());
  72. } catch (Throwable t) {
  73. String commandline = "";
  74. for (String arg : pb.command())
  75. commandline += " " + arg;
  76. System.out.println("Exception trying to run process: " + commandline);
  77. unexpected(t);
  78. return "";
  79. }
  80. }
  81. private static String commandOutput(String...command) {
  82. try {
  83. return commandOutput(Runtime.getRuntime().exec(command));
  84. } catch (Throwable t) {
  85. String commandline = "";
  86. for (String arg : command)
  87. commandline += " " + arg;
  88. System.out.println("Exception trying to run process: " + commandline);
  89. unexpected(t);
  90. return "";
  91. }
  92. }
  93. private static void checkCommandOutput(ProcessBuilder pb,
  94. String expected,
  95. String failureMsg) {
  96. String got = commandOutput(pb);
  97. check(got.equals(expected),
  98. failureMsg + "\n" +
  99. "Expected: \"" + expected + "\"\n" +
  100. "Got: \"" + got + "\"");
  101. }
  102. private static String absolutifyPath(String path) {
  103. StringBuilder sb = new StringBuilder();
  104. for (String file : path.split(File.pathSeparator)) {
  105. if (sb.length() != 0)
  106. sb.append(File.pathSeparator);
  107. sb.append(new File(file).getAbsolutePath());
  108. }
  109. return sb.toString();
  110. }
  111. // compare windows-style, by canonicalizing to upper case,
  112. // not lower case as String.compareToIgnoreCase does
  113. private static class WindowsComparator
  114. implements Comparator<String> {
  115. public int compare(String x, String y) {
  116. return x.toUpperCase(Locale.US)
  117. .compareTo(y.toUpperCase(Locale.US));
  118. }
  119. }
  120. private static String sortedLines(String lines) {
  121. String[] arr = lines.split("\n");
  122. List<String> ls = new ArrayList<String>();
  123. for (String s : arr)
  124. ls.add(s);
  125. Collections.sort(ls, new WindowsComparator());
  126. StringBuilder sb = new StringBuilder();
  127. for (String s : ls)
  128. sb.append(s + "\n");
  129. return sb.toString();
  130. }
  131. private static void compareLinesIgnoreCase(String lines1, String lines2) {
  132. if (! (sortedLines(lines1).equalsIgnoreCase(sortedLines(lines2)))) {
  133. String dashes =
  134. "-----------------------------------------------------";
  135. out.println(dashes);
  136. out.print(sortedLines(lines1));
  137. out.println(dashes);
  138. out.print(sortedLines(lines2));
  139. out.println(dashes);
  140. out.println("sizes: " + sortedLines(lines1).length() +
  141. " " + sortedLines(lines2).length());
  142. fail("Sorted string contents differ");
  143. }
  144. }
  145. private static final Runtime runtime = Runtime.getRuntime();
  146. private static final String[] winEnvCommand = {"cmd.exe", "/c", "set"};
  147. private static String winEnvFilter(String env) {
  148. return env.replaceAll("\r", "")
  149. .replaceAll("(?m)^(?:COMSPEC|PROMPT|PATHEXT)=.*\n","");
  150. }
  151. private static String unixEnvProg() {
  152. return new File("/usr/bin/env").canExecute() ? "/usr/bin/env"
  153. : "/bin/env";
  154. }
  155. private static String nativeEnv(String[] env) {
  156. try {
  157. if (Windows.is()) {
  158. return winEnvFilter
  159. (commandOutput(runtime.exec(winEnvCommand, env)));
  160. } else {
  161. return commandOutput(runtime.exec(unixEnvProg(), env));
  162. }
  163. } catch (Throwable t) { throw new Error(t); }
  164. }
  165. private static String nativeEnv(ProcessBuilder pb) {
  166. try {
  167. if (Windows.is()) {
  168. pb.command(winEnvCommand);
  169. return winEnvFilter(commandOutput(pb));
  170. } else {
  171. pb.command(new String[]{unixEnvProg()});
  172. return commandOutput(pb);
  173. }
  174. } catch (Throwable t) { throw new Error(t); }
  175. }
  176. private static void checkSizes(Map<String,String> environ, int size) {
  177. try {
  178. equal(size, environ.size());
  179. equal(size, environ.entrySet().size());
  180. equal(size, environ.keySet().size());
  181. equal(size, environ.values().size());
  182. boolean isEmpty = (size == 0);
  183. equal(isEmpty, environ.isEmpty());
  184. equal(isEmpty, environ.entrySet().isEmpty());
  185. equal(isEmpty, environ.keySet().isEmpty());
  186. equal(isEmpty, environ.values().isEmpty());
  187. } catch (Throwable t) { unexpected(t); }
  188. }
  189. private interface EnvironmentFrobber {
  190. void doIt(Map<String,String> environ);
  191. }
  192. private static void testVariableDeleter(EnvironmentFrobber fooDeleter) {
  193. try {
  194. Map<String,String> environ = new ProcessBuilder().environment();
  195. environ.put("Foo", "BAAR");
  196. fooDeleter.doIt(environ);
  197. equal(environ.get("Foo"), null);
  198. equal(environ.remove("Foo"), null);
  199. } catch (Throwable t) { unexpected(t); }
  200. }
  201. private static void testVariableAdder(EnvironmentFrobber fooAdder) {
  202. try {
  203. Map<String,String> environ = new ProcessBuilder().environment();
  204. environ.remove("Foo");
  205. fooAdder.doIt(environ);
  206. equal(environ.get("Foo"), "Bahrein");
  207. } catch (Throwable t) { unexpected(t); }
  208. }
  209. private static void testVariableModifier(EnvironmentFrobber fooModifier) {
  210. try {
  211. Map<String,String> environ = new ProcessBuilder().environment();
  212. environ.put("Foo","OldValue");
  213. fooModifier.doIt(environ);
  214. equal(environ.get("Foo"), "NewValue");
  215. } catch (Throwable t) { unexpected(t); }
  216. }
  217. private static void printUTF8(String s) throws IOException {
  218. out.write(s.getBytes("UTF-8"));
  219. }
  220. private static String getenvAsString(Map<String,String> environment) {
  221. StringBuilder sb = new StringBuilder();
  222. environment = new TreeMap<>(environment);
  223. for (Map.Entry<String,String> e : environment.entrySet())
  224. // Ignore magic environment variables added by the launcher
  225. if (! e.getKey().equals("NLSPATH") &&
  226. ! e.getKey().equals("XFILESEARCHPATH") &&
  227. ! e.getKey().equals("LD_LIBRARY_PATH"))
  228. sb.append(e.getKey())
  229. .append('=')
  230. .append(e.getValue())
  231. .append(',');
  232. return sb.toString();
  233. }
  234. static void print4095(OutputStream s, byte b) throws Throwable {
  235. byte[] bytes = new byte[4095];
  236. Arrays.fill(bytes, b);
  237. s.write(bytes); // Might hang!
  238. }
  239. static void checkPermissionDenied(ProcessBuilder pb) {
  240. try {
  241. pb.start();
  242. fail("Expected IOException not thrown");
  243. } catch (IOException e) {
  244. String m = e.getMessage();
  245. if (EnglishUnix.is() &&
  246. ! matches(m, "Permission denied"))
  247. unexpected(e);
  248. } catch (Throwable t) { unexpected(t); }
  249. }
  250. public static class JavaChild {
  251. public static void main(String args[]) throws Throwable {
  252. String action = args[0];
  253. if (action.equals("sleep")) {
  254. Thread.sleep(10 * 60 * 1000L);
  255. } else if (action.equals("testIO")) {
  256. String expected = "standard input";
  257. char[] buf = new char[expected.length()+1];
  258. int n = new InputStreamReader(System.in).read(buf,0,buf.length);
  259. if (n != expected.length())
  260. System.exit(5);
  261. if (! new String(buf,0,n).equals(expected))
  262. System.exit(5);
  263. System.err.print("standard error");
  264. System.out.print("standard output");
  265. } else if (action.equals("testInheritIO")) {
  266. List<String> childArgs = new ArrayList<String>(javaChildArgs);
  267. childArgs.add("testIO");
  268. ProcessBuilder pb = new ProcessBuilder(childArgs);
  269. pb.inheritIO();
  270. ProcessResults r = run(pb);
  271. if (! r.out().equals(""))
  272. System.exit(7);
  273. if (! r.err().equals(""))
  274. System.exit(8);
  275. if (r.exitValue() != 0)
  276. System.exit(9);
  277. } else if (action.equals("System.getenv(String)")) {
  278. String val = System.getenv(args[1]);
  279. printUTF8(val == null ? "null" : val);
  280. } else if (action.equals("System.getenv(\\u1234)")) {
  281. String val = System.getenv("\u1234");
  282. printUTF8(val == null ? "null" : val);
  283. } else if (action.equals("System.getenv()")) {
  284. printUTF8(getenvAsString(System.getenv()));
  285. } else if (action.equals("ArrayOOME")) {
  286. Object dummy;
  287. switch(new Random().nextInt(3)) {
  288. case 0: dummy = new Integer[Integer.MAX_VALUE]; break;
  289. case 1: dummy = new double[Integer.MAX_VALUE]; break;
  290. case 2: dummy = new byte[Integer.MAX_VALUE][]; break;
  291. default: throw new InternalError();
  292. }
  293. } else if (action.equals("pwd")) {
  294. printUTF8(new File(System.getProperty("user.dir"))
  295. .getCanonicalPath());
  296. } else if (action.equals("print4095")) {
  297. print4095(System.out, (byte) '!');
  298. print4095(System.err, (byte) 'E');
  299. System.exit(5);
  300. } else if (action.equals("OutErr")) {
  301. // You might think the system streams would be
  302. // buffered, and in fact they are implemented using
  303. // BufferedOutputStream, but each and every print
  304. // causes immediate operating system I/O.
  305. System.out.print("out");
  306. System.err.print("err");
  307. System.out.print("out");
  308. System.err.print("err");
  309. } else if (action.equals("null PATH")) {
  310. equal(System.getenv("PATH"), null);
  311. check(new File("/bin/true").exists());
  312. check(new File("/bin/false").exists());
  313. ProcessBuilder pb1 = new ProcessBuilder();
  314. ProcessBuilder pb2 = new ProcessBuilder();
  315. pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
  316. ProcessResults r;
  317. for (final ProcessBuilder pb :
  318. new ProcessBuilder[] {pb1, pb2}) {
  319. pb.command("true");
  320. equal(run(pb).exitValue(), True.exitValue());
  321. pb.command("false");
  322. equal(run(pb).exitValue(), False.exitValue());
  323. }
  324. if (failed != 0) throw new Error("null PATH");
  325. } else if (action.equals("PATH search algorithm")) {
  326. equal(System.getenv("PATH"), "dir1:dir2:");
  327. check(new File("/bin/true").exists());
  328. check(new File("/bin/false").exists());
  329. String[] cmd = {"prog"};
  330. ProcessBuilder pb1 = new ProcessBuilder(cmd);
  331. ProcessBuilder pb2 = new ProcessBuilder(cmd);
  332. ProcessBuilder pb3 = new ProcessBuilder(cmd);
  333. pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
  334. pb3.environment().remove("PATH");
  335. for (final ProcessBuilder pb :
  336. new ProcessBuilder[] {pb1, pb2, pb3}) {
  337. try {
  338. // Not on PATH at all; directories don't exist
  339. try {
  340. pb.start();
  341. fail("Expected IOException not thrown");
  342. } catch (IOException e) {
  343. String m = e.getMessage();
  344. if (EnglishUnix.is() &&
  345. ! matches(m, "No such file"))
  346. unexpected(e);
  347. } catch (Throwable t) { unexpected(t); }
  348. // Not on PATH at all; directories exist
  349. new File("dir1").mkdirs();
  350. new File("dir2").mkdirs();
  351. try {
  352. pb.start();
  353. fail("Expected IOException not thrown");
  354. } catch (IOException e) {
  355. String m = e.getMessage();
  356. if (EnglishUnix.is() &&
  357. ! matches(m, "No such file"))
  358. unexpected(e);
  359. } catch (Throwable t) { unexpected(t); }
  360. // Can't execute a directory -- permission denied
  361. // Report EACCES errno
  362. new File("dir1/prog").mkdirs();
  363. checkPermissionDenied(pb);
  364. // continue searching if EACCES
  365. copy("/bin/true", "dir2/prog");
  366. equal(run(pb).exitValue(), True.exitValue());
  367. new File("dir1/prog").delete();
  368. new File("dir2/prog").delete();
  369. new File("dir2/prog").mkdirs();
  370. copy("/bin/true", "dir1/prog");
  371. equal(run(pb).exitValue(), True.exitValue());
  372. // Check empty PATH component means current directory.
  373. //
  374. // While we're here, let's test different kinds of
  375. // Unix executables, and PATH vs explicit searching.
  376. new File("dir1/prog").delete();
  377. new File("dir2/prog").delete();
  378. for (String[] command :
  379. new String[][] {
  380. new String[] {"./prog"},
  381. cmd}) {
  382. pb.command(command);
  383. File prog = new File("./prog");
  384. // "Normal" binaries
  385. copy("/bin/true", "./prog");
  386. equal(run(pb).exitValue(),
  387. True.exitValue());
  388. copy("/bin/false", "./prog");
  389. equal(run(pb).exitValue(),
  390. False.exitValue());
  391. prog.delete();
  392. // Interpreter scripts with #!
  393. setFileContents(prog, "#!/bin/true\n");
  394. prog.setExecutable(true);
  395. equal(run(pb).exitValue(),
  396. True.exitValue());
  397. prog.delete();
  398. setFileContents(prog, "#!/bin/false\n");
  399. prog.setExecutable(true);
  400. equal(run(pb).exitValue(),
  401. False.exitValue());
  402. // Traditional shell scripts without #!
  403. setFileContents(prog, "exec /bin/true\n");
  404. prog.setExecutable(true);
  405. equal(run(pb).exitValue(),
  406. True.exitValue());
  407. prog.delete();
  408. setFileContents(prog, "exec /bin/false\n");
  409. prog.setExecutable(true);
  410. equal(run(pb).exitValue(),
  411. False.exitValue());
  412. prog.delete();
  413. }
  414. // Test Unix interpreter scripts
  415. File dir1Prog = new File("dir1/prog");
  416. dir1Prog.delete();
  417. pb.command(new String[] {"prog", "world"});
  418. setFileContents(dir1Prog, "#!/bin/echo hello\n");
  419. checkPermissionDenied(pb);
  420. dir1Prog.setExecutable(true);
  421. equal(run(pb).out(), "hello dir1/prog world\n");
  422. equal(run(pb).exitValue(), True.exitValue());
  423. dir1Prog.delete();
  424. pb.command(cmd);
  425. // Test traditional shell scripts without #!
  426. setFileContents(dir1Prog, "/bin/echo \"$@\"\n");
  427. pb.command(new String[] {"prog", "hello", "world"});
  428. checkPermissionDenied(pb);
  429. dir1Prog.setExecutable(true);
  430. equal(run(pb).out(), "hello world\n");
  431. equal(run(pb).exitValue(), True.exitValue());
  432. dir1Prog.delete();
  433. pb.command(cmd);
  434. // If prog found on both parent and child's PATH,
  435. // parent's is used.
  436. new File("dir1/prog").delete();
  437. new File("dir2/prog").delete();
  438. new File("prog").delete();
  439. new File("dir3").mkdirs();
  440. copy("/bin/true", "dir1/prog");
  441. copy("/bin/false", "dir3/prog");
  442. pb.environment().put("PATH","dir3");
  443. equal(run(pb).exitValue(), True.exitValue());
  444. copy("/bin/true", "dir3/prog");
  445. copy("/bin/false", "dir1/prog");
  446. equal(run(pb).exitValue(), False.exitValue());
  447. } finally {
  448. // cleanup
  449. new File("dir1/prog").delete();
  450. new File("dir2/prog").delete();
  451. new File("dir3/prog").delete();
  452. new File("dir1").delete();
  453. new File("dir2").delete();
  454. new File("dir3").delete();
  455. new File("prog").delete();
  456. }
  457. }
  458. if (failed != 0) throw new Error("PATH search algorithm");
  459. }
  460. else throw new Error("JavaChild invocation error");
  461. }
  462. }
  463. private static void copy(String src, String dst) {
  464. system("/bin/cp", "-fp", src, dst);
  465. }
  466. private static void system(String... command) {
  467. try {
  468. ProcessBuilder pb = new ProcessBuilder(command);
  469. ProcessResults r = run(pb.start());
  470. equal(r.exitValue(), 0);
  471. equal(r.out(), "");
  472. equal(r.err(), "");
  473. } catch (Throwable t) { unexpected(t); }
  474. }
  475. private static String javaChildOutput(ProcessBuilder pb, String...args) {
  476. List<String> list = new ArrayList<String>(javaChildArgs);
  477. for (String arg : args)
  478. list.add(arg);
  479. pb.command(list);
  480. return commandOutput(pb);
  481. }
  482. private static String getenvInChild(ProcessBuilder pb) {
  483. return javaChildOutput(pb, "System.getenv()");
  484. }
  485. private static String getenvInChild1234(ProcessBuilder pb) {
  486. return javaChildOutput(pb, "System.getenv(\\u1234)");
  487. }
  488. private static String getenvInChild(ProcessBuilder pb, String name) {
  489. return javaChildOutput(pb, "System.getenv(String)", name);
  490. }
  491. private static String pwdInChild(ProcessBuilder pb) {
  492. return javaChildOutput(pb, "pwd");
  493. }
  494. private static final String javaExe =
  495. System.getProperty("java.home") +
  496. File.separator + "bin" + File.separator + "java";
  497. private static final String classpath =
  498. System.getProperty("java.class.path");
  499. private static final List<String> javaChildArgs =
  500. Arrays.asList(new String[]
  501. { javaExe, "-classpath", absolutifyPath(classpath),
  502. "Basic$JavaChild"});
  503. private static void testEncoding(String encoding, String tested) {
  504. try {
  505. // If round trip conversion works, should be able to set env vars
  506. // correctly in child.
  507. if (new String(tested.getBytes()).equals(tested)) {
  508. out.println("Testing " + encoding + " environment values");
  509. ProcessBuilder pb = new ProcessBuilder();
  510. pb.environment().put("ASCIINAME",tested);
  511. equal(getenvInChild(pb,"ASCIINAME"), tested);
  512. }
  513. } catch (Throwable t) { unexpected(t); }
  514. }
  515. static class Windows {
  516. public static boolean is() { return is; }
  517. private static final boolean is =
  518. System.getProperty("os.name").startsWith("Windows");
  519. }
  520. static class Unix {
  521. public static boolean is() { return is; }
  522. private static final boolean is =
  523. (! Windows.is() &&
  524. new File("/bin/sh").exists() &&
  525. new File("/bin/true").exists() &&
  526. new File("/bin/false").exists());
  527. }
  528. static class UnicodeOS {
  529. public static boolean is() { return is; }
  530. private static final String osName = System.getProperty("os.name");
  531. private static final boolean is =
  532. // MacOS X would probably also qualify
  533. osName.startsWith("Windows") &&
  534. ! osName.startsWith("Windows 9") &&
  535. ! osName.equals("Windows Me");
  536. }
  537. static class MacOSX {
  538. public static boolean is() { return is; }
  539. private static final String osName = System.getProperty("os.name");
  540. private static final boolean is = osName.contains("OS X");
  541. }
  542. static class True {
  543. public static int exitValue() { return 0; }
  544. }
  545. private static class False {
  546. public static int exitValue() { return exitValue; }
  547. private static final int exitValue = exitValue0();
  548. private static int exitValue0() {
  549. // /bin/false returns an *unspecified* non-zero number.
  550. try {
  551. if (! Unix.is())
  552. return -1;
  553. else {
  554. int rc = new ProcessBuilder("/bin/false")
  555. .start().waitFor();
  556. check(rc != 0);
  557. return rc;
  558. }
  559. } catch (Throwable t) { unexpected(t); return -1; }
  560. }
  561. }
  562. static class EnglishUnix {
  563. private final static Boolean is =
  564. (! Windows.is() && isEnglish("LANG") && isEnglish("LC_ALL"));
  565. private static boolean isEnglish(String envvar) {
  566. String val = getenv(envvar);
  567. return (val == null) || val.matches("en.*");
  568. }
  569. /** Returns true if we can expect English OS error strings */
  570. static boolean is() { return is; }
  571. }
  572. static class DelegatingProcess extends Process {
  573. final Process p;
  574. DelegatingProcess(Process p) {
  575. this.p = p;
  576. }
  577. @Override
  578. public void destroy() {
  579. p.destroy();
  580. }
  581. @Override
  582. public int exitValue() {
  583. return p.exitValue();
  584. }
  585. @Override
  586. public int waitFor() throws InterruptedException {
  587. return p.waitFor();
  588. }
  589. @Override
  590. public OutputStream getOutputStream() {
  591. return p.getOutputStream();
  592. }
  593. @Override
  594. public InputStream getInputStream() {
  595. return p.getInputStream();
  596. }
  597. @Override
  598. public InputStream getErrorStream() {
  599. return p.getErrorStream();
  600. }
  601. }
  602. private static boolean matches(String str, String regex) {
  603. return Pattern.compile(regex).matcher(str).find();
  604. }
  605. private static String matchAndExtract(String str, String regex) {
  606. Matcher matcher = Pattern.compile(regex).matcher(str);
  607. if (matcher.find()) {
  608. return matcher.group();
  609. } else {
  610. return "";
  611. }
  612. }
  613. /* Only used for Mac OS X --
  614. * Mac OS X (may) add the variable __CF_USER_TEXT_ENCODING to an empty
  615. * environment. The environment variable JAVA_MAIN_CLASS_<pid> may also
  616. * be set in Mac OS X.
  617. * Remove them both from the list of env variables
  618. */
  619. private static String removeMacExpectedVars(String vars) {
  620. // Check for __CF_USER_TEXT_ENCODING
  621. String cleanedVars = vars.replace("__CF_USER_TEXT_ENCODING="
  622. +cfUserTextEncoding+",","");
  623. // Check for JAVA_MAIN_CLASS_<pid>
  624. String javaMainClassStr
  625. = matchAndExtract(cleanedVars,
  626. "JAVA_MAIN_CLASS_\\d+=Basic.JavaChild,");
  627. return cleanedVars.replace(javaMainClassStr,"");
  628. }
  629. private static String sortByLinesWindowsly(String text) {
  630. String[] lines = text.split("\n");
  631. Arrays.sort(lines, new WindowsComparator());
  632. StringBuilder sb = new StringBuilder();
  633. for (String line : lines)
  634. sb.append(line).append("\n");
  635. return sb.toString();
  636. }
  637. private static void checkMapSanity(Map<String,String> map) {
  638. try {
  639. Set<String> keySet = map.keySet();
  640. Collection<String> values = map.values();
  641. Set<Map.Entry<String,String>> entrySet = map.entrySet();
  642. equal(entrySet.size(), keySet.size());
  643. equal(entrySet.size(), values.size());
  644. StringBuilder s1 = new StringBuilder();
  645. for (Map.Entry<String,String> e : entrySet)
  646. s1.append(e.getKey() + "=" + e.getValue() + "\n");
  647. StringBuilder s2 = new StringBuilder();
  648. for (String var : keySet)
  649. s2.append(var + "=" + map.get(var) + "\n");
  650. equal(s1.toString(), s2.toString());
  651. Iterator<String> kIter = keySet.iterator();
  652. Iterator<String> vIter = values.iterator();
  653. Iterator<Map.Entry<String,String>> eIter = entrySet.iterator();
  654. while (eIter.hasNext()) {
  655. Map.Entry<String,String> entry = eIter.next();
  656. String key = kIter.next();
  657. String value = vIter.next();
  658. check(entrySet.contains(entry));
  659. check(keySet.contains(key));
  660. check(values.contains(value));
  661. check(map.containsKey(key));
  662. check(map.containsValue(value));
  663. equal(entry.getKey(), key);
  664. equal(entry.getValue(), value);
  665. }
  666. check(! kIter.hasNext() &&
  667. ! vIter.hasNext());
  668. } catch (Throwable t) { unexpected(t); }
  669. }
  670. private static void checkMapEquality(Map<String,String> map1,
  671. Map<String,String> map2) {
  672. try {
  673. equal(map1.size(), map2.size());
  674. equal(map1.isEmpty(), map2.isEmpty());
  675. for (String key : map1.keySet()) {
  676. equal(map1.get(key), map2.get(key));
  677. check(map2.keySet().contains(key));
  678. }
  679. equal(map1, map2);
  680. equal(map2, map1);
  681. equal(map1.entrySet(), map2.entrySet());
  682. equal(map2.entrySet(), map1.entrySet());
  683. equal(map1.keySet(), map2.keySet());
  684. equal(map2.keySet(), map1.keySet());
  685. equal(map1.hashCode(), map2.hashCode());
  686. equal(map1.entrySet().hashCode(), map2.entrySet().hashCode());
  687. equal(map1.keySet().hashCode(), map2.keySet().hashCode());
  688. } catch (Throwable t) { unexpected(t); }
  689. }
  690. static void checkRedirects(ProcessBuilder pb,
  691. Redirect in, Redirect out, Redirect err) {
  692. equal(pb.redirectInput(), in);
  693. equal(pb.redirectOutput(), out);
  694. equal(pb.redirectError(), err);
  695. }
  696. static void redirectIO(ProcessBuilder pb,
  697. Redirect in, Redirect out, Redirect err) {
  698. pb.redirectInput(in);
  699. pb.redirectOutput(out);
  700. pb.redirectError(err);
  701. }
  702. static void setFileContents(File file, String contents) {
  703. try {
  704. Writer w = new FileWriter(file);
  705. w.write(contents);
  706. w.close();
  707. } catch (Throwable t) { unexpected(t); }
  708. }
  709. static String fileContents(File file) {
  710. try {
  711. Reader r = new FileReader(file);
  712. StringBuilder sb = new StringBuilder();
  713. char[] buffer = new char[1024];
  714. int n;
  715. while ((n = r.read(buffer)) != -1)
  716. sb.append(buffer,0,n);
  717. r.close();
  718. return new String(sb);
  719. } catch (Throwable t) { unexpected(t); return ""; }
  720. }
  721. static void testIORedirection() throws Throwable {
  722. final File ifile = new File("ifile");
  723. final File ofile = new File("ofile");
  724. final File efile = new File("efile");
  725. ifile.delete();
  726. ofile.delete();
  727. efile.delete();
  728. //----------------------------------------------------------------
  729. // Check mutual inequality of different types of Redirect
  730. //----------------------------------------------------------------
  731. Redirect[] redirects =
  732. { PIPE,
  733. INHERIT,
  734. Redirect.from(ifile),
  735. Redirect.to(ifile),
  736. Redirect.appendTo(ifile),
  737. Redirect.from(ofile),
  738. Redirect.to(ofile),
  739. Redirect.appendTo(ofile),
  740. };
  741. for (int i = 0; i < redirects.length; i++)
  742. for (int j = 0; j < redirects.length; j++)
  743. equal(redirects[i].equals(redirects[j]), (i == j));
  744. //----------------------------------------------------------------
  745. // Check basic properties of different types of Redirect
  746. //----------------------------------------------------------------
  747. equal(PIPE.type(), Redirect.Type.PIPE);
  748. equal(PIPE.toString(), "PIPE");
  749. equal(PIPE.file(), null);
  750. equal(INHERIT.type(), Redirect.Type.INHERIT);
  751. equal(INHERIT.toString(), "INHERIT");
  752. equal(INHERIT.file(), null);
  753. equal(Redirect.from(ifile).type(), Redirect.Type.READ);
  754. equal(Redirect.from(ifile).toString(),
  755. "redirect to read from file \"ifile\"");
  756. equal(Redirect.from(ifile).file(), ifile);
  757. equal(Redirect.from(ifile),
  758. Redirect.from(ifile));
  759. equal(Redirect.from(ifile).hashCode(),
  760. Redirect.from(ifile).hashCode());
  761. equal(Redirect.to(ofile).type(), Redirect.Type.WRITE);
  762. equal(Redirect.to(ofile).toString(),
  763. "redirect to write to file \"ofile\"");
  764. equal(Redirect.to(ofile).file(), ofile);
  765. equal(Redirect.to(ofile),
  766. Redirect.to(ofile));
  767. equal(Redirect.to(ofile).hashCode(),
  768. Redirect.to(ofile).hashCode());
  769. equal(Redirect.appendTo(ofile).type(), Redirect.Type.APPEND);
  770. equal(Redirect.appendTo(efile).toString(),
  771. "redirect to append to file \"efile\"");
  772. equal(Redirect.appendTo(efile).file(), efile);
  773. equal(Redirect.appendTo(efile),
  774. Redirect.appendTo(efile));
  775. equal(Redirect.appendTo(efile).hashCode(),
  776. Redirect.appendTo(efile).hashCode());
  777. //----------------------------------------------------------------
  778. // Check initial values of redirects
  779. //----------------------------------------------------------------
  780. List<String> childArgs = new ArrayList<String>(javaChildArgs);
  781. childArgs.add("testIO");
  782. final ProcessBuilder pb = new ProcessBuilder(childArgs);
  783. checkRedirects(pb, PIPE, PIPE, PIPE);
  784. //----------------------------------------------------------------
  785. // Check inheritIO
  786. //----------------------------------------------------------------
  787. pb.inheritIO();
  788. checkRedirects(pb, INHERIT, INHERIT, INHERIT);
  789. //----------------------------------------------------------------
  790. // Check setters and getters agree
  791. //----------------------------------------------------------------
  792. pb.redirectInput(ifile);
  793. equal(pb.redirectInput().file(), ifile);
  794. equal(pb.redirectInput(), Redirect.from(ifile));
  795. pb.redirectOutput(ofile);
  796. equal(pb.redirectOutput().file(), ofile);
  797. equal(pb.redirectOutput(), Redirect.to(ofile));
  798. pb.redirectError(efile);
  799. equal(pb.redirectError().file(), efile);
  800. equal(pb.redirectError(), Redirect.to(efile));
  801. THROWS(IllegalArgumentException.class,
  802. new Fun(){void f() {
  803. pb.redirectInput(Redirect.to(ofile)); }},
  804. new Fun(){void f() {
  805. pb.redirectInput(Redirect.appendTo(ofile)); }},
  806. new Fun(){void f() {
  807. pb.redirectOutput(Redirect.from(ifile)); }},
  808. new Fun(){void f() {
  809. pb.redirectError(Redirect.from(ifile)); }});
  810. THROWS(IOException.class,
  811. // Input file does not exist
  812. new Fun(){void f() throws Throwable { pb.start(); }});
  813. setFileContents(ifile, "standard input");
  814. //----------------------------------------------------------------
  815. // Writing to non-existent files
  816. //----------------------------------------------------------------
  817. {
  818. ProcessResults r = run(pb);
  819. equal(r.exitValue(), 0);
  820. equal(fileContents(ofile), "standard output");
  821. equal(fileContents(efile), "standard error");
  822. equal(r.out(), "");
  823. equal(r.err(), "");
  824. ofile.delete();
  825. efile.delete();
  826. }
  827. //----------------------------------------------------------------
  828. // Both redirectErrorStream + redirectError
  829. //----------------------------------------------------------------
  830. {
  831. pb.redirectErrorStream(true);
  832. ProcessResults r = run(pb);
  833. equal(r.exitValue(), 0);
  834. equal(fileContents(ofile),
  835. "standard error" + "standard output");
  836. equal(fileContents(efile), "");
  837. equal(r.out(), "");
  838. equal(r.err(), "");
  839. ofile.delete();
  840. efile.delete();
  841. }
  842. //----------------------------------------------------------------
  843. // Appending to existing files
  844. //----------------------------------------------------------------
  845. {
  846. setFileContents(ofile, "ofile-contents");
  847. setFileContents(efile, "efile-contents");
  848. pb.redirectOutput(Redirect.appendTo(ofile));
  849. pb.redirectError(Redirect.appendTo(efile));
  850. pb.redirectErrorStream(false);
  851. ProcessResults r = run(pb);
  852. equal(r.exitValue(), 0);
  853. equal(fileContents(ofile),
  854. "ofile-contents" + "standard output");
  855. equal(fileContents(efile),
  856. "efile-contents" + "standard error");
  857. equal(r.out(), "");
  858. equal(r.err(), "");
  859. ofile.delete();
  860. efile.delete();
  861. }
  862. //----------------------------------------------------------------
  863. // Replacing existing files
  864. //----------------------------------------------------------------
  865. {
  866. setFileContents(ofile, "ofile-contents");
  867. setFileContents(efile, "efile-contents");
  868. pb.redirectOutput(ofile);
  869. pb.redirectError(Redirect.to(efile));
  870. ProcessResults r = run(pb);
  871. equal(r.exitValue(), 0);
  872. equal(fileContents(ofile), "standard output");
  873. equal(fileContents(efile), "standard error");
  874. equal(r.out(), "");
  875. equal(r.err(), "");
  876. ofile.delete();
  877. efile.delete();
  878. }
  879. //----------------------------------------------------------------
  880. // Appending twice to the same file?
  881. //----------------------------------------------------------------
  882. {
  883. setFileContents(ofile, "ofile-contents");
  884. setFileContents(efile, "efile-contents");
  885. Redirect appender = Redirect.appendTo(ofile);
  886. pb.redirectOutput(appender);
  887. pb.redirectError(appender);
  888. ProcessResults r = run(pb);
  889. equal(r.exitValue(), 0);
  890. equal(fileContents(ofile),
  891. "ofile-contents" +
  892. "standard error" +
  893. "standard output");
  894. equal(fileContents(efile), "efile-contents");
  895. equal(r.out(), "");
  896. equal(r.err(), "");
  897. ifile.delete();
  898. ofile.delete();
  899. efile.delete();
  900. }
  901. //----------------------------------------------------------------
  902. // Testing INHERIT is harder.
  903. // Note that this requires __FOUR__ nested JVMs involved in one test,
  904. // if you count the harness JVM.
  905. //----------------------------------------------------------------
  906. {
  907. redirectIO(pb, PIPE, PIPE, PIPE);
  908. List<String> command = pb.command();
  909. command.set(command.size() - 1, "testInheritIO");
  910. Process p = pb.start();
  911. new PrintStream(p.getOutputStream()).print("standard input");
  912. p.getOutputStream().close();
  913. ProcessResults r = run(p);
  914. equal(r.exitValue(), 0);
  915. equal(r.out(), "standard output");
  916. equal(r.err(), "standard error");
  917. }
  918. //----------------------------------------------------------------
  919. // Test security implications of I/O redirection
  920. //----------------------------------------------------------------
  921. // Read access to current directory is always granted;
  922. // So create a tmpfile for input instead.
  923. final File tmpFile = File.createTempFile("Basic", "tmp");
  924. setFileContents(tmpFile, "standard input");
  925. final Policy policy = new Policy();
  926. Policy.setPolicy(policy);
  927. System.setSecurityManager(new SecurityManager());
  928. try {
  929. final Permission xPermission
  930. = new FilePermission("<<ALL FILES>>", "execute");
  931. final Permission rxPermission
  932. = new FilePermission("<<ALL FILES>>", "read,execute");
  933. final Permission wxPermission
  934. = new FilePermission("<<ALL FILES>>", "write,execute");
  935. final Permission rwxPermission
  936. = new FilePermission("<<ALL FILES>>", "read,write,execute");
  937. THROWS(SecurityException.class,
  938. new Fun() { void f() throws IOException {
  939. policy.setPermissions(xPermission);
  940. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  941. pb.start();}},
  942. new Fun() { void f() throws IOException {
  943. policy.setPermissions(rxPermission);
  944. redirectIO(pb, PIPE, to(ofile), PIPE);
  945. pb.start();}},
  946. new Fun() { void f() throws IOException {
  947. policy.setPermissions(rxPermission);
  948. redirectIO(pb, PIPE, PIPE, to(efile));
  949. pb.start();}});
  950. {
  951. policy.setPermissions(rxPermission);
  952. redirectIO(pb, from(tmpFile), PIPE, PIPE);
  953. ProcessResults r = run(pb);
  954. equal(r.out(), "standard output");
  955. equal(r.err(), "standard error");
  956. }
  957. {
  958. policy.setPermissions(wxPermission);
  959. redirectIO(pb, PIPE, to(ofile), to(efile));
  960. Process p = pb.start();
  961. new PrintStream(p.getOutputStream()).print("standard input");
  962. p.getOutputStream().close();
  963. ProcessResults r = run(p);
  964. policy.setPermissions(rwxPermission);
  965. equal(fileContents(ofile), "standard output");
  966. equal(fileContents(efile), "standard error");
  967. }
  968. {
  969. policy.setPermissions(rwxPermission);
  970. redirectIO(pb, from(tmpFile), to(ofile), to(efile));
  971. ProcessResults r = run(pb);
  972. policy.setPermissions(rwxPermission);
  973. equal(fileContents(ofile), "standard output");
  974. equal(fileContents(efile), "standard error");
  975. }
  976. } finally {
  977. policy.setPermissions(new RuntimePermission("setSecurityManager"));
  978. System.setSecurityManager(null);
  979. tmpFile.delete();
  980. ifile.delete();
  981. ofile.delete();
  982. efile.delete();
  983. }
  984. }
  985. private static void realMain(String[] args) throws Throwable {
  986. if (Windows.is())
  987. System.out.println("This appears to be a Windows system.");
  988. if (Unix.is())
  989. System.out.println("This appears to be a Unix system.");
  990. if (UnicodeOS.is())
  991. System.out.println("This appears to be a Unicode-based OS.");
  992. try { testIORedirection(); }
  993. catch (Throwable t) { unexpected(t); }
  994. //----------------------------------------------------------------
  995. // Basic tests for setting, replacing and deleting envvars
  996. //----------------------------------------------------------------
  997. try {
  998. ProcessBuilder pb = new ProcessBuilder();
  999. Map<String,String> environ = pb.environment();
  1000. // New env var
  1001. environ.put("QUUX", "BAR");
  1002. equal(environ.get("QUUX"), "BAR");
  1003. equal(getenvInChild(pb,"QUUX"), "BAR");
  1004. // Modify env var
  1005. environ.put("QUUX","bear");
  1006. equal(environ.get("QUUX"), "bear");
  1007. equal(getenvInChild(pb,"QUUX"), "bear");
  1008. checkMapSanity(environ);
  1009. // Remove env var
  1010. environ.remove("QUUX");
  1011. equal(environ.get("QUUX"), null);
  1012. equal(getenvInChild(pb,"QUUX"), "null");
  1013. checkMapSanity(environ);
  1014. // Remove non-existent env var
  1015. environ.remove("QUUX");
  1016. equal(environ.get("QUUX"), null);
  1017. equal(getenvInChild(pb,"QUUX"), "null");
  1018. checkMapSanity(environ);
  1019. } catch (Throwable t) { unexpected(t); }
  1020. //----------------------------------------------------------------
  1021. // Pass Empty environment to child
  1022. //----------------------------------------------------------------
  1023. try {
  1024. ProcessBuilder pb = new ProcessBuilder();
  1025. pb.environment().clear();
  1026. String expected = Windows.is() ? "SystemRoot="+systemRoot+",": "";
  1027. if (Windows.is()) {
  1028. pb.environment().put("SystemRoot", systemRoot);
  1029. }
  1030. String result = getenvInChild(pb);
  1031. if (MacOSX.is()) {
  1032. result = removeMacExpectedVars(result);
  1033. }
  1034. equal(result, expected);
  1035. } catch (Throwable t) { unexpected(t); }
  1036. //----------------------------------------------------------------
  1037. // System.getenv() is read-only.
  1038. //----------------------------------------------------------------
  1039. THROWS(UnsupportedOperationException.class,
  1040. new Fun(){void f(){ getenv().put("FOO","BAR");}},
  1041. new Fun(){void f(){ getenv().remove("PATH");}},
  1042. new Fun(){void f(){ getenv().keySet().remove("PATH");}},
  1043. new Fun(){void f(){ getenv().values().remove("someValue");}});
  1044. try {
  1045. Collection<Map.Entry<String,String>> c = getenv().entrySet();
  1046. if (! c.isEmpty())
  1047. try {
  1048. c.iterator().next().setValue("foo");
  1049. fail("Expected UnsupportedOperationException not thrown");
  1050. } catch (UnsupportedOperationException e) {} // OK
  1051. } catch (Throwable t) { unexpected(t); }
  1052. //----------------------------------------------------------------
  1053. // System.getenv() always returns the same object in our implementation.
  1054. //----------------------------------------------------------------
  1055. try {
  1056. check(System.getenv() == System.getenv());
  1057. } catch (Throwable t) { unexpected(t); }
  1058. //----------------------------------------------------------------
  1059. // You can't create an env var name containing "=",
  1060. // or an env var name or value containing NUL.
  1061. //----------------------------------------------------------------
  1062. {
  1063. final Map<String,String> m = new ProcessBuilder().environment();
  1064. THROWS(IllegalArgumentException.class,
  1065. new Fun(){void f(){ m.put("FOO=","BAR");}},
  1066. new Fun(){void f(){ m.put("FOO\u0000","BAR");}},
  1067. new Fun(){void f(){ m.put("FOO","BAR\u0000");}});
  1068. }
  1069. //----------------------------------------------------------------
  1070. // Commands must never be null.
  1071. //----------------------------------------------------------------
  1072. THROWS(NullPointerException.class,
  1073. new Fun(){void f(){
  1074. new ProcessBuilder((List<String>)null);}},
  1075. new Fun(){void f(){
  1076. new ProcessBuilder().command((List<String>)null);}});
  1077. //----------------------------------------------------------------
  1078. // Put in a command; get the same one back out.
  1079. //----------------------------------------------------------------
  1080. try {
  1081. List<String> command = new ArrayList<String>();
  1082. ProcessBuilder pb = new ProcessBuilder(command);
  1083. check(pb.command() == command);
  1084. List<String> command2 = new ArrayList<String>(2);
  1085. command2.add("foo");
  1086. command2.add("bar");
  1087. pb.command(command2);
  1088. check(pb.command() == command2);
  1089. pb.command("foo", "bar");
  1090. check(pb.command() != command2 && pb.command().equals(command2));
  1091. pb.command(command2);
  1092. command2.add("baz");
  1093. equal(pb.command().get(2), "baz");
  1094. } catch (Throwable t) { unexpected(t); }
  1095. //----------------------------------------------------------------
  1096. // Commands must contain at least one element.
  1097. //----------------------------------------------------------------
  1098. THROWS(IndexOutOfBoundsException.class,

Large files files are truncated, but you can click here to view the full file