1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.BufferedReader ; 22 import java.io.ByteArrayOutputStream ; 23 import java.io.File ; 24 import java.io.FileWriter ; 25 import java.io.IOException ; 26 import java.io.OutputStream ; 27 import java.io.PrintWriter ; 28 import java.io.StringReader ; 29 import java.lang.reflect.InvocationTargetException ; 30 import java.lang.reflect.Method ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.Vector ; 34 35 import org.apache.tools.ant.BuildException; 36 import org.apache.tools.ant.MagicNames; 37 import org.apache.tools.ant.Project; 38 import org.apache.tools.ant.Task; 39 import org.apache.tools.ant.taskdefs.condition.Os; 40 import org.apache.tools.ant.types.Commandline; 41 import org.apache.tools.ant.util.FileUtils; 42 import org.apache.tools.ant.util.StringUtils; 43 44 50 public class Execute { 51 52 55 public static final int INVALID = Integer.MAX_VALUE; 56 57 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 58 59 private String [] cmdl = null; 60 private String [] env = null; 61 private int exitValue = INVALID; 62 private ExecuteStreamHandler streamHandler; 63 private ExecuteWatchdog watchdog; 64 private File workingDirectory = null; 65 private Project project = null; 66 private boolean newEnvironment = false; 67 private boolean spawn = false; 69 70 71 72 private boolean useVMLauncher = true; 73 74 private static String antWorkingDirectory = System.getProperty("user.dir"); 75 private static CommandLauncher vmLauncher = null; 76 private static CommandLauncher shellLauncher = null; 77 private static Vector procEnvironment = null; 78 79 80 private static ProcessDestroyer processDestroyer = new ProcessDestroyer(); 81 82 83 private static boolean environmentCaseInSensitive = false; 84 85 88 static { 89 try { 91 if (!Os.isFamily("os/2")) { 92 vmLauncher = new Java13CommandLauncher(); 93 } 94 } catch (NoSuchMethodException exc) { 95 } 97 if (Os.isFamily("mac") && !Os.isFamily("unix")) { 98 shellLauncher = new MacCommandLauncher(new CommandLauncher()); 100 } else if (Os.isFamily("os/2")) { 101 shellLauncher = new OS2CommandLauncher(new CommandLauncher()); 103 } else if (Os.isFamily("windows")) { 104 environmentCaseInSensitive = true; 105 CommandLauncher baseLauncher = new CommandLauncher(); 106 107 if (!Os.isFamily("win9x")) { 108 shellLauncher = new WinNTCommandLauncher(baseLauncher); 110 } else { 111 shellLauncher 113 = new ScriptCommandLauncher("bin/antRun.bat", baseLauncher); 114 } 115 } else if (Os.isFamily("netware")) { 116 117 CommandLauncher baseLauncher = new CommandLauncher(); 118 119 shellLauncher 120 = new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher); 121 } else if (Os.isFamily("openvms")) { 122 try { 124 shellLauncher = new VmsCommandLauncher(); 125 } catch (NoSuchMethodException exc) { 126 } 128 } else { 129 shellLauncher = new ScriptCommandLauncher("bin/antRun", 131 new CommandLauncher()); 132 } 133 } 134 135 144 public void setSpawn(boolean spawn) { 145 this.spawn = spawn; 146 } 147 148 154 public static synchronized Vector getProcEnvironment() { 155 if (procEnvironment != null) { 156 return procEnvironment; 157 } 158 procEnvironment = new Vector (); 159 try { 160 ByteArrayOutputStream out = new ByteArrayOutputStream (); 161 Execute exe = new Execute(new PumpStreamHandler(out)); 162 exe.setCommandline(getProcEnvCommand()); 163 exe.setNewenvironment(true); 165 int retval = exe.execute(); 166 if (retval != 0) { 167 } 169 BufferedReader in = 170 new BufferedReader (new StringReader (toString(out))); 171 172 if (Os.isFamily("openvms")) { 173 procEnvironment = addVMSLogicals(procEnvironment, in); 174 return procEnvironment; 175 } 176 String var = null; 177 String line, lineSep = StringUtils.LINE_SEP; 178 while ((line = in.readLine()) != null) { 179 if (line.indexOf('=') == -1) { 180 if (var == null) { 183 var = lineSep + line; 184 } else { 185 var += lineSep + line; 186 } 187 } else { 188 if (var != null) { 190 procEnvironment.addElement(var); 191 } 192 var = line; 193 } 194 } 195 if (var != null) { 197 procEnvironment.addElement(var); 198 } 199 } catch (java.io.IOException exc) { 200 exc.printStackTrace(); 201 } 203 return procEnvironment; 204 } 205 206 212 private static String [] getProcEnvCommand() { 213 if (Os.isFamily("os/2")) { 214 return new String [] {"cmd", "/c", "set" }; 216 } else if (Os.isFamily("windows")) { 217 if (Os.isFamily("win9x")) { 219 return new String [] {"command.com", "/c", "set" }; 221 } else { 222 return new String [] {"cmd", "/c", "set" }; 224 } 225 } else if (Os.isFamily("z/os") || Os.isFamily("unix")) { 226 228 String [] cmd = new String [1]; 230 if (new File ("/bin/env").canRead()) { 231 cmd[0] = "/bin/env"; 232 } else if (new File ("/usr/bin/env").canRead()) { 233 cmd[0] = "/usr/bin/env"; 234 } else { 235 cmd[0] = "env"; 237 } 238 return cmd; 239 } else if (Os.isFamily("netware") || Os.isFamily("os/400")) { 240 return new String [] {"env"}; 242 } else if (Os.isFamily("openvms")) { 243 return new String [] {"show", "logical"}; 244 } else { 245 return null; 248 } 249 } 250 251 262 public static String toString(ByteArrayOutputStream bos) { 263 if (Os.isFamily("z/os")) { 264 try { 265 return bos.toString("Cp1047"); 266 } catch (java.io.UnsupportedEncodingException e) { 267 } 269 } else if (Os.isFamily("os/400")) { 270 try { 271 return bos.toString("Cp500"); 272 } catch (java.io.UnsupportedEncodingException e) { 273 } 275 } 276 return bos.toString(); 277 } 278 279 283 public Execute() { 284 this(new PumpStreamHandler(), null); 285 } 286 287 293 public Execute(ExecuteStreamHandler streamHandler) { 294 this(streamHandler, null); 295 } 296 297 305 public Execute(ExecuteStreamHandler streamHandler, 306 ExecuteWatchdog watchdog) { 307 setStreamHandler(streamHandler); 308 this.watchdog = watchdog; 309 if (Os.isFamily("openvms")) { 312 useVMLauncher = false; 313 } 314 } 315 316 321 public void setStreamHandler(ExecuteStreamHandler streamHandler) { 322 this.streamHandler = streamHandler; 323 } 324 325 330 public String [] getCommandline() { 331 return cmdl; 332 } 333 334 339 public void setCommandline(String [] commandline) { 340 cmdl = commandline; 341 } 342 343 348 public void setNewenvironment(boolean newenv) { 349 newEnvironment = newenv; 350 } 351 352 357 public String [] getEnvironment() { 358 return (env == null || newEnvironment) 359 ? env : patchEnvironment(); 360 } 361 362 368 public void setEnvironment(String [] env) { 369 this.env = env; 370 } 371 372 382 public void setWorkingDirectory(File wd) { 383 workingDirectory = 384 (wd == null || wd.getAbsolutePath().equals(antWorkingDirectory)) 385 ? null : wd; 386 } 387 388 393 public File getWorkingDirectory() { 394 return workingDirectory == null ? new File (antWorkingDirectory) 395 : workingDirectory; 396 } 397 398 406 public void setAntRun(Project project) throws BuildException { 407 this.project = project; 408 } 409 410 420 public void setVMLauncher(boolean useVMLauncher) { 421 this.useVMLauncher = useVMLauncher; 422 } 423 424 437 public static Process launch(Project project, String [] command, 438 String [] env, File dir, boolean useVM) 439 throws IOException { 440 if (dir != null && !dir.exists()) { 441 throw new BuildException(dir + " doesn't exist."); 442 } 443 CommandLauncher launcher 444 = ((useVM && vmLauncher != null) ? vmLauncher : shellLauncher); 445 return launcher.exec(project, command, env, dir); 446 } 447 448 455 public int execute() throws IOException { 456 if (workingDirectory != null && !workingDirectory.exists()) { 457 throw new BuildException(workingDirectory + " doesn't exist."); 458 } 459 final Process process = launch(project, getCommandline(), 460 getEnvironment(), workingDirectory, 461 useVMLauncher); 462 try { 463 streamHandler.setProcessInputStream(process.getOutputStream()); 464 streamHandler.setProcessOutputStream(process.getInputStream()); 465 streamHandler.setProcessErrorStream(process.getErrorStream()); 466 } catch (IOException e) { 467 process.destroy(); 468 throw e; 469 } 470 streamHandler.start(); 471 472 try { 473 processDestroyer.add(process); 476 477 if (watchdog != null) { 478 watchdog.start(process); 479 } 480 waitFor(process); 481 482 if (watchdog != null) { 483 watchdog.stop(); 484 } 485 streamHandler.stop(); 486 closeStreams(process); 487 488 if (watchdog != null) { 489 watchdog.checkException(); 490 } 491 return getExitValue(); 492 } catch (ThreadDeath t) { 493 process.destroy(); 495 throw t; 496 } finally { 497 processDestroyer.remove(process); 501 } 502 } 503 504 512 public void spawn() throws IOException { 513 if (workingDirectory != null && !workingDirectory.exists()) { 514 throw new BuildException(workingDirectory + " doesn't exist."); 515 } 516 final Process process = launch(project, getCommandline(), 517 getEnvironment(), workingDirectory, 518 useVMLauncher); 519 if (Os.isFamily("windows")) { 520 try { 521 Thread.sleep(1000); 522 } catch (InterruptedException e) { 523 project.log("interruption in the sleep after having spawned a" 524 + " process", Project.MSG_VERBOSE); 525 } 526 } 527 OutputStream dummyOut = new OutputStream () { 528 public void write(int b) throws IOException { 529 } 530 }; 531 532 ExecuteStreamHandler handler = new PumpStreamHandler(dummyOut); 533 handler.setProcessErrorStream(process.getErrorStream()); 534 handler.setProcessOutputStream(process.getInputStream()); 535 handler.start(); 536 process.getOutputStream().close(); 537 538 project.log("spawned process " + process.toString(), 539 Project.MSG_VERBOSE); 540 } 541 542 547 protected void waitFor(Process process) { 548 try { 549 process.waitFor(); 550 setExitValue(process.exitValue()); 551 } catch (InterruptedException e) { 552 process.destroy(); 553 } 554 } 555 556 561 protected void setExitValue(int value) { 562 exitValue = value; 563 } 564 565 570 public int getExitValue() { 571 return exitValue; 572 } 573 574 589 public static boolean isFailure(int exitValue) { 590 return Os.isFamily("openvms") 593 ? (exitValue % 2 == 0) : (exitValue != 0); 594 } 595 596 602 public boolean isFailure() { 603 return isFailure(getExitValue()); 604 } 605 606 611 public boolean killedProcess() { 612 return watchdog != null && watchdog.killedProcess(); 613 } 614 615 619 private String [] patchEnvironment() { 620 if (Os.isFamily("openvms")) { 624 return env; 625 } 626 Vector osEnv = (Vector ) getProcEnvironment().clone(); 627 for (int i = 0; i < env.length; i++) { 628 String keyValue = env[i]; 629 String key = keyValue.substring(0, keyValue.indexOf('=') + 1); 631 if (environmentCaseInSensitive) { 632 key = key.toLowerCase(); 634 } 635 int size = osEnv.size(); 636 for (int j = 0; j < size; j++) { 639 String osEnvItem = (String ) osEnv.elementAt(j); 640 String convertedItem = environmentCaseInSensitive 641 ? osEnvItem.toLowerCase() : osEnvItem; 642 if (convertedItem.startsWith(key)) { 643 osEnv.removeElementAt(j); 644 if (environmentCaseInSensitive) { 645 keyValue = osEnvItem.substring(0, key.length()) 647 + keyValue.substring(key.length()); 648 } 649 break; 650 } 651 } 652 osEnv.addElement(keyValue); 654 } 655 return (String []) (osEnv.toArray(new String [osEnv.size()])); 656 } 657 658 667 public static void runCommand(Task task, String [] cmdline) 668 throws BuildException { 669 try { 670 task.log(Commandline.describeCommand(cmdline), 671 Project.MSG_VERBOSE); 672 Execute exe = new Execute( 673 new LogStreamHandler(task, Project.MSG_INFO, Project.MSG_ERR)); 674 exe.setAntRun(task.getProject()); 675 exe.setCommandline(cmdline); 676 int retval = exe.execute(); 677 if (isFailure(retval)) { 678 throw new BuildException(cmdline[0] 679 + " failed with return code " + retval, task.getLocation()); 680 } 681 } catch (java.io.IOException exc) { 682 throw new BuildException("Could not launch " + cmdline[0] + ": " 683 + exc, task.getLocation()); 684 } 685 } 686 687 691 public static void closeStreams(Process process) { 692 FileUtils.close(process.getInputStream()); 693 FileUtils.close(process.getOutputStream()); 694 FileUtils.close(process.getErrorStream()); 695 } 696 697 708 private static Vector addVMSLogicals(Vector environment, BufferedReader in) 709 throws IOException { 710 HashMap logicals = new HashMap (); 711 String logName = null, logValue = null, newLogName; 712 String line = null; 713 while ((line = in.readLine()) != null) { 714 if (line.startsWith("\t=")) { 716 if (logName != null) { 718 logValue += "," + line.substring(4, line.length() - 1); 719 } 720 } else if (line.startsWith(" \"")) { 721 if (logName != null) { 723 logicals.put(logName, logValue); 724 } 725 int eqIndex = line.indexOf('='); 726 newLogName = line.substring(3, eqIndex - 2); 727 if (logicals.containsKey(newLogName)) { 728 logName = null; 730 } else { 731 logName = newLogName; 732 logValue = line.substring(eqIndex + 3, line.length() - 1); 733 } 734 } 735 } 736 if (logName != null) { 738 logicals.put(logName, logValue); 739 } 740 for (Iterator i = logicals.keySet().iterator(); i.hasNext();) { 741 String logical = (String ) i.next(); 742 environment.add(logical + "=" + logicals.get(logical)); 743 } 744 return environment; 745 } 746 747 752 private static class CommandLauncher { 753 764 public Process exec(Project project, String [] cmd, String [] env) 765 throws IOException { 766 if (project != null) { 767 project.log("Execute:CommandLauncher: " 768 + Commandline.describeCommand(cmd), Project.MSG_DEBUG); 769 } 770 return Runtime.getRuntime().exec(cmd, env); 771 } 772 773 786 public Process exec(Project project, String [] cmd, String [] env, 787 File workingDir) throws IOException { 788 if (workingDir == null) { 789 return exec(project, cmd, env); 790 } 791 throw new IOException ("Cannot execute a process in different " 792 + "directory under this JVM"); 793 } 794 } 795 796 800 private static class Java13CommandLauncher extends CommandLauncher { 801 private Method myExecWithCWD; 802 803 public Java13CommandLauncher() throws NoSuchMethodException { 804 myExecWithCWD = Runtime .class.getMethod("exec", 807 new Class [] {String [].class, String [].class, File .class}); 808 } 809 810 821 public Process exec(Project project, String [] cmd, String [] env, 822 File workingDir) throws IOException { 823 try { 824 if (project != null) { 825 project.log("Execute:Java13CommandLauncher: " 826 + Commandline.describeCommand(cmd), Project.MSG_DEBUG); 827 } 828 return (Process ) myExecWithCWD.invoke(Runtime.getRuntime(), 829 new Object [] {cmd, env, workingDir}); 830 } catch (InvocationTargetException exc) { 831 Throwable realexc = exc.getTargetException(); 832 if (realexc instanceof ThreadDeath ) { 833 throw (ThreadDeath ) realexc; 834 } else if (realexc instanceof IOException ) { 835 throw (IOException ) realexc; 836 } else { 837 throw new BuildException("Unable to execute command", 838 realexc); 839 } 840 } catch (Exception exc) { 841 throw new BuildException("Unable to execute command", exc); 843 } 844 } 845 } 846 847 852 private static class CommandLauncherProxy extends CommandLauncher { 853 private CommandLauncher myLauncher; 854 855 CommandLauncherProxy(CommandLauncher launcher) { 856 myLauncher = launcher; 857 } 858 859 869 public Process exec(Project project, String [] cmd, String [] env) 870 throws IOException { 871 return myLauncher.exec(project, cmd, env); 872 } 873 } 874 875 883 private static class OS2CommandLauncher extends CommandLauncherProxy { 884 OS2CommandLauncher(CommandLauncher launcher) { 885 super(launcher); 886 } 887 888 899 public Process exec(Project project, String [] cmd, String [] env, 900 File workingDir) throws IOException { 901 File commandDir = workingDir; 902 if (workingDir == null) { 903 if (project != null) { 904 commandDir = project.getBaseDir(); 905 } else { 906 return exec(project, cmd, env); 907 } 908 } 909 final int preCmdLength = 7; 912 final String cmdDir = commandDir.getAbsolutePath(); 913 String [] newcmd = new String [cmd.length + preCmdLength]; 914 newcmd[0] = "cmd"; 915 newcmd[1] = "/c"; 916 newcmd[2] = cmdDir.substring(0, 2); 917 newcmd[3] = "&&"; 918 newcmd[4] = "cd"; 919 newcmd[5] = cmdDir.substring(2); 920 newcmd[6] = "&&"; 921 System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length); 922 923 return exec(project, newcmd, env); 924 } 925 } 926 927 932 private static class WinNTCommandLauncher extends CommandLauncherProxy { 933 WinNTCommandLauncher(CommandLauncher launcher) { 934 super(launcher); 935 } 936 937 948 public Process exec(Project project, String [] cmd, String [] env, 949 File workingDir) throws IOException { 950 File commandDir = workingDir; 951 if (workingDir == null) { 952 if (project != null) { 953 commandDir = project.getBaseDir(); 954 } else { 955 return exec(project, cmd, env); 956 } 957 } 958 final int preCmdLength = 6; 961 String [] newcmd = new String [cmd.length + preCmdLength]; 962 newcmd[0] = "cmd"; 963 newcmd[1] = "/c"; 964 newcmd[2] = "cd"; 965 newcmd[3] = "/d"; 966 newcmd[4] = commandDir.getAbsolutePath(); 967 newcmd[5] = "&&"; 968 System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length); 969 970 return exec(project, newcmd, env); 971 } 972 } 973 974 978 private static class MacCommandLauncher extends CommandLauncherProxy { 979 MacCommandLauncher(CommandLauncher launcher) { 980 super(launcher); 981 } 982 983 994 public Process exec(Project project, String [] cmd, String [] env, 995 File workingDir) throws IOException { 996 if (workingDir == null) { 997 return exec(project, cmd, env); 998 } 999 System.getProperties().put("user.dir", workingDir.getAbsolutePath()); 1000 try { 1001 return exec(project, cmd, env); 1002 } finally { 1003 System.getProperties().put("user.dir", antWorkingDirectory); 1004 } 1005 } 1006 } 1007 1008 1012 private static class ScriptCommandLauncher extends CommandLauncherProxy { 1013 ScriptCommandLauncher(String script, CommandLauncher launcher) { 1014 super(launcher); 1015 myScript = script; 1016 } 1017 1018 1029 public Process exec(Project project, String [] cmd, String [] env, 1030 File workingDir) throws IOException { 1031 if (project == null) { 1032 if (workingDir == null) { 1033 return exec(project, cmd, env); 1034 } 1035 throw new IOException ("Cannot locate antRun script: " 1036 + "No project provided"); 1037 } 1038 String antHome = project.getProperty(MagicNames.ANT_HOME); 1040 if (antHome == null) { 1041 throw new IOException ("Cannot locate antRun script: " 1042 + "Property '" + MagicNames.ANT_HOME + "' not found"); 1043 } 1044 String antRun = 1045 FILE_UTILS.resolveFile(project.getBaseDir(), 1046 antHome + File.separator + myScript).toString(); 1047 1048 File commandDir = workingDir; 1050 if (workingDir == null && project != null) { 1051 commandDir = project.getBaseDir(); 1052 } 1053 String [] newcmd = new String [cmd.length + 2]; 1054 newcmd[0] = antRun; 1055 newcmd[1] = commandDir.getAbsolutePath(); 1056 System.arraycopy(cmd, 0, newcmd, 2, cmd.length); 1057 1058 return exec(project, newcmd, env); 1059 } 1060 1061 private String myScript; 1062 } 1063 1064 1068 private static class PerlScriptCommandLauncher 1069 extends CommandLauncherProxy { 1070 private String myScript; 1071 1072 PerlScriptCommandLauncher(String script, CommandLauncher launcher) { 1073 super(launcher); 1074 myScript = script; 1075 } 1076 1077 1088 public Process exec(Project project, String [] cmd, String [] env, 1089 File workingDir) throws IOException { 1090 if (project == null) { 1091 if (workingDir == null) { 1092 return exec(project, cmd, env); 1093 } 1094 throw new IOException ("Cannot locate antRun script: " 1095 + "No project provided"); 1096 } 1097 String antHome = project.getProperty(MagicNames.ANT_HOME); 1099 if (antHome == null) { 1100 throw new IOException ("Cannot locate antRun script: " 1101 + "Property '" + MagicNames.ANT_HOME + "' not found"); 1102 } 1103 String antRun = 1104 FILE_UTILS.resolveFile(project.getBaseDir(), 1105 antHome + File.separator + myScript).toString(); 1106 1107 File commandDir = workingDir; 1109 if (workingDir == null && project != null) { 1110 commandDir = project.getBaseDir(); 1111 } 1112 String [] newcmd = new String [cmd.length + 3]; 1113 newcmd[0] = "perl"; 1114 newcmd[1] = antRun; 1115 newcmd[2] = commandDir.getAbsolutePath(); 1116 System.arraycopy(cmd, 0, newcmd, 3, cmd.length); 1117 1118 return exec(project, newcmd, env); 1119 } 1120 } 1121 1122 1127 private static class VmsCommandLauncher extends Java13CommandLauncher { 1128 1129 public VmsCommandLauncher() throws NoSuchMethodException { 1130 super(); 1131 } 1132 1133 1142 public Process exec(Project project, String [] cmd, String [] env) 1143 throws IOException { 1144 File cmdFile = createCommandFile(cmd, env); 1145 Process p 1146 = super.exec(project, new String [] {cmdFile.getPath()}, env); 1147 deleteAfter(cmdFile, p); 1148 return p; 1149 } 1150 1151 1164 public Process exec(Project project, String [] cmd, String [] env, 1165 File workingDir) throws IOException { 1166 File cmdFile = createCommandFile(cmd, env); 1167 Process p = super.exec(project, new String [] {cmdFile.getPath()}, 1168 env, workingDir); 1169 deleteAfter(cmdFile, p); 1170 return p; 1171 } 1172 1173 1181 private File createCommandFile(String [] cmd, String [] env) 1182 throws IOException { 1183 File script = FILE_UTILS.createTempFile("ANT", ".COM", null); 1184 script.deleteOnExit(); 1185 PrintWriter out = null; 1186 try { 1187 out = new PrintWriter (new FileWriter (script)); 1188 1189 if (env != null) { 1191 int eqIndex; 1192 for (int i = 0; i < env.length; i++) { 1193 eqIndex = env[i].indexOf('='); 1194 if (eqIndex != -1) { 1195 out.print("$ DEFINE/NOLOG "); 1196 out.print(env[i].substring(0, eqIndex)); 1197 out.print(" \""); 1198 out.print(env[i].substring(eqIndex + 1)); 1199 out.println('\"'); 1200 } 1201 } 1202 } 1203 out.print("$ " + cmd[0]); 1204 for (int i = 1; i < cmd.length; i++) { 1205 out.println(" -"); 1206 out.print(cmd[i]); 1207 } 1208 } finally { 1209 if (out != null) { 1210 out.close(); 1211 } 1212 } 1213 return script; 1214 } 1215 1216 private void deleteAfter(final File f, final Process p) { 1217 new Thread () { 1218 public void run() { 1219 try { 1220 p.waitFor(); 1221 } catch (InterruptedException e) { 1222 } 1224 FileUtils.delete(f); 1225 } 1226 } 1227 .start(); 1228 } 1229 } 1230} 1231 | Popular Tags |