PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/adoptopenjdk/jdk8-jdk
Java | 2457 lines | 1893 code | 258 blank | 306 comment | 175 complexity | 47b2486ac924c74e4d16ba19342132b9 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, BSD-3-Clause

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

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

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