1 18 19 package org.apache.tools.ant; 20 21 import java.io.File ; 22 import java.io.FileInputStream ; 23 import java.io.FileOutputStream ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.io.PrintStream ; 27 import java.util.Enumeration ; 28 import java.util.Properties ; 29 import java.util.Vector ; 30 import java.util.HashMap ; 31 32 import org.apache.tools.ant.input.DefaultInputHandler; 33 import org.apache.tools.ant.input.InputHandler; 34 import org.apache.tools.ant.launch.AntMain; 35 import org.apache.tools.ant.util.ClasspathUtils; 36 import org.apache.tools.ant.util.FileUtils; 37 import org.apache.tools.ant.util.ProxySetup; 38 39 40 51 public class Main implements AntMain { 52 53 54 public static final String DEFAULT_BUILD_FILENAME = "build.xml"; 55 56 57 private int msgOutputLevel = Project.MSG_INFO; 58 59 60 private File buildFile; 61 62 63 private static PrintStream out = System.out; 64 65 66 private static PrintStream err = System.err; 67 68 69 private Vector targets = new Vector (); 70 71 72 private Properties definedProps = new Properties (); 73 74 75 private Vector listeners = new Vector (1); 76 77 78 private Vector propertyFiles = new Vector (1); 79 80 81 private boolean allowInput = true; 82 83 84 private boolean keepGoingMode = false; 85 86 91 private String loggerClassname = null; 92 93 97 private String inputHandlerClassname = null; 98 99 102 private boolean emacsMode = false; 103 104 108 private boolean readyToRun = false; 109 110 114 private boolean projectHelp = false; 115 116 120 private static boolean isLogFileUsed = false; 121 122 125 private Integer threadPriority = null; 126 127 130 private boolean proxy = false; 131 132 139 private static void printMessage(Throwable t) { 140 String message = t.getMessage(); 141 if (message != null) { 142 System.err.println(message); 143 } 144 } 145 146 158 public static void start(String [] args, Properties additionalUserProperties, 159 ClassLoader coreLoader) { 160 Main m = new Main(); 161 m.startAnt(args, additionalUserProperties, coreLoader); 162 } 163 164 173 public void startAnt(String [] args, Properties additionalUserProperties, 174 ClassLoader coreLoader) { 175 176 try { 177 Diagnostics.validateVersion(); 178 processArgs(args); 179 } catch (Throwable exc) { 180 handleLogfile(); 181 printMessage(exc); 182 exit(1); 183 return; 184 } 185 186 if (additionalUserProperties != null) { 187 for (Enumeration e = additionalUserProperties.keys(); 188 e.hasMoreElements();) { 189 String key = (String ) e.nextElement(); 190 String property = additionalUserProperties.getProperty(key); 191 definedProps.put(key, property); 192 } 193 } 194 195 int exitCode = 1; 197 try { 198 try { 199 runBuild(coreLoader); 200 exitCode = 0; 201 } catch (ExitStatusException ese) { 202 exitCode = ese.getStatus(); 203 if (exitCode != 0) { 204 throw ese; 205 } 206 } 207 } catch (BuildException be) { 208 if (err != System.err) { 209 printMessage(be); 210 } 211 } catch (Throwable exc) { 212 exc.printStackTrace(); 213 printMessage(exc); 214 } finally { 215 handleLogfile(); 216 } 217 exit(exitCode); 218 } 219 220 226 protected void exit(int exitCode) { 227 System.exit(exitCode); 228 } 229 230 235 private static void handleLogfile() { 236 if (isLogFileUsed) { 237 FileUtils.close(out); 238 FileUtils.close(err); 239 } 240 } 241 242 249 public static void main(String [] args) { 250 start(args, null, null); 251 } 252 253 257 public Main() { 258 } 259 260 271 protected Main(String [] args) throws BuildException { 272 processArgs(args); 273 } 274 275 284 private void processArgs(String [] args) { 285 String searchForThis = null; 286 PrintStream logTo = null; 287 288 HashMap launchCommands = new HashMap (); 290 launchCommands.put("-lib", ""); 291 launchCommands.put("-cp", ""); 292 launchCommands.put("-noclasspath", ""); 293 launchCommands.put("--noclasspath", ""); 294 launchCommands.put("-nouserlib", ""); 295 launchCommands.put("--nouserlib", ""); 296 launchCommands.put("-main", ""); 297 299 for (int i = 0; i < args.length; i++) { 300 String arg = args[i]; 301 302 if (arg.equals("-help") || arg.equals("-h")) { 303 printUsage(); 304 return; 305 } else if (arg.equals("-version")) { 306 printVersion(); 307 return; 308 } else if (arg.equals("-diagnostics")) { 309 Diagnostics.doReport(System.out); 310 return; 311 } else if (arg.equals("-quiet") || arg.equals("-q")) { 312 msgOutputLevel = Project.MSG_WARN; 313 } else if (arg.equals("-verbose") || arg.equals("-v")) { 314 printVersion(); 315 msgOutputLevel = Project.MSG_VERBOSE; 316 } else if (arg.equals("-debug") || arg.equals("-d")) { 317 printVersion(); 318 msgOutputLevel = Project.MSG_DEBUG; 319 } else if (arg.equals("-noinput")) { 320 allowInput = false; 321 } else if (arg.equals("-logfile") || arg.equals("-l")) { 322 try { 323 File logFile = new File (args[i + 1]); 324 i++; 325 logTo = new PrintStream (new FileOutputStream (logFile)); 326 isLogFileUsed = true; 327 } catch (IOException ioe) { 328 String msg = "Cannot write on the specified log file. " 329 + "Make sure the path exists and you have write " 330 + "permissions."; 331 throw new BuildException(msg); 332 } catch (ArrayIndexOutOfBoundsException aioobe) { 333 String msg = "You must specify a log file when " 334 + "using the -log argument"; 335 throw new BuildException(msg); 336 } 337 } else if (arg.equals("-buildfile") || arg.equals("-file") 338 || arg.equals("-f")) { 339 try { 340 buildFile = new File (args[i + 1].replace('/', File.separatorChar)); 341 i++; 342 } catch (ArrayIndexOutOfBoundsException aioobe) { 343 String msg = "You must specify a buildfile when " 344 + "using the -buildfile argument"; 345 throw new BuildException(msg); 346 } 347 } else if (arg.equals("-listener")) { 348 try { 349 listeners.addElement(args[i + 1]); 350 i++; 351 } catch (ArrayIndexOutOfBoundsException aioobe) { 352 String msg = "You must specify a classname when " 353 + "using the -listener argument"; 354 throw new BuildException(msg); 355 } 356 } else if (arg.startsWith("-D")) { 357 358 368 369 String name = arg.substring(2, arg.length()); 370 String value = null; 371 int posEq = name.indexOf("="); 372 if (posEq > 0) { 373 value = name.substring(posEq + 1); 374 name = name.substring(0, posEq); 375 } else if (i < args.length - 1) { 376 value = args[++i]; 377 } else { 378 throw new BuildException("Missing value for property " 379 + name); 380 } 381 382 definedProps.put(name, value); 383 } else if (arg.equals("-logger")) { 384 if (loggerClassname != null) { 385 throw new BuildException("Only one logger class may " 386 + " be specified."); 387 } 388 try { 389 loggerClassname = args[++i]; 390 } catch (ArrayIndexOutOfBoundsException aioobe) { 391 throw new BuildException("You must specify a classname when" 392 + " using the -logger argument"); 393 } 394 } else if (arg.equals("-inputhandler")) { 395 if (inputHandlerClassname != null) { 396 throw new BuildException("Only one input handler class may " 397 + "be specified."); 398 } 399 try { 400 inputHandlerClassname = args[++i]; 401 } catch (ArrayIndexOutOfBoundsException aioobe) { 402 throw new BuildException("You must specify a classname when" 403 + " using the -inputhandler" 404 + " argument"); 405 } 406 } else if (arg.equals("-emacs") || arg.equals("-e")) { 407 emacsMode = true; 408 } else if (arg.equals("-projecthelp") || arg.equals("-p")) { 409 projectHelp = true; 411 } else if (arg.equals("-find") || arg.equals("-s")) { 412 if (i < args.length - 1) { 414 searchForThis = args[++i]; 415 } else { 416 searchForThis = DEFAULT_BUILD_FILENAME; 417 } 418 } else if (arg.startsWith("-propertyfile")) { 419 try { 420 propertyFiles.addElement(args[i + 1]); 421 i++; 422 } catch (ArrayIndexOutOfBoundsException aioobe) { 423 String msg = "You must specify a property filename when " 424 + "using the -propertyfile argument"; 425 throw new BuildException(msg); 426 } 427 } else if (arg.equals("-k") || arg.equals("-keep-going")) { 428 keepGoingMode = true; 429 } else if (arg.equals("-nice")) { 430 try { 431 threadPriority = Integer.decode(args[i + 1]); 432 } catch (ArrayIndexOutOfBoundsException aioobe) { 433 throw new BuildException( 434 "You must supply a niceness value (1-10)" 435 + " after the -nice option"); 436 } catch (NumberFormatException e) { 437 throw new BuildException("Unrecognized niceness value: " 438 + args[i + 1]); 439 } 440 i++; 441 if (threadPriority.intValue() < Thread.MIN_PRIORITY 442 || threadPriority.intValue() > Thread.MAX_PRIORITY) { 443 throw new BuildException( 444 "Niceness value is out of the range 1-10"); 445 } 446 } else if (launchCommands.get(arg) != null) { 447 String msg = "Ant's Main method is being handed " 451 + "an option " + arg + " that is only for the launcher class." 452 + "\nThis can be caused by a version mismatch between " 453 + "the ant script/.bat file and Ant itself."; 454 throw new BuildException(msg); 455 } else if (arg.equals("-autoproxy")) { 456 proxy = false; 457 } else if (arg.startsWith("-")) { 458 String msg = "Unknown argument: " + arg; 460 System.err.println(msg); 461 printUsage(); 462 throw new BuildException(""); 463 } else { 464 targets.addElement(arg); 466 } 467 } 468 469 if (buildFile == null) { 471 if (searchForThis != null) { 473 buildFile = findBuildFile(System.getProperty("user.dir"), 474 searchForThis); 475 } else { 476 buildFile = new File (DEFAULT_BUILD_FILENAME); 477 } 478 } 479 480 if (!buildFile.exists()) { 482 System.out.println("Buildfile: " + buildFile + " does not exist!"); 483 throw new BuildException("Build failed"); 484 } 485 486 489 if (buildFile.isDirectory()) { 490 System.out.println("What? Buildfile: " + buildFile + " is a dir!"); 491 throw new BuildException("Build failed"); 492 } 493 494 for (int propertyFileIndex = 0; 496 propertyFileIndex < propertyFiles.size(); 497 propertyFileIndex++) { 498 String filename 499 = (String ) propertyFiles.elementAt(propertyFileIndex); 500 Properties props = new Properties (); 501 FileInputStream fis = null; 502 try { 503 fis = new FileInputStream (filename); 504 props.load(fis); 505 } catch (IOException e) { 506 System.out.println("Could not load property file " 507 + filename + ": " + e.getMessage()); 508 } finally { 509 FileUtils.close(fis); 510 } 511 512 Enumeration propertyNames = props.propertyNames(); 514 while (propertyNames.hasMoreElements()) { 515 String name = (String ) propertyNames.nextElement(); 516 if (definedProps.getProperty(name) == null) { 517 definedProps.put(name, props.getProperty(name)); 518 } 519 } 520 } 521 522 if (msgOutputLevel >= Project.MSG_INFO) { 523 System.out.println("Buildfile: " + buildFile); 524 } 525 526 if (logTo != null) { 527 out = logTo; 528 err = logTo; 529 System.setOut(out); 530 System.setErr(err); 531 } 532 readyToRun = true; 533 } 534 535 544 private File getParentFile(File file) { 545 File parent = file.getParentFile(); 546 547 if (parent != null && msgOutputLevel >= Project.MSG_VERBOSE) { 548 System.out.println("Searching in " + parent.getAbsolutePath()); 549 } 550 551 return parent; 552 } 553 554 571 private File findBuildFile(String start, String suffix) 572 throws BuildException { 573 if (msgOutputLevel >= Project.MSG_INFO) { 574 System.out.println("Searching for " + suffix + " ..."); 575 } 576 577 File parent = new File (new File (start).getAbsolutePath()); 578 File file = new File (parent, suffix); 579 580 while (!file.exists()) { 582 parent = getParentFile(parent); 584 585 if (parent == null) { 588 throw new BuildException("Could not locate a build file!"); 589 } 590 591 file = new File (parent, suffix); 593 } 594 595 return file; 596 } 597 598 609 private void runBuild(ClassLoader coreLoader) throws BuildException { 610 611 if (!readyToRun) { 612 return; 613 } 614 615 final Project project = new Project(); 616 project.setCoreLoader(coreLoader); 617 618 Throwable error = null; 619 620 try { 621 addBuildListeners(project); 622 addInputHandler(project); 623 624 PrintStream savedErr = System.err; 625 PrintStream savedOut = System.out; 626 InputStream savedIn = System.in; 627 628 SecurityManager oldsm = null; 630 oldsm = System.getSecurityManager(); 631 632 try { 637 if (allowInput) { 638 project.setDefaultInputStream(System.in); 639 } 640 System.setIn(new DemuxInputStream(project)); 641 System.setOut(new PrintStream (new DemuxOutputStream(project, false))); 642 System.setErr(new PrintStream (new DemuxOutputStream(project, true))); 643 644 645 if (!projectHelp) { 646 project.fireBuildStarted(); 647 } 648 649 if (threadPriority != null) { 651 try { 652 project.log("Setting Ant's thread priority to " 653 + threadPriority, Project.MSG_VERBOSE); 654 Thread.currentThread().setPriority(threadPriority.intValue()); 655 } catch (SecurityException swallowed) { 656 project.log("A security manager refused to set the -nice value"); 658 } 659 } 660 661 662 663 project.init(); 664 665 Enumeration e = definedProps.keys(); 667 while (e.hasMoreElements()) { 668 String arg = (String ) e.nextElement(); 669 String value = (String ) definedProps.get(arg); 670 project.setUserProperty(arg, value); 671 } 672 673 project.setUserProperty(MagicNames.ANT_FILE, 674 buildFile.getAbsolutePath()); 675 676 project.setKeepGoingMode(keepGoingMode); 677 if (proxy) { 678 ProxySetup proxySetup = new ProxySetup(project); 680 proxySetup.enableProxies(); 681 } 682 683 ProjectHelper.configureProject(project, buildFile); 684 685 if (projectHelp) { 686 printDescription(project); 687 printTargets(project, msgOutputLevel > Project.MSG_INFO); 688 return; 689 } 690 691 if (targets.size() == 0) { 693 if (project.getDefaultTarget() != null) { 694 targets.addElement(project.getDefaultTarget()); 695 } 696 } 697 698 project.executeTargets(targets); 699 } finally { 700 if (oldsm != null) { 703 System.setSecurityManager(oldsm); 704 } 705 706 System.setOut(savedOut); 707 System.setErr(savedErr); 708 System.setIn(savedIn); 709 } 710 } catch (RuntimeException exc) { 711 error = exc; 712 throw exc; 713 } catch (Error e) { 714 error = e; 715 throw e; 716 } finally { 717 if (!projectHelp) { 718 project.fireBuildFinished(error); 719 } else if (error != null) { 720 project.log(error.toString(), Project.MSG_ERR); 721 } 722 } 723 } 724 725 732 protected void addBuildListeners(Project project) { 733 734 project.addBuildListener(createLogger()); 736 737 for (int i = 0; i < listeners.size(); i++) { 738 String className = (String ) listeners.elementAt(i); 739 BuildListener listener = 740 (BuildListener) ClasspathUtils.newInstance(className, 741 Main.class.getClassLoader(), BuildListener.class); 742 if (project != null) { 743 project.setProjectReference(listener); 744 } 745 project.addBuildListener(listener); 746 } 747 } 748 749 757 private void addInputHandler(Project project) throws BuildException { 758 InputHandler handler = null; 759 if (inputHandlerClassname == null) { 760 handler = new DefaultInputHandler(); 761 } else { 762 handler = (InputHandler) ClasspathUtils.newInstance( 763 inputHandlerClassname, Main.class.getClassLoader(), 764 InputHandler.class); 765 if (project != null) { 766 project.setProjectReference(handler); 767 } 768 } 769 project.setInputHandler(handler); 770 } 771 772 782 private BuildLogger createLogger() { 783 BuildLogger logger = null; 784 if (loggerClassname != null) { 785 try { 786 logger = (BuildLogger) ClasspathUtils.newInstance( 787 loggerClassname, Main.class.getClassLoader(), 788 BuildLogger.class); 789 } catch (BuildException e) { 790 System.err.println("The specified logger class " 791 + loggerClassname 792 + " could not be used because " + e.getMessage()); 793 throw new RuntimeException (); 794 } 795 } else { 796 logger = new DefaultLogger(); 797 } 798 799 logger.setMessageOutputLevel(msgOutputLevel); 800 logger.setOutputPrintStream(out); 801 logger.setErrorPrintStream(err); 802 logger.setEmacsMode(emacsMode); 803 804 return logger; 805 } 806 807 810 private static void printUsage() { 811 String lSep = System.getProperty("line.separator"); 812 StringBuffer msg = new StringBuffer (); 813 msg.append("ant [options] [target [target2 [target3] ...]]" + lSep); 814 msg.append("Options: " + lSep); 815 msg.append(" -help, -h print this message" + lSep); 816 msg.append(" -projecthelp, -p print project help information" + lSep); 817 msg.append(" -version print the version information and exit" + lSep); 818 msg.append(" -diagnostics print information that might be helpful to" + lSep); 819 msg.append(" diagnose or report problems." + lSep); 820 msg.append(" -quiet, -q be extra quiet" + lSep); 821 msg.append(" -verbose, -v be extra verbose" + lSep); 822 msg.append(" -debug, -d print debugging information" + lSep); 823 msg.append(" -emacs, -e produce logging information without adornments" 824 + lSep); 825 msg.append(" -lib <path> specifies a path to search for jars and classes" 826 + lSep); 827 msg.append(" -logfile <file> use given file for log" + lSep); 828 msg.append(" -l <file> ''" + lSep); 829 msg.append(" -logger <classname> the class which is to perform logging" + lSep); 830 msg.append(" -listener <classname> add an instance of class as a project listener" 831 + lSep); 832 msg.append(" -noinput do not allow interactive input" + lSep); 833 msg.append(" -buildfile <file> use given buildfile" + lSep); 834 msg.append(" -file <file> ''" + lSep); 835 msg.append(" -f <file> ''" + lSep); 836 msg.append(" -D<property>=<value> use value for given property" + lSep); 837 msg.append(" -keep-going, -k execute all targets that do not depend" + lSep); 838 msg.append(" on failed target(s)" + lSep); 839 msg.append(" -propertyfile <name> load all properties from file with -D" + lSep); 840 msg.append(" properties taking precedence" + lSep); 841 msg.append(" -inputhandler <class> the class which will handle input requests" + lSep); 842 msg.append(" -find <file> (s)earch for buildfile towards the root of" + lSep); 843 msg.append(" -s <file> the filesystem and use it" + lSep); 844 msg.append(" -nice number A niceness value for the main thread:" + lSep 845 + " 1 (lowest) to 10 (highest); 5 is the default" 846 + lSep); 847 msg.append(" -nouserlib Run ant without using the jar files from" + lSep 848 + " ${user.home}/.ant/lib" + lSep); 849 msg.append(" -noclasspath Run ant without using CLASSPATH" + lSep); 850 msg.append(" -autoproxy Java1.5+: use the OS proxy settings" 851 + lSep); 852 msg.append(" -main <class> override Ant's normal entry point"); 853 System.out.println(msg.toString()); 854 } 855 856 861 private static void printVersion() throws BuildException { 862 System.out.println(getAntVersion()); 863 } 864 865 868 private static String antVersion = null; 869 870 880 public static synchronized String getAntVersion() throws BuildException { 881 if (antVersion == null) { 882 try { 883 Properties props = new Properties (); 884 InputStream in = 885 Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); 886 props.load(in); 887 in.close(); 888 889 StringBuffer msg = new StringBuffer (); 890 msg.append("Apache Ant version "); 891 msg.append(props.getProperty("VERSION")); 892 msg.append(" compiled on "); 893 msg.append(props.getProperty("DATE")); 894 antVersion = msg.toString(); 895 } catch (IOException ioe) { 896 throw new BuildException("Could not load the version information:" 897 + ioe.getMessage()); 898 } catch (NullPointerException npe) { 899 throw new BuildException("Could not load the version information."); 900 } 901 } 902 return antVersion; 903 } 904 905 912 private static void printDescription(Project project) { 913 if (project.getDescription() != null) { 914 project.log(project.getDescription()); 915 } 916 } 917 918 927 private static void printTargets(Project project, boolean printSubTargets) { 928 int maxLength = 0; 930 Enumeration ptargets = project.getTargets().elements(); 931 String targetName; 932 String targetDescription; 933 Target currentTarget; 934 Vector topNames = new Vector (); 937 Vector topDescriptions = new Vector (); 938 Vector subNames = new Vector (); 939 940 while (ptargets.hasMoreElements()) { 941 currentTarget = (Target) ptargets.nextElement(); 942 targetName = currentTarget.getName(); 943 if (targetName.equals("")) { 944 continue; 945 } 946 targetDescription = currentTarget.getDescription(); 947 if (targetDescription == null) { 949 int pos = findTargetPosition(subNames, targetName); 950 subNames.insertElementAt(targetName, pos); 951 } else { 952 int pos = findTargetPosition(topNames, targetName); 953 topNames.insertElementAt(targetName, pos); 954 topDescriptions.insertElementAt(targetDescription, pos); 955 if (targetName.length() > maxLength) { 956 maxLength = targetName.length(); 957 } 958 } 959 } 960 961 printTargets(project, topNames, topDescriptions, "Main targets:", 962 maxLength); 963 if (topNames.size() == 0) { 966 printSubTargets = true; 967 } 968 if (printSubTargets) { 969 printTargets(project, subNames, null, "Other targets:", 0); 970 } 971 972 String defaultTarget = project.getDefaultTarget(); 973 if (defaultTarget != null && !"".equals(defaultTarget)) { 974 project.log("Default target: " + defaultTarget); 976 } 977 } 978 979 989 private static int findTargetPosition(Vector names, String name) { 990 int res = names.size(); 991 for (int i = 0; i < names.size() && res == names.size(); i++) { 992 if (name.compareTo((String ) names.elementAt(i)) < 0) { 993 res = i; 994 } 995 } 996 return res; 997 } 998 999 1019 private static void printTargets(Project project, Vector names, 1020 Vector descriptions, String heading, 1021 int maxlen) { 1022 String lSep = System.getProperty("line.separator"); 1024 String spaces = " "; 1026 while (spaces.length() <= maxlen) { 1027 spaces += spaces; 1028 } 1029 StringBuffer msg = new StringBuffer (); 1030 msg.append(heading + lSep + lSep); 1031 for (int i = 0; i < names.size(); i++) { 1032 msg.append(" "); 1033 msg.append(names.elementAt(i)); 1034 if (descriptions != null) { 1035 msg.append( 1036 spaces.substring(0, maxlen - ((String ) names.elementAt(i)).length() + 2)); 1037 msg.append(descriptions.elementAt(i)); 1038 } 1039 msg.append(lSep); 1040 } 1041 project.log(msg.toString(), Project.MSG_WARN); 1042 } 1043} 1044 | Popular Tags |