KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > Project


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.EOFException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Modifier JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.util.Stack JavaDoc;
33 import java.util.Vector JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.WeakHashMap JavaDoc;
39 import org.apache.tools.ant.input.DefaultInputHandler;
40 import org.apache.tools.ant.input.InputHandler;
41 import org.apache.tools.ant.helper.DefaultExecutor;
42 import org.apache.tools.ant.types.FilterSet;
43 import org.apache.tools.ant.types.FilterSetCollection;
44 import org.apache.tools.ant.types.Description;
45 import org.apache.tools.ant.types.Path;
46 import org.apache.tools.ant.types.Resource;
47 import org.apache.tools.ant.types.ResourceFactory;
48 import org.apache.tools.ant.types.resources.FileResource;
49 import org.apache.tools.ant.util.FileUtils;
50 import org.apache.tools.ant.util.JavaEnvUtils;
51 import org.apache.tools.ant.util.StringUtils;
52
53 /**
54  * Central representation of an Ant project. This class defines an
55  * Ant project with all of its targets, tasks and various other
56  * properties. It also provides the mechanism to kick off a build using
57  * a particular target name.
58  * <p>
59  * This class also encapsulates methods which allow files to be referred
60  * to using abstract path names which are translated to native system
61  * file paths at runtime.
62  *
63  */

64 public class Project implements ResourceFactory {
65     private static final String JavaDoc LINE_SEP = System.getProperty("line.separator");
66
67     /** Message priority of &quot;error&quot;. */
68     public static final int MSG_ERR = 0;
69     /** Message priority of &quot;warning&quot;. */
70     public static final int MSG_WARN = 1;
71     /** Message priority of &quot;information&quot;. */
72     public static final int MSG_INFO = 2;
73     /** Message priority of &quot;verbose&quot;. */
74     public static final int MSG_VERBOSE = 3;
75     /** Message priority of &quot;debug&quot;. */
76     public static final int MSG_DEBUG = 4;
77
78     /**
79      * Constant for the &quot;visiting&quot; state, used when
80      * traversing a DFS of target dependencies.
81      */

82     private static final String JavaDoc VISITING = "VISITING";
83     /**
84      * Constant for the &quot;visited&quot; state, used when
85      * traversing a DFS of target dependencies.
86      */

87     private static final String JavaDoc VISITED = "VISITED";
88
89     /**
90      * Version constant for Java 1.0 .
91      *
92      * @deprecated since 1.5.x.
93      * Use {@link JavaEnvUtils#JAVA_1_0} instead.
94      */

95     public static final String JavaDoc JAVA_1_0 = JavaEnvUtils.JAVA_1_0;
96     /**
97      * Version constant for Java 1.1 .
98      *
99      * @deprecated since 1.5.x.
100      * Use {@link JavaEnvUtils#JAVA_1_1} instead.
101      */

102     public static final String JavaDoc JAVA_1_1 = JavaEnvUtils.JAVA_1_1;
103     /**
104      * Version constant for Java 1.2 .
105      *
106      * @deprecated since 1.5.x.
107      * Use {@link JavaEnvUtils#JAVA_1_2} instead.
108      */

109     public static final String JavaDoc JAVA_1_2 = JavaEnvUtils.JAVA_1_2;
110     /**
111      * Version constant for Java 1.3 .
112      *
113      * @deprecated since 1.5.x.
114      * Use {@link JavaEnvUtils#JAVA_1_3} instead.
115      */

116     public static final String JavaDoc JAVA_1_3 = JavaEnvUtils.JAVA_1_3;
117     /**
118      * Version constant for Java 1.4 .
119      *
120      * @deprecated since 1.5.x.
121      * Use {@link JavaEnvUtils#JAVA_1_4} instead.
122      */

123     public static final String JavaDoc JAVA_1_4 = JavaEnvUtils.JAVA_1_4;
124
125     /** Default filter start token. */
126     public static final String JavaDoc TOKEN_START = FilterSet.DEFAULT_TOKEN_START;
127     /** Default filter end token. */
128     public static final String JavaDoc TOKEN_END = FilterSet.DEFAULT_TOKEN_END;
129
130     /** Instance of a utility class to use for file operations. */
131     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
132
133     /** Name of this project. */
134     private String JavaDoc name;
135     /** Description for this project (if any). */
136     private String JavaDoc description;
137
138
139     /** Map of references within the project (paths etc) (String to Object). */
140     private Hashtable JavaDoc references = new AntRefTable();
141
142     /** Map of id references - used for indicating broken build files */
143     private HashMap JavaDoc idReferences = new HashMap JavaDoc();
144
145     /** the parent project for old id resolution (if inheritreferences is set) */
146     private Project parentIdProject = null;
147
148     /** Name of the project's default target. */
149     private String JavaDoc defaultTarget;
150
151     /** Map from target names to targets (String to Target). */
152     private Hashtable JavaDoc targets = new Hashtable JavaDoc();
153     /** Set of global filters. */
154     private FilterSet globalFilterSet = new FilterSet();
155     {
156         // Initialize the globalFileSet's project
157
globalFilterSet.setProject(this);
158     }
159
160     /**
161      * Wrapper around globalFilterSet. This collection only ever
162      * contains one FilterSet, but the wrapper is needed in order to
163      * make it easier to use the FileUtils interface.
164      */

165     private FilterSetCollection globalFilters
166         = new FilterSetCollection(globalFilterSet);
167
168     /** Project base directory. */
169     private File JavaDoc baseDir;
170
171     /** List of listeners to notify of build events. */
172     private Vector JavaDoc listeners = new Vector JavaDoc();
173
174     /**
175      * The Ant core classloader--may be <code>null</code> if using
176      * parent classloader.
177      */

178     private ClassLoader JavaDoc coreLoader = null;
179
180     /** Records the latest task to be executed on a thread. */
181     private Map JavaDoc/*<Thread,Task>*/ threadTasks = Collections.synchronizedMap(new WeakHashMap JavaDoc());
182
183     /** Records the latest task to be executed on a thread group. */
184     private Map JavaDoc/*<ThreadGroup,Task>*/ threadGroupTasks
185         = Collections.synchronizedMap(new WeakHashMap JavaDoc());
186
187     /**
188      * Called to handle any input requests.
189      */

190     private InputHandler inputHandler = null;
191
192     /**
193      * The default input stream used to read any input.
194      */

195     private InputStream JavaDoc defaultInputStream = null;
196
197     /**
198      * Keep going flag.
199      */

200     private boolean keepGoingMode = false;
201
202     /**
203      * Flag which catches Listeners which try to use System.out or System.err .
204      */

205     private boolean loggingMessage = false;
206
207     /**
208      * Set the input handler.
209      *
210      * @param handler the InputHandler instance to use for gathering input.
211      */

212     public void setInputHandler(InputHandler handler) {
213         inputHandler = handler;
214     }
215
216     /**
217      * Set the default System input stream. Normally this stream is set to
218      * System.in. This inputStream is used when no task input redirection is
219      * being performed.
220      *
221      * @param defaultInputStream the default input stream to use when input
222      * is requested.
223      * @since Ant 1.6
224      */

225     public void setDefaultInputStream(InputStream JavaDoc defaultInputStream) {
226         this.defaultInputStream = defaultInputStream;
227     }
228
229     /**
230      * Get this project's input stream.
231      *
232      * @return the InputStream instance in use by this Project instance to
233      * read input.
234      */

235     public InputStream JavaDoc getDefaultInputStream() {
236         return defaultInputStream;
237     }
238
239     /**
240      * Retrieve the current input handler.
241      *
242      * @return the InputHandler instance currently in place for the project
243      * instance.
244      */

245     public InputHandler getInputHandler() {
246         return inputHandler;
247     }
248
249     /**
250      * Create a new Ant project.
251      */

252     public Project() {
253         inputHandler = new DefaultInputHandler();
254     }
255
256     /**
257      * Create and initialize a subproject. By default the subproject will be of
258      * the same type as its parent. If a no-arg constructor is unavailable, the
259      * <code>Project</code> class will be used.
260      * @return a Project instance configured as a subproject of this Project.
261      * @since Ant 1.7
262      */

263     public Project createSubProject() {
264         Project subProject = null;
265         try {
266             subProject = (Project) (getClass().newInstance());
267         } catch (Exception JavaDoc e) {
268             subProject = new Project();
269         }
270         initSubProject(subProject);
271         return subProject;
272     }
273
274     /**
275      * Initialize a subproject.
276      * @param subProject the subproject to initialize.
277      */

278     public void initSubProject(Project subProject) {
279         ComponentHelper.getComponentHelper(subProject)
280             .initSubProject(ComponentHelper.getComponentHelper(this));
281         subProject.setDefaultInputStream(getDefaultInputStream());
282         subProject.setKeepGoingMode(this.isKeepGoingMode());
283         subProject.setExecutor(getExecutor().getSubProjectExecutor());
284     }
285
286     /**
287      * Initialise the project.
288      *
289      * This involves setting the default task definitions and loading the
290      * system properties.
291      *
292      * @exception BuildException if the default task list cannot be loaded.
293      */

294     public void init() throws BuildException {
295         initProperties();
296
297         ComponentHelper.getComponentHelper(this).initDefaultDefinitions();
298     }
299
300     /**
301      * Initializes the properties.
302      * @exception BuildException if an vital property could not be set.
303      * @since Ant 1.7
304      */

305     public void initProperties() throws BuildException {
306         setJavaVersionProperty();
307         setSystemProperties();
308         setPropertyInternal(MagicNames.ANT_VERSION, Main.getAntVersion());
309         setAntLib();
310     }
311
312     private void setAntLib() {
313         File JavaDoc antlib = org.apache.tools.ant.launch.Locator.getClassSource(
314             Project.class);
315         if (antlib != null) {
316             setPropertyInternal(MagicNames.ANT_LIB, antlib.getAbsolutePath());
317         }
318     }
319     /**
320      * Factory method to create a class loader for loading classes from
321      * a given path.
322      *
323      * @param path the path from which classes are to be loaded.
324      *
325      * @return an appropriate classloader.
326      */

327     public AntClassLoader createClassLoader(Path path) {
328         return new AntClassLoader(
329             getClass().getClassLoader(), this, path);
330     }
331
332     /**
333      * Factory method to create a class loader for loading classes from
334      * a given path.
335      *
336      * @param parent the parent classloader for the new loader.
337      * @param path the path from which classes are to be loaded.
338      *
339      * @return an appropriate classloader.
340      */

341     public AntClassLoader createClassLoader(
342         ClassLoader JavaDoc parent, Path path) {
343         return new AntClassLoader(parent, this, path);
344     }
345
346     /**
347      * Set the core classloader for the project. If a <code>null</code>
348      * classloader is specified, the parent classloader should be used.
349      *
350      * @param coreLoader The classloader to use for the project.
351      * May be <code>null</code>.
352      */

353     public void setCoreLoader(ClassLoader JavaDoc coreLoader) {
354         this.coreLoader = coreLoader;
355     }
356
357     /**
358      * Return the core classloader to use for this project.
359      * This may be <code>null</code>, indicating that
360      * the parent classloader should be used.
361      *
362      * @return the core classloader to use for this project.
363      *
364      */

365     public ClassLoader JavaDoc getCoreLoader() {
366         return coreLoader;
367     }
368
369     /**
370      * Add a build listener to the list. This listener will
371      * be notified of build events for this project.
372      *
373      * @param listener The listener to add to the list.
374      * Must not be <code>null</code>.
375      */

376     public synchronized void addBuildListener(BuildListener listener) {
377         // If the listeners already has this listener, do nothing
378
if (listeners.contains(listener)) {
379             return;
380         }
381         // create a new Vector to avoid ConcurrentModificationExc when
382
// the listeners get added/removed while we are in fire
383
Vector JavaDoc newListeners = getBuildListeners();
384         newListeners.addElement(listener);
385         listeners = newListeners;
386     }
387
388     /**
389      * Remove a build listener from the list. This listener
390      * will no longer be notified of build events for this project.
391      *
392      * @param listener The listener to remove from the list.
393      * Should not be <code>null</code>.
394      */

395     public synchronized void removeBuildListener(BuildListener listener) {
396         // create a new Vector to avoid ConcurrentModificationExc when
397
// the listeners get added/removed while we are in fire
398
Vector JavaDoc newListeners = getBuildListeners();
399         newListeners.removeElement(listener);
400         listeners = newListeners;
401     }
402
403     /**
404      * Return a copy of the list of build listeners for the project.
405      *
406      * @return a list of build listeners for the project
407      */

408     public Vector JavaDoc getBuildListeners() {
409         return (Vector JavaDoc) listeners.clone();
410     }
411
412     /**
413      * Write a message to the log with the default log level
414      * of MSG_INFO .
415      * @param message The text to log. Should not be <code>null</code>.
416      */

417
418     public void log(String JavaDoc message) {
419         log(message, MSG_INFO);
420     }
421
422     /**
423      * Write a project level message to the log with the given log level.
424      * @param message The text to log. Should not be <code>null</code>.
425      * @param msgLevel The log priority level to use.
426      */

427     public void log(String JavaDoc message, int msgLevel) {
428         log(message, null, msgLevel);
429     }
430
431     /**
432      * Write a project level message to the log with the given log level.
433      * @param message The text to log. Should not be <code>null</code>.
434      * @param throwable The exception causing this log, may be <code>null</code>.
435      * @param msgLevel The log priority level to use.
436      * @since 1.7
437      */

438     public void log(String JavaDoc message, Throwable JavaDoc throwable, int msgLevel) {
439         fireMessageLogged(this, message, throwable, msgLevel);
440     }
441
442     /**
443      * Write a task level message to the log with the given log level.
444      * @param task The task to use in the log. Must not be <code>null</code>.
445      * @param message The text to log. Should not be <code>null</code>.
446      * @param msgLevel The log priority level to use.
447      */

448     public void log(Task task, String JavaDoc message, int msgLevel) {
449         fireMessageLogged(task, message, null, msgLevel);
450     }
451
452     /**
453      * Write a task level message to the log with the given log level.
454      * @param task The task to use in the log. Must not be <code>null</code>.
455      * @param message The text to log. Should not be <code>null</code>.
456      * @param throwable The exception causing this log, may be <code>null</code>.
457      * @param msgLevel The log priority level to use.
458      * @since 1.7
459      */

460     public void log(Task task, String JavaDoc message, Throwable JavaDoc throwable, int msgLevel) {
461         fireMessageLogged(task, message, throwable, msgLevel);
462     }
463
464     /**
465      * Write a target level message to the log with the given log level.
466      * @param target The target to use in the log.
467      * Must not be <code>null</code>.
468      * @param message The text to log. Should not be <code>null</code>.
469      * @param msgLevel The log priority level to use.
470      */

471     public void log(Target target, String JavaDoc message, int msgLevel) {
472         log(target, message, null, msgLevel);
473     }
474
475     /**
476      * Write a target level message to the log with the given log level.
477      * @param target The target to use in the log.
478      * Must not be <code>null</code>.
479      * @param message The text to log. Should not be <code>null</code>.
480      * @param throwable The exception causing this log, may be <code>null</code>.
481      * @param msgLevel The log priority level to use.
482      * @since 1.7
483      */

484     public void log(Target target, String JavaDoc message, Throwable JavaDoc throwable,
485             int msgLevel) {
486         fireMessageLogged(target, message, throwable, msgLevel);
487     }
488
489     /**
490      * Return the set of global filters.
491      *
492      * @return the set of global filters.
493      */

494     public FilterSet getGlobalFilterSet() {
495         return globalFilterSet;
496     }
497
498     /**
499      * Set a property. Any existing property of the same name
500      * is overwritten, unless it is a user property.
501      * @param name The name of property to set.
502      * Must not be <code>null</code>.
503      * @param value The new value of the property.
504      * Must not be <code>null</code>.
505      */

506     public void setProperty(String JavaDoc name, String JavaDoc value) {
507         PropertyHelper.getPropertyHelper(this).
508                 setProperty(null, name, value, true);
509     }
510
511     /**
512      * Set a property if no value currently exists. If the property
513      * exists already, a message is logged and the method returns with
514      * no other effect.
515      *
516      * @param name The name of property to set.
517      * Must not be <code>null</code>.
518      * @param value The new value of the property.
519      * Must not be <code>null</code>.
520      * @since 1.5
521      */

522     public void setNewProperty(String JavaDoc name, String JavaDoc value) {
523         PropertyHelper.getPropertyHelper(this).setNewProperty(null, name,
524                                                               value);
525     }
526
527     /**
528      * Set a user property, which cannot be overwritten by
529      * set/unset property calls. Any previous value is overwritten.
530      * @param name The name of property to set.
531      * Must not be <code>null</code>.
532      * @param value The new value of the property.
533      * Must not be <code>null</code>.
534      * @see #setProperty(String,String)
535      */

536     public void setUserProperty(String JavaDoc name, String JavaDoc value) {
537         PropertyHelper.getPropertyHelper(this).setUserProperty(null, name,
538                                                                value);
539     }
540
541     /**
542      * Set a user property, which cannot be overwritten by set/unset
543      * property calls. Any previous value is overwritten. Also marks
544      * these properties as properties that have not come from the
545      * command line.
546      *
547      * @param name The name of property to set.
548      * Must not be <code>null</code>.
549      * @param value The new value of the property.
550      * Must not be <code>null</code>.
551      * @see #setProperty(String,String)
552      */

553     public void setInheritedProperty(String JavaDoc name, String JavaDoc value) {
554         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
555         ph.setInheritedProperty(null, name, value);
556     }
557
558     /**
559      * Set a property unless it is already defined as a user property
560      * (in which case the method returns silently).
561      *
562      * @param name The name of the property.
563      * Must not be <code>null</code>.
564      * @param value The property value. Must not be <code>null</code>.
565      */

566     private void setPropertyInternal(String JavaDoc name, String JavaDoc value) {
567         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
568         ph.setProperty(null, name, value, false);
569     }
570
571     /**
572      * Return the value of a property, if it is set.
573      *
574      * @param propertyName The name of the property.
575      * May be <code>null</code>, in which case
576      * the return value is also <code>null</code>.
577      * @return the property value, or <code>null</code> for no match
578      * or if a <code>null</code> name is provided.
579      */

580     public String JavaDoc getProperty(String JavaDoc propertyName) {
581         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
582         return (String JavaDoc) ph.getProperty(null, propertyName);
583     }
584
585     /**
586      * Replace ${} style constructions in the given value with the
587      * string value of the corresponding data types.
588      *
589      * @param value The string to be scanned for property references.
590      * May be <code>null</code>.
591      *
592      * @return the given string with embedded property names replaced
593      * by values, or <code>null</code> if the given string is
594      * <code>null</code>.
595      *
596      * @exception BuildException if the given value has an unclosed
597      * property name, e.g. <code>${xxx</code>.
598      */

599     public String JavaDoc replaceProperties(String JavaDoc value)
600         throws BuildException {
601         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
602         return ph.replaceProperties(null, value, null);
603     }
604
605     /**
606      * Return the value of a user property, if it is set.
607      *
608      * @param propertyName The name of the property.
609      * May be <code>null</code>, in which case
610      * the return value is also <code>null</code>.
611      * @return the property value, or <code>null</code> for no match
612      * or if a <code>null</code> name is provided.
613      */

614      public String JavaDoc getUserProperty(String JavaDoc propertyName) {
615         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
616         return (String JavaDoc) ph.getUserProperty(null, propertyName);
617     }
618
619     /**
620      * Return a copy of the properties table.
621      * @return a hashtable containing all properties
622      * (including user properties).
623      */

624     public Hashtable JavaDoc getProperties() {
625         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
626         return ph.getProperties();
627     }
628
629     /**
630      * Return a copy of the user property hashtable.
631      * @return a hashtable containing just the user properties.
632      */

633     public Hashtable JavaDoc getUserProperties() {
634         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
635         return ph.getUserProperties();
636     }
637
638     /**
639      * Copy all user properties that have been set on the command
640      * line or a GUI tool from this instance to the Project instance
641      * given as the argument.
642      *
643      * <p>To copy all &quot;user&quot; properties, you will also have to call
644      * {@link #copyInheritedProperties copyInheritedProperties}.</p>
645      *
646      * @param other the project to copy the properties to. Must not be null.
647      *
648      * @since Ant 1.5
649      */

650     public void copyUserProperties(Project other) {
651         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
652         ph.copyUserProperties(other);
653     }
654
655     /**
656      * Copy all user properties that have not been set on the
657      * command line or a GUI tool from this instance to the Project
658      * instance given as the argument.
659      *
660      * <p>To copy all &quot;user&quot; properties, you will also have to call
661      * {@link #copyUserProperties copyUserProperties}.</p>
662      *
663      * @param other the project to copy the properties to. Must not be null.
664      *
665      * @since Ant 1.5
666      */

667     public void copyInheritedProperties(Project other) {
668         PropertyHelper ph = PropertyHelper.getPropertyHelper(this);
669         ph.copyInheritedProperties(other);
670     }
671
672     /**
673      * Set the default target of the project.
674      *
675      * @param defaultTarget The name of the default target for this project.
676      * May be <code>null</code>, indicating that there is
677      * no default target.
678      *
679      * @deprecated since 1.5.x.
680      * Use setDefault.
681      * @see #setDefault(String)
682      */

683     public void setDefaultTarget(String JavaDoc defaultTarget) {
684         this.defaultTarget = defaultTarget;
685     }
686
687     /**
688      * Return the name of the default target of the project.
689      * @return name of the default target or
690      * <code>null</code> if no default has been set.
691      */

692     public String JavaDoc getDefaultTarget() {
693         return defaultTarget;
694     }
695
696     /**
697      * Set the default target of the project.
698      *
699      * @param defaultTarget The name of the default target for this project.
700      * May be <code>null</code>, indicating that there is
701      * no default target.
702      */

703     public void setDefault(String JavaDoc defaultTarget) {
704         this.defaultTarget = defaultTarget;
705     }
706
707     /**
708      * Set the name of the project, also setting the user
709      * property <code>ant.project.name</code>.
710      *
711      * @param name The name of the project.
712      * Must not be <code>null</code>.
713      */

714     public void setName(String JavaDoc name) {
715         setUserProperty("ant.project.name", name);
716         this.name = name;
717     }
718
719     /**
720      * Return the project name, if one has been set.
721      *
722      * @return the project name, or <code>null</code> if it hasn't been set.
723      */

724     public String JavaDoc getName() {
725         return name;
726     }
727
728     /**
729      * Set the project description.
730      *
731      * @param description The description of the project.
732      * May be <code>null</code>.
733      */

734     public void setDescription(String JavaDoc description) {
735         this.description = description;
736     }
737
738     /**
739      * Return the project description, if one has been set.
740      *
741      * @return the project description, or <code>null</code> if it hasn't
742      * been set.
743      */

744     public String JavaDoc getDescription() {
745         if (description == null) {
746             description = Description.getDescription(this);
747         }
748         return description;
749     }
750
751     /**
752      * Add a filter to the set of global filters.
753      *
754      * @param token The token to filter.
755      * Must not be <code>null</code>.
756      * @param value The replacement value.
757      * Must not be <code>null</code>.
758      * @deprecated since 1.4.x.
759      * Use getGlobalFilterSet().addFilter(token,value)
760      *
761      * @see #getGlobalFilterSet()
762      * @see FilterSet#addFilter(String,String)
763      */

764     public void addFilter(String JavaDoc token, String JavaDoc value) {
765         if (token == null) {
766             return;
767         }
768         globalFilterSet.addFilter(new FilterSet.Filter(token, value));
769     }
770
771     /**
772      * Return a hashtable of global filters, mapping tokens to values.
773      *
774      * @return a hashtable of global filters, mapping tokens to values
775      * (String to String).
776      *
777      * @deprecated since 1.4.x
778      * Use getGlobalFilterSet().getFilterHash().
779      *
780      * @see #getGlobalFilterSet()
781      * @see FilterSet#getFilterHash()
782      */

783     public Hashtable JavaDoc getFilters() {
784         // we need to build the hashtable dynamically
785
return globalFilterSet.getFilterHash();
786     }
787
788     /**
789      * Set the base directory for the project, checking that
790      * the given filename exists and is a directory.
791      *
792      * @param baseD The project base directory.
793      * Must not be <code>null</code>.
794      *
795      * @exception BuildException if the directory if invalid.
796      */

797     public void setBasedir(String JavaDoc baseD) throws BuildException {
798         setBaseDir(new File JavaDoc(baseD));
799     }
800
801     /**
802      * Set the base directory for the project, checking that
803      * the given file exists and is a directory.
804      *
805      * @param baseDir The project base directory.
806      * Must not be <code>null</code>.
807      * @exception BuildException if the specified file doesn't exist or
808      * isn't a directory.
809      */

810     public void setBaseDir(File JavaDoc baseDir) throws BuildException {
811         baseDir = FILE_UTILS.normalize(baseDir.getAbsolutePath());
812         if (!baseDir.exists()) {
813             throw new BuildException("Basedir " + baseDir.getAbsolutePath()
814                 + " does not exist");
815         }
816         if (!baseDir.isDirectory()) {
817             throw new BuildException("Basedir " + baseDir.getAbsolutePath()
818                 + " is not a directory");
819         }
820         this.baseDir = baseDir;
821         setPropertyInternal(MagicNames.PROJECT_BASEDIR, this.baseDir.getPath());
822         String JavaDoc msg = "Project base dir set to: " + this.baseDir;
823          log(msg, MSG_VERBOSE);
824     }
825
826     /**
827      * Return the base directory of the project as a file object.
828      *
829      * @return the project base directory, or <code>null</code> if the
830      * base directory has not been successfully set to a valid value.
831      */

832     public File JavaDoc getBaseDir() {
833         if (baseDir == null) {
834             try {
835                 setBasedir(".");
836             } catch (BuildException ex) {
837                 ex.printStackTrace();
838             }
839         }
840         return baseDir;
841     }
842
843     /**
844      * Set &quot;keep-going&quot; mode. In this mode Ant will try to execute
845      * as many targets as possible. All targets that do not depend
846      * on failed target(s) will be executed. If the keepGoing settor/getter
847      * methods are used in conjunction with the <code>ant.executor.class</code>
848      * property, they will have no effect.
849      * @param keepGoingMode &quot;keep-going&quot; mode
850      * @since Ant 1.6
851      */

852     public void setKeepGoingMode(boolean keepGoingMode) {
853         this.keepGoingMode = keepGoingMode;
854     }
855
856     /**
857      * Return the keep-going mode. If the keepGoing settor/getter
858      * methods are used in conjunction with the <code>ant.executor.class</code>
859      * property, they will have no effect.
860      * @return &quot;keep-going&quot; mode
861      * @since Ant 1.6
862      */

863     public boolean isKeepGoingMode() {
864         return this.keepGoingMode;
865     }
866
867     /**
868      * Return the version of Java this class is running under.
869      * @return the version of Java as a String, e.g. "1.1" .
870      * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
871      * @deprecated since 1.5.x.
872      * Use org.apache.tools.ant.util.JavaEnvUtils instead.
873      */

874     public static String JavaDoc getJavaVersion() {
875         return JavaEnvUtils.getJavaVersion();
876     }
877
878     /**
879      * Set the <code>ant.java.version</code> property and tests for
880      * unsupported JVM versions. If the version is supported,
881      * verbose log messages are generated to record the Java version
882      * and operating system name.
883      *
884      * @exception BuildException if this Java version is not supported.
885      *
886      * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
887      */

888     public void setJavaVersionProperty() throws BuildException {
889         String JavaDoc javaVersion = JavaEnvUtils.getJavaVersion();
890         setPropertyInternal(MagicNames.ANT_JAVA_VERSION, javaVersion);
891
892         // sanity check
893
if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_0)
894                 || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
895             throw new BuildException("Ant cannot work on Java 1.0 / 1.1");
896         }
897         log("Detected Java version: " + javaVersion + " in: "
898             + System.getProperty("java.home"), MSG_VERBOSE);
899
900         log("Detected OS: " + System.getProperty("os.name"), MSG_VERBOSE);
901     }
902
903     /**
904      * Add all system properties which aren't already defined as
905      * user properties to the project properties.
906      */

907     public void setSystemProperties() {
908      &nb