diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index 7fdcc17cc..564051d5b 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -70,13 +70,14 @@ import org.apache.tools.ant.types.FilterSetCollection; import org.apache.tools.ant.util.FileUtils; /** - * Central representation of an Ant project. This class defines a - * Ant project with all of it's targets and tasks. It also provides - * the mechanism to kick off a build using a particular target name. + * Central representation of an Ant project. This class defines an + * Ant project with all of its targets, tasks and various other + * properties. It also provides the mechanism to kick off a build using + * a particular target name. *

- * This class also encapsulates methods which allow Files to be refered + * This class also encapsulates methods which allow files to be referred * to using abstract path names which are translated to native system - * file paths at runtime as well as defining various project properties. + * file paths at runtime. * * @author duncan@x180.com * @@ -85,54 +86,105 @@ import org.apache.tools.ant.util.FileUtils; public class Project { + /** Message priority of "error". */ public final static int MSG_ERR = 0; + /** Message priority of "warning". */ public final static int MSG_WARN = 1; + /** Message priority of "information". */ public final static int MSG_INFO = 2; + /** Message priority of "verbose". */ public final static int MSG_VERBOSE = 3; + /** Message priority of "debug". */ public final static int MSG_DEBUG = 4; - // private set of constants to represent the state - // of a DFS of the Target dependencies + /** + * Constant for the "visiting" state, used when + * traversing a DFS of target dependencies. + */ private final static String VISITING = "VISITING"; + /** + * Constant for the "visited" state, used when + * traversing a DFS of target dependencies. + */ private final static String VISITED = "VISITED"; + /** Version of currently running VM. */ private static String javaVersion; + /** Version constant for Java 1.0 */ public final static String JAVA_1_0 = "1.0"; + /** Version constant for Java 1.1 */ public final static String JAVA_1_1 = "1.1"; + /** Version constant for Java 1.2 */ public final static String JAVA_1_2 = "1.2"; + /** Version constant for Java 1.3 */ public final static String JAVA_1_3 = "1.3"; + /** Version constant for Java 1.4 */ public final static String JAVA_1_4 = "1.4"; + /** Default filter start token. */ public final static String TOKEN_START = FilterSet.DEFAULT_TOKEN_START; + /** Default filter end token. */ public final static String TOKEN_END = FilterSet.DEFAULT_TOKEN_END; + /** Name of this project. */ private String name; + /** Description for this project (if any). */ private String description; + /** Project properties map (String to String). */ private Hashtable properties = new Hashtable(); + /** + * Map of "user" properties (as created in the Ant task, for example). + * Note that these key/value pairs are also always put into the + * project properties, so only the project properties need to be queried. + * Mapping is String to String. + */ private Hashtable userProperties = new Hashtable(); + /** Map of references within the project (paths etc) (String to Object). */ private Hashtable references = new Hashtable(); + + /** Name of the project's default target. */ private String defaultTarget; + /** Map from data type names to implementing classes (String to Class). */ private Hashtable dataClassDefinitions = new Hashtable(); + /** Map from task names to implementing classes (String to Class). */ private Hashtable taskClassDefinitions = new Hashtable(); + /** + * Map from task names to vectors of created tasks + * (String to Vector of Task). This is used to invalidate tasks if + * the task definition changes. + */ private Hashtable createdTasks = new Hashtable(); + /** Map from target names to targets (String to Target). */ private Hashtable targets = new Hashtable(); + /** Set of global filters. */ private FilterSet globalFilterSet = new FilterSet(); + /** + * Wrapper around globalFilterSet. This collection only ever + * contains one FilterSet, but the wrapper is needed in order to + * make it easier to use the FileUtils interface. + */ private FilterSetCollection globalFilters = new FilterSetCollection(globalFilterSet); + /** Project base directory. */ private File baseDir; + /** List of listeners to notify of build events. */ private Vector listeners = new Vector(); - /** The Ant core classloader - may be null if using system loader */ + /** + * The Ant core classloader - may be null if using + * parent classloader. + */ private ClassLoader coreLoader = null; - /** Records the latest task on a thread */ + /** Records the latest task to be executed on a thread (Thread to Task). */ private Hashtable threadTasks = new Hashtable(); static { // Determine the Java version by looking at available classes + // java.lang.CharSequence was introduced in JDK 1.4 // java.lang.StrictMath was introduced in JDK 1.3 // java.lang.ThreadLocal was introduced in JDK 1.2 // java.lang.Void was introduced in JDK 1.1 @@ -154,20 +206,23 @@ public class Project { } } + /** Instance of a utility class to use for file operations. */ private FileUtils fileUtils; /** - * create a new ant project + * Creates a new Ant project. */ public Project() { fileUtils = FileUtils.newFileUtils(); } /** - * Initialise the project. + * Initialises the project. * * This involves setting the default task definitions and loading the * system properties. + * + * @exception BuildException if the default task list cannot be loaded */ public void init() throws BuildException { setJavaVersionProperty(); @@ -231,30 +286,65 @@ public class Project { setSystemProperties(); } + /** + * Sets the core classloader for the project. If a null + * classloader is specified, the parent classloader should be used. + * + * @param coreLoader The classloader to use for the project. + * May be null. + */ public void setCoreLoader(ClassLoader coreLoader) { this.coreLoader = coreLoader; } + /** + * Returns the core classloader to use for this project. + * This may be null, indicating that + * the parent classloader should be used. + * + * @return the core classloader to use for this project. + * + */ public ClassLoader getCoreLoader() { return coreLoader; } + /** + * Adds a build listener to the list. This listener will + * be notified of build events for this project. + * + * @param listener The listener to add to the list. + * Must not be null. + */ public void addBuildListener(BuildListener listener) { listeners.addElement(listener); } + /** + * Removes a build listener from the list. This listener + * will no longer be notified of build events for this project. + * + * @param listener The listener to remove from the list. + * Should not be null. + */ public void removeBuildListener(BuildListener listener) { listeners.removeElement(listener); } + /** + * Returns a list of build listeners for the project. The returned + * vector is "live" and so should not be modified. + * + * @return a list of build listeners for the project + */ public Vector getBuildListeners() { return listeners; } /** - * Output a message to the log with the default log level + * Writes a message to the log with the default log level * of MSG_INFO - * @param msg text to log + * @param msg The text to log. Should not be null. */ public void log(String msg) { @@ -262,47 +352,51 @@ public class Project { } /** - * Output a message to the log with the given log level - * and an event scope of project - * @param msg text to log - * @param msgLevel level to log at + * Writes a project level message to the log with the given log level. + * @param msg The text to log. Should not be null. + * @param msgLevel The priority level to log at. */ public void log(String msg, int msgLevel) { fireMessageLogged(this, msg, msgLevel); } /** - * Output a message to the log with the given log level - * and an event scope of a task - * @param task task to use in the log - * @param msg text to log - * @param msgLevel level to log at + * Writes a task level message to the log with the given log level. + * @param task The task to use in the log. Must not be null. + * @param msg The text to log. Should not be null. + * @param msgLevel The priority level to log at. */ public void log(Task task, String msg, int msgLevel) { fireMessageLogged(task, msg, msgLevel); } - + /** - * Output a message to the log with the given log level - * and an event scope of a target - * @param target target to use in the log - * @param msg text to log - * @param msgLevel level to log at + * Writes a target level message to the log with the given log level. + * @param target The target to use in the log. + * Must not be null. + * @param msg The text to log. Should not be null. + * @param msgLevel The priority level to log at. */ public void log(Target target, String msg, int msgLevel) { fireMessageLogged(target, msg, msgLevel); } - + /** + * Returns the set of global filters. + * + * @return the set of global filters + */ public FilterSet getGlobalFilterSet() { return globalFilterSet; } /** - * set a property. Any existing property of the same name + * Sets a property. Any existing property of the same name * is overwritten, unless it is a user property. - * @param name name of property - * @param value new value of the property + * @param name The name of property to set. + * Must not be null. + * @param value The new value of the property. + * Must not be null. */ public void setProperty(String name, String value) { // command line properties take precedence @@ -322,10 +416,14 @@ public class Project { } /** - * set a property. An existing property of the same name - * will not be overwritten. - * @param name name of property - * @param value new value of the property + * Sets a property if no value currently exists. If the property + * exists already, a message is logged and the method returns with + * no other effect. + * + * @param name The name of property to set. + * Must not be null. + * @param value The new value of the property. + * Must not be null. * @since 1.5 */ public void setNewProperty(String name, String value) { @@ -339,8 +437,12 @@ public class Project { } /** - * set a user property, which can not be overwritten by - * set/unset property calls + * Sets a user property, which cannot be overwritten by + * set/unset property calls. Any previous value is overwritten. + * @param name The name of property to set. + * Must not be null. + * @param value The new value of the property. + * Must not be null. * @see #setProperty(String,String) */ public void setUserProperty(String name, String value) { @@ -351,9 +453,8 @@ public class Project { } /** - * Allows Project and subclasses to set a property unless its - * already defined as a user property. There are a few cases - * internally to Project that need to do this currently. + * Sets a property unless it is already defined as a user property + * (in which case the method returns silently). */ private void setPropertyInternal(String name, String value) { if (null != userProperties.get(name)) { @@ -363,9 +464,13 @@ public class Project { } /** - * query a property. - * @param name the name of the property - * @return the property value, or null for no match + * Returns the value of a property, if it is set. + * + * @param name The name of the property. + * May be null, in which case + * the return value is also null. + * @return the property value, or null for no match + * or if a null name is provided. */ public String getProperty(String name) { if (name == null) { @@ -376,10 +481,18 @@ public class Project { } /** - * Replace ${} style constructions in the given value with the + * Replaces ${} style constructions in the given value with the * string value of the corresponding data types. * - * @param value the string to be scanned for property references. + * @param value The string to be scanned for property references. + * May be null. + * + * @return the given string with embedded property names replaced + * by values, or null if the given string is + * null. + * + * @exception BuildException if the given value has an unclosed property name, + * e.g. ${xxx */ public String replaceProperties(String value) throws BuildException { @@ -387,11 +500,15 @@ public class Project { } /** - * query a user property. - * @param name the name of the property - * @return the property value, or null for no match + * Returns the value of a user property, if it is set. + * + * @param name The name of the property. + * May be null, in which case + * the return value is also null. + * @return the property value, or null for no match + * or if a null name is provided. */ - public String getUserProperty(String name) { + public String getUserProperty(String name) { if (name == null) { return null; } @@ -400,8 +517,8 @@ public class Project { } /** - * get a copy of the property hashtable - * @return the hashtable containing all properties, user included + * Returns a copy of the properties table. + * @return a hashtable containing all properties (including user properties). */ public Hashtable getProperties() { Hashtable propertiesCopy = new Hashtable(); @@ -417,8 +534,8 @@ public class Project { } /** - * get a copy of the user property hashtable - * @return the hashtable user properties only + * Returns a copy of the user property hashtable + * @return a hashtable containing just the user properties */ public Hashtable getUserProperties() { Hashtable propertiesCopy = new Hashtable(); @@ -434,8 +551,13 @@ public class Project { } /** - * set the default target of the project - * @deprecated, use setDefault + * Sets the default target of the project. + * + * @param defaultTarget The name of the default target for this project. + * May be null, indicating that there is + * no default target. + * + * @deprecated use setDefault * @see #setDefault(String) */ public void setDefaultTarget(String defaultTarget) { @@ -443,82 +565,121 @@ public class Project { } /** - * get the default target of the project - * @return default target or null + * Returns the name of the default target of the project. + * @return name of the default target or + * null if no default has been set. */ public String getDefaultTarget() { return defaultTarget; } - /** - * set the default target of the project - * XML attribute name. + * Sets the default target of the project. + * + * @param defaultTarget The name of the default target for this project. + * May be null, indicating that there is + * no default target. */ public void setDefault(String defaultTarget) { this.defaultTarget = defaultTarget; } /** - * ant xml property. Set the project name as - * an attribute of this class, and of the property - * ant.project.name + * Sets the name of the project, also setting the user + * property ant.project.name. + * + * @param name The name of the project. + * Must not be null. */ public void setName(String name) { setUserProperty("ant.project.name", name); this.name = name; } - /** get the project name - * @return name string + /** + * Returns the project name, if one has been set. + * + * @return the project name, or null if it hasn't been set. */ public String getName() { return name; } - /** set the project description - * @param description text + /** + * Sets the project description. + * + * @param description The description of the project. + * May be null. */ public void setDescription(String description) { this.description = description; } - /** get the project description - * @return description or null if no description has been set + /** + * Returns the project description, if one has been set. + * + * @return the project description, or null if it hasn't + * been set. */ public String getDescription() { return description; } - /** @deprecated */ + /** + * Adds a filter to the set of global filters. + * + * @param token The token to filter. + * Must not be null. + * @deprecated Use getGlobalFilterSet().addFilter(token,value) + * + * @see #getGlobalFilterSet() + * @see FilterSet#addFilter(String,String) + */ public void addFilter(String token, String value) { if (token == null) { return; } - + globalFilterSet.addFilter(new FilterSet.Filter(token, value)); } - /** @deprecated */ + /** + * Returns a hashtable of global filters, mapping tokens to values. + * + * @return a hashtable of global filters, mapping tokens to values + * (String to String). + * + * @deprecated Use getGlobalFilterSet().getFilterHash() + * + * @see #getGlobalFilterSet() + * @see FilterSet#getFilterHash() + */ public Hashtable getFilters() { // we need to build the hashtable dynamically return globalFilterSet.getFilterHash(); } /** - * match basedir attribute in xml - * @param baseD project base directory. - * @throws BuildException if the directory was invalid + * Sets the base directory for the project, checking that + * the given filename exists and is a directory. + * + * @param baseD The project base directory. + * Must not be null. + * + * @exception BuildException if the directory if invalid */ public void setBasedir(String baseD) throws BuildException { setBaseDir(new File(baseD)); } /** - * set the base directory; XML attribute. - * checks for the directory existing and being a directory type - * @param baseDir project base directory. - * @throws BuildException if the directory was invalid + * Sets the base directory for the project, checking that + * the given file exists and is a directory. + * + * @param baseDir The project base directory. + * Must not be null. + * @exception BuildException if the specified file doesn't exist or + * isn't a directory */ public void setBaseDir(File baseDir) throws BuildException { baseDir = fileUtils.normalize(baseDir.getAbsolutePath()); @@ -535,9 +696,10 @@ public class Project { } /** - * get the base directory of the project as a file object - * @return the base directory. If this is null, then the base - * dir is not valid + * Returns the base directory of the project as a file object. + * + * @return the project base directory, or null if the + * base directory has not been successfully set to a valid value. */ public File getBaseDir() { if (baseDir == null) { @@ -551,17 +713,22 @@ public class Project { } /** - * static query of the java version - * @return something like "1.1" or "1.3" + * Returns the version of Java this class is running under. + * @return the version of Java as a String, e.g. "1.1" */ public static String getJavaVersion() { return javaVersion; } /** - * set the ant.java.version property, also tests for - * unsupported JVM versions, prints the verbose log messages - * @throws BuildException if this Java version is not supported + * Sets the ant.java.version property and tests for + * unsupported JVM versions. If the version is supported, + * verbose log messages are generated to record the Java version + * and operating system name. + * + * @exception BuildException if this Java version is not supported + * + * @see #getJavaVersion() */ public void setJavaVersionProperty() throws BuildException { setPropertyInternal("ant.java.version", javaVersion); @@ -577,8 +744,8 @@ public class Project { } /** - * turn all the system properties into ant properties. - * user properties still override these values + * Adds all system properties which aren't already defined as + * user properties to the project properties. */ public void setSystemProperties() { Properties systemP = System.getProperties(); @@ -591,11 +758,24 @@ public class Project { } /** - * add a new task definition, complain if there is an overwrite attempt - * @param taskName name of the task - * @param taskClass full task classname - * @throws BuildException and logs as Project.MSG_ERR for - * conditions, that will cause the task execution to fail. + * Adds a new task definition to the project. + * Attempting to override an existing definition with an + * equivalent one (i.e. with the same classname) results in + * a verbose log message. Attempting to override an existing definition + * with a different one results in a warning log message and + * invalidates any tasks which have already been created with the + * old definition. + * + * @param taskName The name of the task to add. + * Must not be null. + * @param taskClass The full name of the class implementing the task. + * Must not be null. + * + * @exception BuildException if the class is unsuitable for being an Ant + * task. An error level message is logged before + * this exception is thrown. + * + * @see #checkTaskClass(Class) */ public void addTaskDefinition(String taskName, Class taskClass) throws BuildException { Class old = (Class)taskClassDefinitions.get(taskName); @@ -619,9 +799,13 @@ public class Project { } /** - * Checks a class, whether it is suitable for serving as ant task. - * @throws BuildException and logs as Project.MSG_ERR for - * conditions, that will cause the task execution to fail. + * Checks whether or not a class is suitable for serving as Ant task. + * Ant task implementation classes must be public, concrete, and have + * a no-arg constructor. + * + * @exception BuildException if the class is unsuitable for being an Ant + * task. An error level message is logged before + * this exception is thrown. */ public void checkTaskClass(final Class taskClass) throws BuildException { if(!Modifier.isPublic(taskClass.getModifiers())) { @@ -639,7 +823,7 @@ public class Project { // don't have to check for public, since // getConstructor finds public constructors only. } catch(NoSuchMethodException e) { - final String message = "No public default constructor in " + taskClass; + final String message = "No public no-arg constructor in " + taskClass; log(message, Project.MSG_ERR); throw new BuildException(message); } @@ -649,16 +833,28 @@ public class Project { } /** - * get the current task definition hashtable + * Returns the current task definition hashtable. The returned hashtable is + * "live" and so should not be modified. + * + * @return a map of from task name to implementing class + * (String to Class). */ public Hashtable getTaskDefinitions() { return taskClassDefinitions; } /** - * add a new datatype - * @param typeName name of the datatype - * @param typeClass full datatype classname + * Adds a new datatype definition. + * Attempting to override an existing definition with an + * equivalent one (i.e. with the same classname) results in + * a verbose log message. Attempting to override an existing definition + * with a different one results in a warning log message, but the + * definition is changed. + * + * @param typeName The name of the datatype. + * Must not be null. + * @param taskClass The full name of the class implementing the datatype. + * Must not be null. */ public void addDataTypeDefinition(String typeName, Class typeClass) { Class old = (Class)dataClassDefinitions.get(typeName); @@ -680,19 +876,25 @@ public class Project { } /** - * get the current task definition hashtable + * Returns the current datatype definition hashtable. The returned hashtable is + * "live" and so should not be modified. + * + * @return a map of from datatype name to implementing class + * (String to Class). */ public Hashtable getDataTypeDefinitions() { return dataClassDefinitions; } /** - * This call expects to add a new Target. - * @param target is the Target to be added to the current - * Project. - * @exception BuildException if the Target already exists - * in the project. - * @see Project#addOrReplaceTarget to replace existing Targets. + * Adds a new target to the project. + * + * @param target The target to be added to the project. + * Must not be null. + * + * @exception BuildException if the target already exists in the project + * + * @see Project#addOrReplaceTarget */ public void addTarget(Target target) { String name = target.getName(); @@ -703,13 +905,16 @@ public class Project { } /** - * This call expects to add a new Target. - * @param target is the Target to be added to the current - * Project. - * @param targetName is the name to use for the Target - * @exception BuildException if the Target already exists - * in the project. - * @see Project#addOrReplaceTarget to replace existing Targets. + * Adds a new target to the project. + * + * @param targetName The name to use for the target. + * Must not be null. + * @param target The target to be added to the project. + * Must not be null. + * + * @exception BuildException if the target already exists in the project + * + * @see Project#addOrReplaceTarget */ public void addTarget(String targetName, Target target) throws BuildException { @@ -720,17 +925,24 @@ public class Project { } /** - * @param target is the Target to be added or replaced in - * the current Project. + * Adds a target to the project, or replaces one with the same + * name. + * + * @param target The target to be added or replaced in the project. + * Must not be null. */ public void addOrReplaceTarget(Target target) { addOrReplaceTarget(target.getName(), target); } /** - * @param target is the Target to be added/replaced in - * the current Project. - * @param targetName is the name to use for the Target + * Adds a target to the project, or replaces one with the same + * name. + * + * @param targetName The name to use for the target. + * Must not be null. + * @param target The target to be added or replaced in the project. + * Must not be null. */ public void addOrReplaceTarget(String targetName, Target target) { String msg = " +Target: " + targetName; @@ -740,18 +952,25 @@ public class Project { } /** - * get the target hashtable - * @return hashtable, the contents of which can be cast to Target + * Returns the hashtable of targets. The returned hashtable + * is "live" and so should not be modified. + * @return a map from name to target (String to Target). */ public Hashtable getTargets() { return targets; } /** - * create a new task instance - * @param taskType name of the task - * @throws BuildException when task creation goes bad - * @return null if the task name is unknown + * Creates a new instance of a task. + * + * @param taskType The name of the task to create an instance of. + * Must not be null. + * + * @return an instance of the specified task, or null if + * the task name is not recognised. + * + * @exception BuildException if the task name is recognised but task + * creation fails. */ public Task createTask(String taskType) throws BuildException { Class c = (Class) taskClassDefinitions.get(taskType); @@ -790,8 +1009,14 @@ public class Project { } /** - * Keep a record of all tasks that have been created so that they - * can be invalidated if a taskdef overrides the definition. + * Keeps a record of all tasks that have been created so that they + * can be invalidated if a new task definition overrides the current one. + * + * @param type The name of the type of task which has been created. + * Must not be null. + * + * @param task The freshly created task instance. + * Must not be null. */ private void addCreatedTask(String type, Task task) { synchronized (createdTasks) { @@ -807,6 +1032,9 @@ public class Project { /** * Mark tasks as invalid which no longer are of the correct type * for a given taskname. + * + * @param type The name of the type of task to invalidate. + * Must not be null. */ private void invalidateCreatedTasks(String type) { synchronized (createdTasks) { @@ -824,10 +1052,16 @@ public class Project { } /** - * create a new DataType instance - * @param typeName name of the datatype - * @throws BuildException when datatype creation goes bad - * @return null if the datatype name is unknown + * Creates a new instance of a data type. + * + * @param taskType The name of the data type to create an instance of. + * Must not be null. + * + * @return an instance of the specified data type, or null if + * the data type name is not recognised. + * + * @exception BuildException if the data type name is recognised but + * instance creation fails. */ public Object createDataType(String typeName) throws BuildException { Class c = (Class) dataClassDefinitions.get(typeName); @@ -874,9 +1108,13 @@ public class Project { } /** - * execute the sequence of targets, and the targets they depend on - * @param Vector a vector of target name strings - * @throws BuildException if the build failed + * Execute the specified sequence of targets, and the targets + * they depend on. + * + * @param targetNames A vector of target name strings to execute. + * Must not be null. + * + * @exception BuildException if the build failed */ public void executeTargets(Vector targetNames) throws BuildException { Throwable error = null; @@ -886,6 +1124,15 @@ public class Project { } } + /** + * Demultiplexes output so that each task receives the appropriate + * messages. If the current thread is not currently executing a task, + * the message is logged directly. + * + * @param line Message to handle. Should not be null. + * @param isError Whether the text represents an error (true) + * or information (false). + */ public void demuxOutput(String line, boolean isError) { Task task = (Task)threadTasks.get(Thread.currentThread()); if (task == null) { @@ -902,9 +1149,12 @@ public class Project { } /** - * execute the targets and any targets it depends on - * @param targetName the target to execute - * @throws BuildException if the build failed + * Executes the specified target and any targets it depends on. + * + * @param targetName The name of the target to execute. + * Must not be null. + * + * @exception BuildException if the build failed */ public void executeTarget(String targetName) throws BuildException { @@ -933,10 +1183,17 @@ public class Project { } /** - * Return the canonical form of fileName as an absolute path. + * Returns the canonical form of a filename. + *

+ * If the specified file name is relative it is resolved + * with respect to the given root directory. * - *

If fileName is a relative file name, resolve it relative to - * rootDir.

+ * @param fileName The name of the file to resolve. + * Must not be null. + * + * @param rootDir The directory to resolve relative file names with + * respect to. May be null, in which case + * the current directory is used. * * @deprecated */ @@ -944,30 +1201,42 @@ public class Project { return fileUtils.resolveFile(rootDir, fileName); } + /** + * Returns the canonical form of a filename. + *

+ * If the specified file name is relative it is resolved + * with respect to the project's base directory. + * + * @param fileName The name of the file to resolve. + * Must not be null. + */ public File resolveFile(String fileName) { return fileUtils.resolveFile(baseDir, fileName); } /** - * Translate a path into its native (platform specific) format. + * Translates a path into its native (platform specific) format. *

- * This method uses the PathTokenizer class to separate the input path + * This method uses PathTokenizer to separate the input path * into its components. This handles DOS style paths in a relatively * sensible way. The file separators are then converted to their platform * specific versions. * - * @param to_process the path to be converted + * @param toProcess The path to be translated. + * May be null. * - * @return the native version of to_process or - * an empty string if to_process is null or empty + * @return the native version of the specified path or + * an empty string if the path is null or empty. + * + * @see PathTokenizer */ - public static String translatePath(String to_process) { - if ( to_process == null || to_process.length() == 0 ) { + public static String translatePath(String toProcess) { + if ( toProcess == null || toProcess.length() == 0 ) { return ""; } - StringBuffer path = new StringBuffer(to_process.length() + 50); - PathTokenizer tokenizer = new PathTokenizer(to_process); + StringBuffer path = new StringBuffer(toProcess.length() + 50); + PathTokenizer tokenizer = new PathTokenizer(toProcess); while (tokenizer.hasMoreTokens()) { String pathComponent = tokenizer.nextToken(); pathComponent = pathComponent.replace('/', File.separatorChar); @@ -982,10 +1251,15 @@ public class Project { } /** - * Convienence method to copy a file from a source to a destination. + * Convenience method to copy a file from a source to a destination. * No filtering is performed. * - * @throws IOException + * @param sourceFile Name of file to copy from. + * Must not be null. + * @param destFile Name of file to copy to. + * Must not be null. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -994,10 +1268,17 @@ public class Project { } /** - * Convienence method to copy a file from a source to a destination - * specifying if token filtering must be used. + * Convenience method to copy a file from a source to a destination + * specifying if token filtering should be used. * - * @throws IOException + * @param sourceFile Name of file to copy from. + * Must not be null. + * @param destFile Name of file to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -1007,11 +1288,20 @@ public class Project { } /** - * Convienence method to copy a file from a source to a - * destination specifying if token filtering must be used and if + * Convenience method to copy a file from a source to a + * destination specifying if token filtering should be used and if * source files may overwrite newer destination files. * - * @throws IOException + * @param sourceFile Name of file to copy from. + * Must not be null. + * @param destFile Name of file to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. + * @param overwrite Whether or not the destination file should be + * overwritten if it already exists. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -1020,14 +1310,26 @@ public class Project { fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null, overwrite); } - /** - * Convienence method to copy a file from a source to a - * destination specifying if token filtering must be used, if - * source files may overwrite newer destination files and the - * last modified time of destFile file should be made equal - * to the last modified time of sourceFile. + /** + * Convenience method to copy a file from a source to a + * destination specifying if token filtering should be used, if + * source files may overwrite newer destination files, and if the + * last modified time of the resulting file should be set to + * that of the source file. * - * @throws IOException + * @param sourceFile Name of file to copy from. + * Must not be null. + * @param destFile Name of file to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. + * @param overwrite Whether or not the destination file should be + * overwritten if it already exists. + * @param preserveLastModified Whether or not the last modified time of + * the resulting file should be set to that + * of the source file. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -1039,10 +1341,15 @@ public class Project { } /** - * Convienence method to copy a file from a source to a destination. + * Convenience method to copy a file from a source to a destination. * No filtering is performed. * - * @throws IOException + * @param sourceFile File to copy from. + * Must not be null. + * @param destFile File to copy to. + * Must not be null. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -1051,10 +1358,17 @@ public class Project { } /** - * Convienence method to copy a file from a source to a destination - * specifying if token filtering must be used. + * Convenience method to copy a file from a source to a destination + * specifying if token filtering should be used. + * + * @param sourceFile File to copy from. + * Must not be null. + * @param destFile File to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. * - * @throws IOException + * @exception IOException if the copying fails * * @deprecated */ @@ -1064,11 +1378,20 @@ public class Project { } /** - * Convienence method to copy a file from a source to a - * destination specifying if token filtering must be used and if + * Convenience method to copy a file from a source to a + * destination specifying if token filtering should be used and if * source files may overwrite newer destination files. * - * @throws IOException + * @param sourceFile File to copy from. + * Must not be null. + * @param destFile File to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. + * @param overwrite Whether or not the destination file should be + * overwritten if it already exists. + * + * @exception IOException * * @deprecated */ @@ -1078,13 +1401,25 @@ public class Project { } /** - * Convienence method to copy a file from a source to a - * destination specifying if token filtering must be used, if - * source files may overwrite newer destination files and the - * last modified time of destFile file should be made equal - * to the last modified time of sourceFile. + * Convenience method to copy a file from a source to a + * destination specifying if token filtering should be used, if + * source files may overwrite newer destination files, and if the + * last modified time of the resulting file should be set to + * that of the source file. * - * @throws IOException + * @param sourceFile File to copy from. + * Must not be null. + * @param destFile File to copy to. + * Must not be null. + * @param filtering Whether or not token filtering should be used during + * the copy. + * @param overwrite Whether or not the destination file should be + * overwritten if it already exists. + * @param preserveLastModified Whether or not the last modified time of + * the resulting file should be set to that + * of the source file. + * + * @exception IOException if the copying fails * * @deprecated */ @@ -1096,9 +1431,17 @@ public class Project { } /** - * Calls File.setLastModified(long time) in a Java 1.1 compatible way. + * Calls File.setLastModified(long time) on Java above 1.1, and logs + * a warning on Java 1.1. + * + * @param File The file to set the last modified time on. + * Must not be null. * * @deprecated + * + * @exception BuildException if the last modified time cannot be set + * despite running on a platform with a version + * above 1.1. */ public void setFileLastModified(File file, long time) throws BuildException { if (getJavaVersion() == JAVA_1_1) { @@ -1111,8 +1454,16 @@ public class Project { } /** - * returns the boolean equivalent of a string, which is considered true - * if either "on", "true", or "yes" is found, ignoring case. + * Returns the boolean equivalent of a string, which is considered + * true if either "on", "true", + * or "yes" is found, ignoring case. + * + * @param s The string to convert to a boolean value. + * Must not be null. + * + * @return true if the given string is "on", + * "true" or "yes", or + * false otherwise. */ public static boolean toBoolean(String s) { return (s.equalsIgnoreCase("on") || @@ -1121,15 +1472,18 @@ public class Project { } /** - * Topologically sort a set of Targets. - * @param root is the (String) name of the root Target. The sort is - * created in such a way that the sequence of Targets uptil the root - * target is the minimum possible such sequence. - * @param targets is a Hashtable representing a "name to Target" mapping - * @return a Vector of Strings with the names of the targets in - * sorted order. + * Topologically sorts a set of targets. + * + * @param root The name of the root target. The sort is created in such + * a way that the sequence of Targets up to the root + * target is the minimum possible such sequence. + * Must not be null. + * @param targets A map of names to targets (String to Target). + * Must not be null. + * @return a vector of strings with the names of the targets in + * sorted order. * @exception BuildException if there is a cyclic dependency among the - * Targets, or if a Target does not exist. + * targets, or if a named target does not exist. */ public final Vector topoSort(String root, Hashtable targets) throws BuildException { @@ -1161,23 +1515,46 @@ public class Project { return ret; } - // one step in a recursive DFS traversal of the Target dependency tree. - // - The Hashtable "state" contains the state (VISITED or VISITING or null) - // of all the target names. - // - The Stack "visiting" contains a stack of target names that are - // currently on the DFS stack. (NB: the target names in "visiting" are - // exactly the target names in "state" that are in the VISITING state.) - // 1. Set the current target to the VISITING state, and push it onto - // the "visiting" stack. - // 2. Throw a BuildException if any child of the current node is - // in the VISITING state (implies there is a cycle.) It uses the - // "visiting" Stack to construct the cycle. - // 3. If any children have not been VISITED, tsort() the child. - // 4. Add the current target to the Vector "ret" after the children - // have been visited. Move the current target to the VISITED state. - // "ret" now contains the sorted sequence of Targets upto the current - // Target. - + /** + * Performs a single step in a recursive depth-first-search traversal of + * the target dependency tree. + *

+ * The current target is first set to the "visiting" state, and pushed + * onto the "visiting" stack. + *

+ * An exception is then thrown if any child of the current node is in the + * visiting state, as that implies a circular dependency. The exception + * contains details of the cycle, using elements of the "visiting" stack. + *

+ * If any child has not already been "visited", this method is called + * recursively on it. + *

+ * The current target is then added to the ordered list of targets. Note + * that this is performed after the children have been visited in order + * to get the correct order. The current target is set to the "visited" + * state. + *

+ * By the time this method returns, the ordered list contains the sequence + * of targets up to and including the current target. + * + * @param root The current target to inspect. + * Must not be null. + * @param targets A mapping from names to targets (String to Target). + * Must not be null. + * @param state A mapping from target names to states + * (String to String). + * The states in question are "VISITING" and "VISITED". + * Must not be null. + * @param visiting A stack of targets which are currently being visited. + * Must not be null. + * @param ret The list to add target names to. This will end up + * containing the complete list of depenencies in + * dependency order. + * Must not be null. + * + * @exception BuildException if a non-existent target is specified or if + * a circular dependency is detected. + */ private final void tsort(String root, Hashtable targets, Hashtable state, Stack visiting, Vector ret) @@ -1224,6 +1601,14 @@ public class Project { ret.addElement(target); } + /** + * Builds an appropriate exception detailing a specified circular dependency. + * + * @param end The dependency to stop at. Must not be null. + * @param stk A stack of dependencies. Must not be null. + * + * @return a BuildException detailing the specified circular dependency. + */ private static BuildException makeCircularException(String end, Stack stk) { StringBuffer sb = new StringBuffer("Circular dependency: "); sb.append(end); @@ -1236,6 +1621,12 @@ public class Project { return new BuildException(new String(sb)); } + /** + * Adds a reference to the project. + * + * @param name The name of the reference. Must not be null. + * @param value The value of the reference. Must not be null. + */ public void addReference(String name, Object value) { if (null != references.get(name)) { log("Overriding previous definition of reference to " + name, @@ -1245,22 +1636,34 @@ public class Project { references.put(name,value); } + /** + * Returns a map of the references in the project (String to Object). + * The returned hashtable is "live" and so should not be modified. + * + * @return a map of the references in the project (String to Object). + */ public Hashtable getReferences() { return references; } /** - * @return The object with the "id" key. + * Looks up a reference by its key (ID). + * + * @param key The key for the desired reference. + * Must not be null. + * + * @return the reference with the specified ID, or null if + * there is no such reference in the project. */ public Object getReference(String key) { return references.get(key); } /** - * Returns a description of the type of the given element - with + * Returns a description of the type of the given element, with * special handling for instances of tasks and data types. - * - *

This is useful for logging purposes.

+ *

+ * This is useful for logging purposes. * * @param element The element to describe. * Must not be null. @@ -1296,7 +1699,7 @@ public class Project { } /** - * send build started event to the listeners + * Sends a "build started" event to the build listeners for this project. */ protected void fireBuildStarted() { BuildEvent event = new BuildEvent(this); @@ -1307,8 +1710,10 @@ public class Project { } /** - * send build finished event to the listeners - * @param exception exception which indicates failure if not null + * Sends a "build finished" event to the build listeners for this project. + * @param exception an exception indicating a reason for a build + * failure. May be null, indicating + * a successful build. */ protected void fireBuildFinished(Throwable exception) { BuildEvent event = new BuildEvent(this); @@ -1321,7 +1726,10 @@ public class Project { /** - * send target started event to the listeners + * Sends a "target started" event to the build listeners for this project. + * + * @param target The target which is starting to build. + * Must not be null. */ protected void fireTargetStarted(Target target) { BuildEvent event = new BuildEvent(target); @@ -1332,8 +1740,14 @@ public class Project { } /** - * send build finished event to the listeners - * @param exception exception which indicates failure if not null + * Sends a "target finished" event to the build listeners for this + * project. + * + * @param target The target which has finished building. + * Must not be null. + * @param exception an exception indicating a reason for a build + * failure. May be null, indicating + * a successful build. */ protected void fireTargetFinished(Target target, Throwable exception) { BuildEvent event = new BuildEvent(target); @@ -1343,7 +1757,13 @@ public class Project { listener.targetFinished(event); } } - + + /** + * Sends a "task started" event to the build listeners for this project. + * + * @param task The target which is starting to execute. + * Must not be null. + */ protected void fireTaskStarted(Task task) { // register this as the current task on the current thread. threadTasks.put(Thread.currentThread(), task); @@ -1354,6 +1774,16 @@ public class Project { } } + /** + * Sends a "task finished" event to the build listeners for this + * project. + * + * @param task The task which has finished executing. + * Must not be null. + * @param exception an exception indicating a reason for a build + * failure. May be null, indicating + * a successful build. + */ protected void fireTaskFinished(Task task, Throwable exception) { threadTasks.remove(Thread.currentThread()); System.out.flush(); @@ -1366,6 +1796,16 @@ public class Project { } } + /** + * Sends a "message logged" event to the build listeners for this project. + * + * @param event The event to send. This should be built up with the + * appropriate task/target/project by the caller, so that + * this method can set the message and priority, then send + * the event. Must not be null. + * @param message The message to send. Should not be null. + * @param priority The priority of the message. + */ private void fireMessageLoggedEvent(BuildEvent event, String message, int priority) { event.setMessage(message, priority); for (int i = 0; i < listeners.size(); i++) { @@ -1374,16 +1814,43 @@ public class Project { } } + /** + * Sends a "message logged" project level event to the build listeners for + * this project. + * + * @param project The project generating the event. + * Should not be null. + * @param message The message to send. Should not be null. + * @param priority The priority of the message. + */ protected void fireMessageLogged(Project project, String message, int priority) { BuildEvent event = new BuildEvent(project); fireMessageLoggedEvent(event, message, priority); } + /** + * Sends a "message logged" target level event to the build listeners for + * this project. + * + * @param target The target generating the event. + * Must not be null. + * @param message The message to send. Should not be null. + * @param priority The priority of the message. + */ protected void fireMessageLogged(Target target, String message, int priority) { BuildEvent event = new BuildEvent(target); fireMessageLoggedEvent(event, message, priority); } + /** + * Sends a "message logged" task level event to the build listeners for + * this project. + * + * @param task The task generating the event. + * Must not be null. + * @param message The message to send. Should not be null. + * @param priority The priority of the message. + */ protected void fireMessageLogged(Task task, String message, int priority) { BuildEvent event = new BuildEvent(task); fireMessageLoggedEvent(event, message, priority);