From 8edaa455e6de687be40590a6a74f166098e20340 Mon Sep 17 00:00:00 2001 From: Magesh Umasankar Date: Mon, 8 Apr 2002 17:45:41 +0000 Subject: [PATCH] Close PrintStreams if logfile is being used. Leaving the streams open causes test case failures on Windows. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272300 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 3 + src/main/org/apache/tools/ant/Main.java | 158 ++++++++++-------- .../org/apache/tools/ant/taskdefs/Ant.java | 60 ++++--- 3 files changed, 129 insertions(+), 92 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index 512c8114a..26c91161a 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -52,6 +52,9 @@ Changes that could break older environments: Fixed bugs: ----------- +* A bug existed that prevented generated log files from being deleted as + part of the build process itself. This has now been fixed. + * Fixed bug where ignored s. * Ant works properly with the combination of Java1.4/WindowsXP. diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java index 8aefc771b..92e2594c5 100644 --- a/src/main/org/apache/tools/ant/Main.java +++ b/src/main/org/apache/tools/ant/Main.java @@ -88,10 +88,10 @@ public class Main { private File buildFile; /* null */ /** Stream to use for logging. */ - private PrintStream out = System.out; + private static PrintStream out = System.out; /** Stream that we are using for logging error messages. */ - private PrintStream err = System.err; + private static PrintStream err = System.err; /** The build targets. */ private Vector targets = new Vector(5); @@ -101,13 +101,13 @@ public class Main { /** Names of classes to add as listeners to project. */ private Vector listeners = new Vector(5); - + /** File names of property files to load on startup. */ private Vector propertyFiles = new Vector(5); - + /** - * The Ant logger class. There may be only one logger. It will have - * the right to use the 'out' PrintStream. The class must implements the + * The Ant logger class. There may be only one logger. It will have + * the right to use the 'out' PrintStream. The class must implements the * BuildLogger interface. */ private String loggerClassname = null; @@ -124,15 +124,21 @@ public class Main { private boolean readyToRun = false; /** - * Whether or not we should only parse and display the project help + * Whether or not we should only parse and display the project help * information. */ private boolean projectHelp = false; /** - * Prints the message of the Throwable if it (the message) is not + * Is a logfile being used? This is used to + * check if the output streams must be closed. + */ + private static boolean isLogFileUsed = false; + + /** + * Prints the message of the Throwable if it (the message) is not * null. - * + * * @param t Throwable to print the message of. * Must not be null. */ @@ -147,12 +153,12 @@ public class Main { * Creates a new instance of this class using the * arguments specified, gives it any extra user properties which have been * specified, and then runs the build using the classloader provided. - * + * * @param args Command line arguments. Must not be null. - * @param additionalUserProperties Any extra properties to use in this - * build. May be null, which is the equivalent to + * @param additionalUserProperties Any extra properties to use in this + * build. May be null, which is the equivalent to * passing in an empty set of properties. - * @param coreLoader Classloader used for core classes. May be + * @param coreLoader Classloader used for core classes. May be * null in which case the system classloader is used. */ public static void start(String[] args, Properties additionalUserProperties, @@ -167,14 +173,14 @@ public class Main { } if (additionalUserProperties != null) { - for (Enumeration e = additionalUserProperties.keys(); + for (Enumeration e = additionalUserProperties.keys(); e.hasMoreElements(); ) { String key = (String) e.nextElement(); String property = additionalUserProperties.getProperty(key); m.definedProps.put(key, property); } } - + try { m.runBuild(coreLoader); System.exit(0); @@ -187,9 +193,26 @@ public class Main { exc.printStackTrace(); printMessage(exc); System.exit(1); + } finally { + if (isLogFileUsed) { + if (out != null) { + try { + out.close(); + } catch (final Exception e) { + //ignore + } + } + if (err != null) { + try { + err.close(); + } catch (final Exception e) { + //ignore + } + } + } } } - + /** * Command line entry point. This method kicks off the building * of a project object and executes a build using either a given @@ -206,11 +229,11 @@ public class Main { // BuildException is thrown. What's the rationale for when to do // what? /** - * Sole constructor, which parses and deals with command line + * Sole constructor, which parses and deals with command line * arguments. - * + * * @param args Command line arguments. Must not be null. - * + * * @exception BuildException if the specified build file doesn't exist * or is a directory. */ @@ -245,9 +268,10 @@ public class Main { err = out; System.setOut(out); System.setErr(out); + isLogFileUsed = true; } catch (IOException ioe) { - String msg = "Cannot write on the specified log file. " - + "Make sure the path exists and you have write " + String msg = "Cannot write on the specified log file. " + + "Make sure the path exists and you have write " + "permissions."; System.out.println(msg); return; @@ -257,7 +281,7 @@ public class Main { System.out.println(msg); return; } - } else if (arg.equals("-buildfile") || arg.equals("-file") + } else if (arg.equals("-buildfile") || arg.equals("-file") || arg.equals("-f")) { try { buildFile = new File(args[i + 1]); @@ -304,13 +328,13 @@ public class Main { definedProps.put(name, value); } else if (arg.equals("-logger")) { if (loggerClassname != null) { - System.out.println("Only one logger class may " + System.out.println("Only one logger class may " + " be specified."); return; } try { loggerClassname = args[++i]; - } + } catch (ArrayIndexOutOfBoundsException aioobe) { System.out.println("You must specify a classname when " + "using the -logger argument"); @@ -349,12 +373,12 @@ public class Main { targets.addElement(arg); } } - + // if buildFile was not specified on the command line, if (buildFile == null) { // but -find then search for it if (searchForThis != null) { - buildFile = findBuildFile(System.getProperty("user.dir"), + buildFile = findBuildFile(System.getProperty("user.dir"), searchForThis); } else { buildFile = new File(DEFAULT_BUILD_FILENAME); @@ -379,7 +403,7 @@ public class Main { for (int propertyFileIndex = 0; propertyFileIndex < propertyFiles.size(); propertyFileIndex++) { - String filename + String filename = (String) propertyFiles.elementAt(propertyFileIndex); Properties props = new Properties(); FileInputStream fis = null; @@ -398,7 +422,7 @@ public class Main { } } } - + // ensure that -D properties take precedence Enumeration propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { @@ -444,12 +468,12 @@ public class Main { * Must not be null. * @param suffix Suffix filename to look for in parents. * Must not be null. - * + * * @return A handle to the build file if one is found * * @exception BuildException if no build file is found */ - private File findBuildFile(String start, String suffix) + private File findBuildFile(String start, String suffix) throws BuildException { if (msgOutputLevel >= Project.MSG_INFO) { System.out.println("Searching for " + suffix + " ..."); @@ -457,22 +481,22 @@ public class Main { File parent = new File(new File(start).getAbsolutePath()); File file = new File(parent, suffix); - + // check if the target file exists in the current directory while (!file.exists()) { // change to parent directory parent = getParentFile(parent); - + // if parent is null, then we are at the root of the fs, // complain that we can't find the build file. if (parent == null) { throw new BuildException("Could not locate a build file!"); } - + // refresh our file handle file = new File(parent, suffix); } - + return file; } @@ -480,11 +504,11 @@ public class Main { * Executes the build. If the constructor for this instance failed * (e.g. returned after issuing a warning), this method returns * immediately. - * + * * @param coreLoader The classloader to use to find core classes. * May be null, in which case the * system classloader is used. - * + * * @exception BuildException if the build fails */ private void runBuild(ClassLoader coreLoader) throws BuildException { @@ -517,7 +541,7 @@ public class Main { !Project.JAVA_1_1.equals(Project.getJavaVersion()) ){ oldsm = System.getSecurityManager(); - //SecurityManager can not be installed here for backwards + //SecurityManager can not be installed here for backwards //compatability reasons (PD). Needs to be loaded prior to //ant class if we are going to implement it. //System.setSecurityManager(new NoExitSecurityManager()); @@ -539,14 +563,14 @@ public class Main { String value = (String)definedProps.get(arg); project.setUserProperty(arg, value); } - - project.setUserProperty("ant.file", + + project.setUserProperty("ant.file", buildFile.getAbsolutePath() ); - + // first use the ProjectHelper to create the project object // from the given build file. String noParserMessage = "No JAXP compliant XML parser found. " - + "Please visit http://xml.apache.org " + + "Please visit http://xml.apache.org " + "for a suitable parser"; try { Class.forName("javax.xml.parsers.SAXParserFactory"); @@ -564,12 +588,12 @@ public class Main { printTargets(project, msgOutputLevel > Project.MSG_INFO ); return; } - + // make sure that we have a target to execute if (targets.size() == 0) { targets.addElement(project.getDefaultTarget()); } - + project.executeTargets(targets); } finally { @@ -601,7 +625,7 @@ public class Main { /** * Adds the listeners specified in the command line arguments, * along with the default listener, to the specified project. - * + * * @param project The project to add listeners to. * Must not be null. */ @@ -618,18 +642,18 @@ public class Main { project.addBuildListener(listener); } catch (Throwable exc) { - throw new BuildException("Unable to instantiate listener " + throw new BuildException("Unable to instantiate listener " + className, exc); } } } - // XXX: (Jon Skeet) Any reason for writing a message and then using a bare + // XXX: (Jon Skeet) Any reason for writing a message and then using a bare // RuntimeException rather than just using a BuildException here? Is it - // in case the message could end up being written to no loggers (as the + // in case the message could end up being written to no loggers (as the // loggers could have failed to be created due to this failure)? /** - * Creates the default build logger for sending build events to the ant + * Creates the default build logger for sending build events to the ant * log. * * @return the logger instance for this build. @@ -641,13 +665,13 @@ public class Main { logger = (BuildLogger)(Class.forName(loggerClassname).newInstance()); } catch (ClassCastException e) { - System.err.println("The specified logger class " - + loggerClassname + System.err.println("The specified logger class " + + loggerClassname + " does not implement the BuildLogger interface"); throw new RuntimeException(); } catch (Exception e) { - System.err.println("Unable to instantiate specified logger " + System.err.println("Unable to instantiate specified logger " + "class " + loggerClassname + " : " + e.getClass().getName()); throw new RuntimeException(); } @@ -693,7 +717,7 @@ public class Main { /** * Prints the Ant version information to System.out. - * + * * @exception BuildException if the version information is unavailable */ private static void printVersion() throws BuildException { @@ -709,10 +733,10 @@ public class Main { * Returns the Ant version information, if available. Once the information * has been loaded once, it's cached and returned from the cache on future * calls. - * - * @return the Ant version information as a String + * + * @return the Ant version information as a String * (always non-null) - * + * * @exception BuildException if the version information is unavailable */ public static synchronized String getAntVersion() throws BuildException { @@ -723,7 +747,7 @@ public class Main { Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); props.load(in); in.close(); - + String lSep = System.getProperty("line.separator"); StringBuffer msg = new StringBuffer(); msg.append("Apache Ant version "); @@ -742,9 +766,9 @@ public class Main { } /** - * Prints the description of a project (if there is one) to + * Prints the description of a project (if there is one) to * System.out. - * + * * @param project The project to display a description of. * Must not be null. */ @@ -755,9 +779,9 @@ public class Main { } /** - * Prints a list of all targets in the specified project to + * Prints a list of all targets in the specified project to * System.out, optionally including subtargets. - * + * * @param project The project to display a description of. * Must not be null. * @param printSubTargets Whether or not subtarget names should also be @@ -795,13 +819,13 @@ public class Main { } printTargets(topNames, topDescriptions, "Main targets:", maxLength); - + if (printSubTargets) { printTargets(subNames, null, "Subtargets:", 0); } String defaultTarget = project.getDefaultTarget(); - if (defaultTarget != null && !"".equals(defaultTarget)) { + if (defaultTarget != null && !"".equals(defaultTarget)) { // shouldn't need to check but... System.out.println( "Default target: " + defaultTarget); } @@ -810,11 +834,11 @@ public class Main { /** * Searches for the correct place to insert a name into a list so as * to keep the list sorted alphabetically. - * + * * @param names The current list of names. Must not be null. * @param name The name to find a place for. * Must not be null. - * + * * @return the correct place in the list for the given name */ private static int findTargetPosition(Vector names, String name) { @@ -835,17 +859,17 @@ public class Main { * Must not be null. * @param descriptions The associated target descriptions. * May be null, in which case - * no descriptions are displayed. + * no descriptions are displayed. * If non-null, this should have * as many elements as names. - * @param heading The heading to display. + * @param heading The heading to display. * Should not be null. * @param maxlen The maximum length of the names of the targets. * If descriptions are given, they are padded to this * position so they line up (so long as the names really * are shorter than this). */ - private static void printTargets(Vector names, Vector descriptions, + private static void printTargets(Vector names, Vector descriptions, String heading, int maxlen) { // now, start printing the targets and their descriptions String lSep = System.getProperty("line.separator"); diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java index 748f57105..372d16d9c 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Ant.java +++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java @@ -96,31 +96,34 @@ public class Ant extends Task { /** the basedir where is executed the build file */ private File dir = null; - + /** the build.xml file (can be absolute) in this case dir will be ignored */ private String antFile = null; - + /** the target to call if any */ private String target = null; - + /** the output */ private String output = null; - + /** should we inherit properties from the parent ? */ private boolean inheritAll = true; - + /** should we inherit references from the parent ? */ private boolean inheritRefs = false; - + /** the properties to pass to the new project */ private Vector properties = new Vector(); - + /** the references to pass to the new project */ private Vector references = new Vector(); /** the temporary project created to run the build file */ private Project newProject; + /** The stream to which output is to be written. */ + private PrintStream out = null; + /** * If true, inherit all properties from parent Project * If false, inherit only userProperties and those defined @@ -142,7 +145,7 @@ public class Ant extends Task { public void init() { newProject = new Project(); newProject.setJavaVersionProperty(); - newProject.addTaskDefinition("property", + newProject.addTaskDefinition("property", (Class)project.getTaskDefinitions().get("property")); } @@ -158,7 +161,7 @@ public class Ant extends Task { } if (p.getFile() != null) { newP.setFile(p.getFile()); - } + } if (p.getResource() != null) { newP.setResource(p.getResource()); } @@ -181,7 +184,7 @@ public class Ant extends Task { outfile = getProject().resolveFile(output); } try { - PrintStream out = new PrintStream(new FileOutputStream(outfile)); + out = new PrintStream(new FileOutputStream(outfile)); DefaultLogger logger = new DefaultLogger(); logger.setMessageOutputLevel(Project.MSG_INFO); logger.setOutputPrintStream(out); @@ -224,7 +227,7 @@ public class Ant extends Task { // b/c we won't inherit them. newProject.setSystemProperties(); } - + e = prop1.keys(); while (e.hasMoreElements()) { String arg = (String) e.nextElement(); @@ -232,7 +235,7 @@ public class Ant extends Task { // basedir and ant.file get special treatment in execute() continue; } - + String value = (String) prop1.get(arg); if (inheritAll){ newProject.setProperty(arg, value); @@ -249,7 +252,7 @@ public class Ant extends Task { super.handleOutput(line); } } - + protected void handleErrorOutput(String line) { if (newProject != null) { newProject.demuxOutput(line, true); @@ -257,7 +260,7 @@ public class Ant extends Task { super.handleErrorOutput(line); } } - + /** * Do the execution. */ @@ -266,7 +269,7 @@ public class Ant extends Task { if (newProject == null) { reinit(); } - + if ( (dir == null) && (inheritAll) ) { dir = project.getBaseDir(); } @@ -289,13 +292,13 @@ public class Ant extends Task { File file = FileUtils.newFileUtils().resolveFile(dir, antFile); antFile = file.getAbsolutePath(); - + log("calling target "+(target!=null?target:"[default]") + " in build file "+ antFile.toString(), Project.MSG_VERBOSE); newProject.setUserProperty( "ant.file" , antFile ); ProjectHelper.configureProject(newProject, new File(antFile)); - + if (target == null) { target = newProject.getDefaultTarget(); } @@ -306,7 +309,7 @@ public class Ant extends Task { if (newProject.getBaseDir().equals(project.getBaseDir()) && newProject.getProperty("ant.file").equals(project.getProperty("ant.file")) && getOwningTarget() != null && - target.equals(this.getOwningTarget().getName())) { + target.equals(this.getOwningTarget().getName())) { throw new BuildException("ant task calling its own parent target"); } @@ -315,6 +318,13 @@ public class Ant extends Task { } finally { // help the gc newProject = null; + if (output != null && out != null) { + try { + out.close(); + } catch (final Exception e) { + //ignore + } + } } } @@ -350,7 +360,7 @@ public class Ant extends Task { } if (!thisReferences.containsKey(refid)) { log("Parent project doesn't contain any reference '" - + refid + "'", + + refid + "'", Project.MSG_WARN); continue; } @@ -397,13 +407,13 @@ public class Ant extends Task { } catch (Exception e) { // not Clonable } - + if (copy instanceof ProjectComponent) { ((ProjectComponent) copy).setProject(newProject); } else { try { - Method setProjectM = + Method setProjectM = c.getMethod( "setProject", new Class[] {Project.class}); if(setProjectM != null) { setProjectM.invoke(copy, new Object[] {newProject}); @@ -413,7 +423,7 @@ public class Ant extends Task { // a set project method. } catch(Exception e2) { String msg = "Error setting new project instance for reference with id " - + oldKey; + + oldKey; throw new BuildException(msg, e2, location); } } @@ -463,7 +473,7 @@ public class Ant extends Task { return p; } - /** + /** * create a reference element that identifies a data type that * should be carried over to the new project. */ @@ -475,11 +485,11 @@ public class Ant extends Task { * Helper class that implements the nested <reference> * element of <ant> and <antcall>. */ - public static class Reference + public static class Reference extends org.apache.tools.ant.types.Reference { public Reference() {super();} - + private String targetid=null; public void setToRefid(String targetid) { this.targetid=targetid; } public String getToRefid() { return targetid; }