Source Code Cross Referenced for Project.java in  » Build » ANT » org » apache » tools » ant » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Build » ANT » org.apache.tools.ant 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         *
0017:         */
0018:
0019:        package org.apache.tools.ant;
0020:
0021:        import java.io.File;
0022:        import java.io.IOException;
0023:        import java.io.EOFException;
0024:        import java.io.InputStream;
0025:        import java.lang.reflect.Method;
0026:        import java.lang.reflect.Modifier;
0027:        import java.util.Collections;
0028:        import java.util.Enumeration;
0029:        import java.util.Hashtable;
0030:        import java.util.Iterator;
0031:        import java.util.Properties;
0032:        import java.util.Stack;
0033:        import java.util.Vector;
0034:        import java.util.Set;
0035:        import java.util.HashSet;
0036:        import java.util.HashMap;
0037:        import java.util.Map;
0038:        import java.util.WeakHashMap;
0039:        import org.apache.tools.ant.input.DefaultInputHandler;
0040:        import org.apache.tools.ant.input.InputHandler;
0041:        import org.apache.tools.ant.helper.DefaultExecutor;
0042:        import org.apache.tools.ant.types.FilterSet;
0043:        import org.apache.tools.ant.types.FilterSetCollection;
0044:        import org.apache.tools.ant.types.Description;
0045:        import org.apache.tools.ant.types.Path;
0046:        import org.apache.tools.ant.types.Resource;
0047:        import org.apache.tools.ant.types.ResourceFactory;
0048:        import org.apache.tools.ant.types.resources.FileResource;
0049:        import org.apache.tools.ant.util.FileUtils;
0050:        import org.apache.tools.ant.util.JavaEnvUtils;
0051:        import org.apache.tools.ant.util.StringUtils;
0052:
0053:        /**
0054:         * Central representation of an Ant project. This class defines an
0055:         * Ant project with all of its targets, tasks and various other
0056:         * properties. It also provides the mechanism to kick off a build using
0057:         * a particular target name.
0058:         * <p>
0059:         * This class also encapsulates methods which allow files to be referred
0060:         * to using abstract path names which are translated to native system
0061:         * file paths at runtime.
0062:         *
0063:         */
0064:        public class Project implements  ResourceFactory {
0065:            private static final String LINE_SEP = System
0066:                    .getProperty("line.separator");
0067:
0068:            /** Message priority of &quot;error&quot;. */
0069:            public static final int MSG_ERR = 0;
0070:            /** Message priority of &quot;warning&quot;. */
0071:            public static final int MSG_WARN = 1;
0072:            /** Message priority of &quot;information&quot;. */
0073:            public static final int MSG_INFO = 2;
0074:            /** Message priority of &quot;verbose&quot;. */
0075:            public static final int MSG_VERBOSE = 3;
0076:            /** Message priority of &quot;debug&quot;. */
0077:            public static final int MSG_DEBUG = 4;
0078:
0079:            /**
0080:             * Constant for the &quot;visiting&quot; state, used when
0081:             * traversing a DFS of target dependencies.
0082:             */
0083:            private static final String VISITING = "VISITING";
0084:            /**
0085:             * Constant for the &quot;visited&quot; state, used when
0086:             * traversing a DFS of target dependencies.
0087:             */
0088:            private static final String VISITED = "VISITED";
0089:
0090:            /**
0091:             * Version constant for Java 1.0 .
0092:             *
0093:             * @deprecated since 1.5.x.
0094:             *             Use {@link JavaEnvUtils#JAVA_1_0} instead.
0095:             */
0096:            public static final String JAVA_1_0 = JavaEnvUtils.JAVA_1_0;
0097:            /**
0098:             * Version constant for Java 1.1 .
0099:             *
0100:             * @deprecated since 1.5.x.
0101:             *             Use {@link JavaEnvUtils#JAVA_1_1} instead.
0102:             */
0103:            public static final String JAVA_1_1 = JavaEnvUtils.JAVA_1_1;
0104:            /**
0105:             * Version constant for Java 1.2 .
0106:             *
0107:             * @deprecated since 1.5.x.
0108:             *             Use {@link JavaEnvUtils#JAVA_1_2} instead.
0109:             */
0110:            public static final String JAVA_1_2 = JavaEnvUtils.JAVA_1_2;
0111:            /**
0112:             * Version constant for Java 1.3 .
0113:             *
0114:             * @deprecated since 1.5.x.
0115:             *             Use {@link JavaEnvUtils#JAVA_1_3} instead.
0116:             */
0117:            public static final String JAVA_1_3 = JavaEnvUtils.JAVA_1_3;
0118:            /**
0119:             * Version constant for Java 1.4 .
0120:             *
0121:             * @deprecated since 1.5.x.
0122:             *             Use {@link JavaEnvUtils#JAVA_1_4} instead.
0123:             */
0124:            public static final String JAVA_1_4 = JavaEnvUtils.JAVA_1_4;
0125:
0126:            /** Default filter start token. */
0127:            public static final String TOKEN_START = FilterSet.DEFAULT_TOKEN_START;
0128:            /** Default filter end token. */
0129:            public static final String TOKEN_END = FilterSet.DEFAULT_TOKEN_END;
0130:
0131:            /** Instance of a utility class to use for file operations. */
0132:            private static final FileUtils FILE_UTILS = FileUtils
0133:                    .getFileUtils();
0134:
0135:            /** Name of this project. */
0136:            private String name;
0137:            /** Description for this project (if any). */
0138:            private String description;
0139:
0140:            /** Map of references within the project (paths etc) (String to Object). */
0141:            private Hashtable references = new AntRefTable();
0142:
0143:            /** Map of id references - used for indicating broken build files */
0144:            private HashMap idReferences = new HashMap();
0145:
0146:            /** the parent project for old id resolution (if inheritreferences is set) */
0147:            private Project parentIdProject = null;
0148:
0149:            /** Name of the project's default target. */
0150:            private String defaultTarget;
0151:
0152:            /** Map from target names to targets (String to Target). */
0153:            private Hashtable targets = new Hashtable();
0154:            /** Set of global filters. */
0155:            private FilterSet globalFilterSet = new FilterSet();
0156:            {
0157:                // Initialize the globalFileSet's project
0158:                globalFilterSet.setProject(this );
0159:            }
0160:
0161:            /**
0162:             * Wrapper around globalFilterSet. This collection only ever
0163:             * contains one FilterSet, but the wrapper is needed in order to
0164:             * make it easier to use the FileUtils interface.
0165:             */
0166:            private FilterSetCollection globalFilters = new FilterSetCollection(
0167:                    globalFilterSet);
0168:
0169:            /** Project base directory. */
0170:            private File baseDir;
0171:
0172:            /** List of listeners to notify of build events. */
0173:            private Vector listeners = new Vector();
0174:
0175:            /**
0176:             * The Ant core classloader--may be <code>null</code> if using
0177:             * parent classloader.
0178:             */
0179:            private ClassLoader coreLoader = null;
0180:
0181:            /** Records the latest task to be executed on a thread. */
0182:            private Map/*<Thread,Task>*/threadTasks = Collections
0183:                    .synchronizedMap(new WeakHashMap());
0184:
0185:            /** Records the latest task to be executed on a thread group. */
0186:            private Map/*<ThreadGroup,Task>*/threadGroupTasks = Collections
0187:                    .synchronizedMap(new WeakHashMap());
0188:
0189:            /**
0190:             * Called to handle any input requests.
0191:             */
0192:            private InputHandler inputHandler = null;
0193:
0194:            /**
0195:             * The default input stream used to read any input.
0196:             */
0197:            private InputStream defaultInputStream = null;
0198:
0199:            /**
0200:             * Keep going flag.
0201:             */
0202:            private boolean keepGoingMode = false;
0203:
0204:            /**
0205:             * Flag which catches Listeners which try to use System.out or System.err .
0206:             */
0207:            private boolean loggingMessage = false;
0208:
0209:            /**
0210:             * Set the input handler.
0211:             *
0212:             * @param handler the InputHandler instance to use for gathering input.
0213:             */
0214:            public void setInputHandler(InputHandler handler) {
0215:                inputHandler = handler;
0216:            }
0217:
0218:            /**
0219:             * Set the default System input stream. Normally this stream is set to
0220:             * System.in. This inputStream is used when no task input redirection is
0221:             * being performed.
0222:             *
0223:             * @param defaultInputStream the default input stream to use when input
0224:             *        is requested.
0225:             * @since Ant 1.6
0226:             */
0227:            public void setDefaultInputStream(InputStream defaultInputStream) {
0228:                this .defaultInputStream = defaultInputStream;
0229:            }
0230:
0231:            /**
0232:             * Get this project's input stream.
0233:             *
0234:             * @return the InputStream instance in use by this Project instance to
0235:             * read input.
0236:             */
0237:            public InputStream getDefaultInputStream() {
0238:                return defaultInputStream;
0239:            }
0240:
0241:            /**
0242:             * Retrieve the current input handler.
0243:             *
0244:             * @return the InputHandler instance currently in place for the project
0245:             *         instance.
0246:             */
0247:            public InputHandler getInputHandler() {
0248:                return inputHandler;
0249:            }
0250:
0251:            /**
0252:             * Create a new Ant project.
0253:             */
0254:            public Project() {
0255:                inputHandler = new DefaultInputHandler();
0256:            }
0257:
0258:            /**
0259:             * Create and initialize a subproject. By default the subproject will be of
0260:             * the same type as its parent. If a no-arg constructor is unavailable, the
0261:             * <code>Project</code> class will be used.
0262:             * @return a Project instance configured as a subproject of this Project.
0263:             * @since Ant 1.7
0264:             */
0265:            public Project createSubProject() {
0266:                Project subProject = null;
0267:                try {
0268:                    subProject = (Project) (getClass().newInstance());
0269:                } catch (Exception e) {
0270:                    subProject = new Project();
0271:                }
0272:                initSubProject(subProject);
0273:                return subProject;
0274:            }
0275:
0276:            /**
0277:             * Initialize a subproject.
0278:             * @param subProject the subproject to initialize.
0279:             */
0280:            public void initSubProject(Project subProject) {
0281:                ComponentHelper.getComponentHelper(subProject).initSubProject(
0282:                        ComponentHelper.getComponentHelper(this ));
0283:                subProject.setDefaultInputStream(getDefaultInputStream());
0284:                subProject.setKeepGoingMode(this .isKeepGoingMode());
0285:                subProject.setExecutor(getExecutor().getSubProjectExecutor());
0286:            }
0287:
0288:            /**
0289:             * Initialise the project.
0290:             *
0291:             * This involves setting the default task definitions and loading the
0292:             * system properties.
0293:             *
0294:             * @exception BuildException if the default task list cannot be loaded.
0295:             */
0296:            public void init() throws BuildException {
0297:                initProperties();
0298:
0299:                ComponentHelper.getComponentHelper(this )
0300:                        .initDefaultDefinitions();
0301:            }
0302:
0303:            /**
0304:             * Initializes the properties.
0305:             * @exception BuildException if an vital property could not be set.
0306:             * @since Ant 1.7
0307:             */
0308:            public void initProperties() throws BuildException {
0309:                setJavaVersionProperty();
0310:                setSystemProperties();
0311:                setPropertyInternal(MagicNames.ANT_VERSION, Main
0312:                        .getAntVersion());
0313:                setAntLib();
0314:            }
0315:
0316:            private void setAntLib() {
0317:                File antlib = org.apache.tools.ant.launch.Locator
0318:                        .getClassSource(Project.class);
0319:                if (antlib != null) {
0320:                    setPropertyInternal(MagicNames.ANT_LIB, antlib
0321:                            .getAbsolutePath());
0322:                }
0323:            }
0324:
0325:            /**
0326:             * Factory method to create a class loader for loading classes from
0327:             * a given path.
0328:             *
0329:             * @param path the path from which classes are to be loaded.
0330:             *
0331:             * @return an appropriate classloader.
0332:             */
0333:            public AntClassLoader createClassLoader(Path path) {
0334:                return new AntClassLoader(getClass().getClassLoader(), this ,
0335:                        path);
0336:            }
0337:
0338:            /**
0339:             * Factory method to create a class loader for loading classes from
0340:             * a given path.
0341:             *
0342:             * @param parent the parent classloader for the new loader.
0343:             * @param path the path from which classes are to be loaded.
0344:             *
0345:             * @return an appropriate classloader.
0346:             */
0347:            public AntClassLoader createClassLoader(ClassLoader parent,
0348:                    Path path) {
0349:                return new AntClassLoader(parent, this , path);
0350:            }
0351:
0352:            /**
0353:             * Set the core classloader for the project. If a <code>null</code>
0354:             * classloader is specified, the parent classloader should be used.
0355:             *
0356:             * @param coreLoader The classloader to use for the project.
0357:             *                   May be <code>null</code>.
0358:             */
0359:            public void setCoreLoader(ClassLoader coreLoader) {
0360:                this .coreLoader = coreLoader;
0361:            }
0362:
0363:            /**
0364:             * Return the core classloader to use for this project.
0365:             * This may be <code>null</code>, indicating that
0366:             * the parent classloader should be used.
0367:             *
0368:             * @return the core classloader to use for this project.
0369:             *
0370:             */
0371:            public ClassLoader getCoreLoader() {
0372:                return coreLoader;
0373:            }
0374:
0375:            /**
0376:             * Add a build listener to the list. This listener will
0377:             * be notified of build events for this project.
0378:             *
0379:             * @param listener The listener to add to the list.
0380:             *                 Must not be <code>null</code>.
0381:             */
0382:            public synchronized void addBuildListener(BuildListener listener) {
0383:                // If the listeners already has this listener, do nothing
0384:                if (listeners.contains(listener)) {
0385:                    return;
0386:                }
0387:                // create a new Vector to avoid ConcurrentModificationExc when
0388:                // the listeners get added/removed while we are in fire
0389:                Vector newListeners = getBuildListeners();
0390:                newListeners.addElement(listener);
0391:                listeners = newListeners;
0392:            }
0393:
0394:            /**
0395:             * Remove a build listener from the list. This listener
0396:             * will no longer be notified of build events for this project.
0397:             *
0398:             * @param listener The listener to remove from the list.
0399:             *                 Should not be <code>null</code>.
0400:             */
0401:            public synchronized void removeBuildListener(BuildListener listener) {
0402:                // create a new Vector to avoid ConcurrentModificationExc when
0403:                // the listeners get added/removed while we are in fire
0404:                Vector newListeners = getBuildListeners();
0405:                newListeners.removeElement(listener);
0406:                listeners = newListeners;
0407:            }
0408:
0409:            /**
0410:             * Return a copy of the list of build listeners for the project.
0411:             *
0412:             * @return a list of build listeners for the project
0413:             */
0414:            public Vector getBuildListeners() {
0415:                return (Vector) listeners.clone();
0416:            }
0417:
0418:            /**
0419:             * Write a message to the log with the default log level
0420:             * of MSG_INFO .
0421:             * @param message The text to log. Should not be <code>null</code>.
0422:             */
0423:
0424:            public void log(String message) {
0425:                log(message, MSG_INFO);
0426:            }
0427:
0428:            /**
0429:             * Write a project level message to the log with the given log level.
0430:             * @param message The text to log. Should not be <code>null</code>.
0431:             * @param msgLevel The log priority level to use.
0432:             */
0433:            public void log(String message, int msgLevel) {
0434:                log(message, null, msgLevel);
0435:            }
0436:
0437:            /**
0438:             * Write a project level message to the log with the given log level.
0439:             * @param message The text to log. Should not be <code>null</code>.
0440:             * @param throwable The exception causing this log, may be <code>null</code>.
0441:             * @param msgLevel The log priority level to use.
0442:             * @since 1.7
0443:             */
0444:            public void log(String message, Throwable throwable, int msgLevel) {
0445:                fireMessageLogged(this , message, throwable, msgLevel);
0446:            }
0447:
0448:            /**
0449:             * Write a task level message to the log with the given log level.
0450:             * @param task The task to use in the log. Must not be <code>null</code>.
0451:             * @param message The text to log. Should not be <code>null</code>.
0452:             * @param msgLevel The log priority level to use.
0453:             */
0454:            public void log(Task task, String message, int msgLevel) {
0455:                fireMessageLogged(task, message, null, msgLevel);
0456:            }
0457:
0458:            /**
0459:             * Write a task level message to the log with the given log level.
0460:             * @param task The task to use in the log. Must not be <code>null</code>.
0461:             * @param message The text to log. Should not be <code>null</code>.
0462:             * @param throwable The exception causing this log, may be <code>null</code>.
0463:             * @param msgLevel The log priority level to use.
0464:             * @since 1.7
0465:             */
0466:            public void log(Task task, String message, Throwable throwable,
0467:                    int msgLevel) {
0468:                fireMessageLogged(task, message, throwable, msgLevel);
0469:            }
0470:
0471:            /**
0472:             * Write a target level message to the log with the given log level.
0473:             * @param target The target to use in the log.
0474:             *               Must not be <code>null</code>.
0475:             * @param message The text to log. Should not be <code>null</code>.
0476:             * @param msgLevel The log priority level to use.
0477:             */
0478:            public void log(Target target, String message, int msgLevel) {
0479:                log(target, message, null, msgLevel);
0480:            }
0481:
0482:            /**
0483:             * Write a target level message to the log with the given log level.
0484:             * @param target The target to use in the log.
0485:             *               Must not be <code>null</code>.
0486:             * @param message The text to log. Should not be <code>null</code>.
0487:             * @param throwable The exception causing this log, may be <code>null</code>.
0488:             * @param msgLevel The log priority level to use.
0489:             * @since 1.7
0490:             */
0491:            public void log(Target target, String message, Throwable throwable,
0492:                    int msgLevel) {
0493:                fireMessageLogged(target, message, throwable, msgLevel);
0494:            }
0495:
0496:            /**
0497:             * Return the set of global filters.
0498:             *
0499:             * @return the set of global filters.
0500:             */
0501:            public FilterSet getGlobalFilterSet() {
0502:                return globalFilterSet;
0503:            }
0504:
0505:            /**
0506:             * Set a property. Any existing property of the same name
0507:             * is overwritten, unless it is a user property.
0508:             * @param name The name of property to set.
0509:             *             Must not be <code>null</code>.
0510:             * @param value The new value of the property.
0511:             *              Must not be <code>null</code>.
0512:             */
0513:            public void setProperty(String name, String value) {
0514:                PropertyHelper.getPropertyHelper(this ).setProperty(null, name,
0515:                        value, true);
0516:            }
0517:
0518:            /**
0519:             * Set a property if no value currently exists. If the property
0520:             * exists already, a message is logged and the method returns with
0521:             * no other effect.
0522:             *
0523:             * @param name The name of property to set.
0524:             *             Must not be <code>null</code>.
0525:             * @param value The new value of the property.
0526:             *              Must not be <code>null</code>.
0527:             * @since 1.5
0528:             */
0529:            public void setNewProperty(String name, String value) {
0530:                PropertyHelper.getPropertyHelper(this ).setNewProperty(null,
0531:                        name, value);
0532:            }
0533:
0534:            /**
0535:             * Set a user property, which cannot be overwritten by
0536:             * set/unset property calls. Any previous value is overwritten.
0537:             * @param name The name of property to set.
0538:             *             Must not be <code>null</code>.
0539:             * @param value The new value of the property.
0540:             *              Must not be <code>null</code>.
0541:             * @see #setProperty(String,String)
0542:             */
0543:            public void setUserProperty(String name, String value) {
0544:                PropertyHelper.getPropertyHelper(this ).setUserProperty(null,
0545:                        name, value);
0546:            }
0547:
0548:            /**
0549:             * Set a user property, which cannot be overwritten by set/unset
0550:             * property calls. Any previous value is overwritten. Also marks
0551:             * these properties as properties that have not come from the
0552:             * command line.
0553:             *
0554:             * @param name The name of property to set.
0555:             *             Must not be <code>null</code>.
0556:             * @param value The new value of the property.
0557:             *              Must not be <code>null</code>.
0558:             * @see #setProperty(String,String)
0559:             */
0560:            public void setInheritedProperty(String name, String value) {
0561:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0562:                ph.setInheritedProperty(null, name, value);
0563:            }
0564:
0565:            /**
0566:             * Set a property unless it is already defined as a user property
0567:             * (in which case the method returns silently).
0568:             *
0569:             * @param name The name of the property.
0570:             *             Must not be <code>null</code>.
0571:             * @param value The property value. Must not be <code>null</code>.
0572:             */
0573:            private void setPropertyInternal(String name, String value) {
0574:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0575:                ph.setProperty(null, name, value, false);
0576:            }
0577:
0578:            /**
0579:             * Return the value of a property, if it is set.
0580:             *
0581:             * @param propertyName The name of the property.
0582:             *             May be <code>null</code>, in which case
0583:             *             the return value is also <code>null</code>.
0584:             * @return the property value, or <code>null</code> for no match
0585:             *         or if a <code>null</code> name is provided.
0586:             */
0587:            public String getProperty(String propertyName) {
0588:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0589:                return (String) ph.getProperty(null, propertyName);
0590:            }
0591:
0592:            /**
0593:             * Replace ${} style constructions in the given value with the
0594:             * string value of the corresponding data types.
0595:             *
0596:             * @param value The string to be scanned for property references.
0597:             *              May be <code>null</code>.
0598:             *
0599:             * @return the given string with embedded property names replaced
0600:             *         by values, or <code>null</code> if the given string is
0601:             *         <code>null</code>.
0602:             *
0603:             * @exception BuildException if the given value has an unclosed
0604:             *                           property name, e.g. <code>${xxx</code>.
0605:             */
0606:            public String replaceProperties(String value) throws BuildException {
0607:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0608:                return ph.replaceProperties(null, value, null);
0609:            }
0610:
0611:            /**
0612:             * Return the value of a user property, if it is set.
0613:             *
0614:             * @param propertyName The name of the property.
0615:             *             May be <code>null</code>, in which case
0616:             *             the return value is also <code>null</code>.
0617:             * @return the property value, or <code>null</code> for no match
0618:             *         or if a <code>null</code> name is provided.
0619:             */
0620:            public String getUserProperty(String propertyName) {
0621:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0622:                return (String) ph.getUserProperty(null, propertyName);
0623:            }
0624:
0625:            /**
0626:             * Return a copy of the properties table.
0627:             * @return a hashtable containing all properties
0628:             *         (including user properties).
0629:             */
0630:            public Hashtable getProperties() {
0631:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0632:                return ph.getProperties();
0633:            }
0634:
0635:            /**
0636:             * Return a copy of the user property hashtable.
0637:             * @return a hashtable containing just the user properties.
0638:             */
0639:            public Hashtable getUserProperties() {
0640:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0641:                return ph.getUserProperties();
0642:            }
0643:
0644:            /**
0645:             * Copy all user properties that have been set on the command
0646:             * line or a GUI tool from this instance to the Project instance
0647:             * given as the argument.
0648:             *
0649:             * <p>To copy all &quot;user&quot; properties, you will also have to call
0650:             * {@link #copyInheritedProperties copyInheritedProperties}.</p>
0651:             *
0652:             * @param other the project to copy the properties to.  Must not be null.
0653:             *
0654:             * @since Ant 1.5
0655:             */
0656:            public void copyUserProperties(Project other) {
0657:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0658:                ph.copyUserProperties(other);
0659:            }
0660:
0661:            /**
0662:             * Copy all user properties that have not been set on the
0663:             * command line or a GUI tool from this instance to the Project
0664:             * instance given as the argument.
0665:             *
0666:             * <p>To copy all &quot;user&quot; properties, you will also have to call
0667:             * {@link #copyUserProperties copyUserProperties}.</p>
0668:             *
0669:             * @param other the project to copy the properties to.  Must not be null.
0670:             *
0671:             * @since Ant 1.5
0672:             */
0673:            public void copyInheritedProperties(Project other) {
0674:                PropertyHelper ph = PropertyHelper.getPropertyHelper(this );
0675:                ph.copyInheritedProperties(other);
0676:            }
0677:
0678:            /**
0679:             * Set the default target of the project.
0680:             *
0681:             * @param defaultTarget The name of the default target for this project.
0682:             *                      May be <code>null</code>, indicating that there is
0683:             *                      no default target.
0684:             *
0685:             * @deprecated since 1.5.x.
0686:             *             Use setDefault.
0687:             * @see #setDefault(String)
0688:             */
0689:            public void setDefaultTarget(String defaultTarget) {
0690:                this .defaultTarget = defaultTarget;
0691:            }
0692:
0693:            /**
0694:             * Return the name of the default target of the project.
0695:             * @return name of the default target or
0696:             *         <code>null</code> if no default has been set.
0697:             */
0698:            public String getDefaultTarget() {
0699:                return defaultTarget;
0700:            }
0701:
0702:            /**
0703:             * Set the default target of the project.
0704:             *
0705:             * @param defaultTarget The name of the default target for this project.
0706:             *                      May be <code>null</code>, indicating that there is
0707:             *                      no default target.
0708:             */
0709:            public void setDefault(String defaultTarget) {
0710:                this .defaultTarget = defaultTarget;
0711:            }
0712:
0713:            /**
0714:             * Set the name of the project, also setting the user
0715:             * property <code>ant.project.name</code>.
0716:             *
0717:             * @param name The name of the project.
0718:             *             Must not be <code>null</code>.
0719:             */
0720:            public void setName(String name) {
0721:                setUserProperty("ant.project.name", name);
0722:                this .name = name;
0723:            }
0724:
0725:            /**
0726:             * Return the project name, if one has been set.
0727:             *
0728:             * @return the project name, or <code>null</code> if it hasn't been set.
0729:             */
0730:            public String getName() {
0731:                return name;
0732:            }
0733:
0734:            /**
0735:             * Set the project description.
0736:             *
0737:             * @param description The description of the project.
0738:             *                    May be <code>null</code>.
0739:             */
0740:            public void setDescription(String description) {
0741:                this .description = description;
0742:            }
0743:
0744:            /**
0745:             * Return the project description, if one has been set.
0746:             *
0747:             * @return the project description, or <code>null</code> if it hasn't
0748:             *         been set.
0749:             */
0750:            public String getDescription() {
0751:                if (description == null) {
0752:                    description = Description.getDescription(this );
0753:                }
0754:                return description;
0755:            }
0756:
0757:            /**
0758:             * Add a filter to the set of global filters.
0759:             *
0760:             * @param token The token to filter.
0761:             *              Must not be <code>null</code>.
0762:             * @param value The replacement value.
0763:             *              Must not be <code>null</code>.
0764:             * @deprecated since 1.4.x.
0765:             *             Use getGlobalFilterSet().addFilter(token,value)
0766:             *
0767:             * @see #getGlobalFilterSet()
0768:             * @see FilterSet#addFilter(String,String)
0769:             */
0770:            public void addFilter(String token, String value) {
0771:                if (token == null) {
0772:                    return;
0773:                }
0774:                globalFilterSet.addFilter(new FilterSet.Filter(token, value));
0775:            }
0776:
0777:            /**
0778:             * Return a hashtable of global filters, mapping tokens to values.
0779:             *
0780:             * @return a hashtable of global filters, mapping tokens to values
0781:             *         (String to String).
0782:             *
0783:             * @deprecated since 1.4.x
0784:             *             Use getGlobalFilterSet().getFilterHash().
0785:             *
0786:             * @see #getGlobalFilterSet()
0787:             * @see FilterSet#getFilterHash()
0788:             */
0789:            public Hashtable getFilters() {
0790:                // we need to build the hashtable dynamically
0791:                return globalFilterSet.getFilterHash();
0792:            }
0793:
0794:            /**
0795:             * Set the base directory for the project, checking that
0796:             * the given filename exists and is a directory.
0797:             *
0798:             * @param baseD The project base directory.
0799:             *              Must not be <code>null</code>.
0800:             *
0801:             * @exception BuildException if the directory if invalid.
0802:             */
0803:            public void setBasedir(String baseD) throws BuildException {
0804:                setBaseDir(new File(baseD));
0805:            }
0806:
0807:            /**
0808:             * Set the base directory for the project, checking that
0809:             * the given file exists and is a directory.
0810:             *
0811:             * @param baseDir The project base directory.
0812:             *                Must not be <code>null</code>.
0813:             * @exception BuildException if the specified file doesn't exist or
0814:             *                           isn't a directory.
0815:             */
0816:            public void setBaseDir(File baseDir) throws BuildException {
0817:                baseDir = FILE_UTILS.normalize(baseDir.getAbsolutePath());
0818:                if (!baseDir.exists()) {
0819:                    throw new BuildException("Basedir "
0820:                            + baseDir.getAbsolutePath() + " does not exist");
0821:                }
0822:                if (!baseDir.isDirectory()) {
0823:                    throw new BuildException("Basedir "
0824:                            + baseDir.getAbsolutePath() + " is not a directory");
0825:                }
0826:                this .baseDir = baseDir;
0827:                setPropertyInternal(MagicNames.PROJECT_BASEDIR, this .baseDir
0828:                        .getPath());
0829:                String msg = "Project base dir set to: " + this .baseDir;
0830:                log(msg, MSG_VERBOSE);
0831:            }
0832:
0833:            /**
0834:             * Return the base directory of the project as a file object.
0835:             *
0836:             * @return the project base directory, or <code>null</code> if the
0837:             *         base directory has not been successfully set to a valid value.
0838:             */
0839:            public File getBaseDir() {
0840:                if (baseDir == null) {
0841:                    try {
0842:                        setBasedir(".");
0843:                    } catch (BuildException ex) {
0844:                        ex.printStackTrace();
0845:                    }
0846:                }
0847:                return baseDir;
0848:            }
0849:
0850:            /**
0851:             * Set &quot;keep-going&quot; mode. In this mode Ant will try to execute
0852:             * as many targets as possible. All targets that do not depend
0853:             * on failed target(s) will be executed.  If the keepGoing settor/getter
0854:             * methods are used in conjunction with the <code>ant.executor.class</code>
0855:             * property, they will have no effect.
0856:             * @param keepGoingMode &quot;keep-going&quot; mode
0857:             * @since Ant 1.6
0858:             */
0859:            public void setKeepGoingMode(boolean keepGoingMode) {
0860:                this .keepGoingMode = keepGoingMode;
0861:            }
0862:
0863:            /**
0864:             * Return the keep-going mode.  If the keepGoing settor/getter
0865:             * methods are used in conjunction with the <code>ant.executor.class</code>
0866:             * property, they will have no effect.
0867:             * @return &quot;keep-going&quot; mode
0868:             * @since Ant 1.6
0869:             */
0870:            public boolean isKeepGoingMode() {
0871:                return this .keepGoingMode;
0872:            }
0873:
0874:            /**
0875:             * Return the version of Java this class is running under.
0876:             * @return the version of Java as a String, e.g. "1.1" .
0877:             * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
0878:             * @deprecated since 1.5.x.
0879:             *             Use org.apache.tools.ant.util.JavaEnvUtils instead.
0880:             */
0881:            public static String getJavaVersion() {
0882:                return JavaEnvUtils.getJavaVersion();
0883:            }
0884:
0885:            /**
0886:             * Set the <code>ant.java.version</code> property and tests for
0887:             * unsupported JVM versions. If the version is supported,
0888:             * verbose log messages are generated to record the Java version
0889:             * and operating system name.
0890:             *
0891:             * @exception BuildException if this Java version is not supported.
0892:             *
0893:             * @see org.apache.tools.ant.util.JavaEnvUtils#getJavaVersion
0894:             */
0895:            public void setJavaVersionProperty() throws BuildException {
0896:                String javaVersion = JavaEnvUtils.getJavaVersion();
0897:                setPropertyInternal(MagicNames.ANT_JAVA_VERSION, javaVersion);
0898:
0899:                // sanity check
0900:                if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_0)
0901:                        || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
0902:                    throw new BuildException(
0903:                            "Ant cannot work on Java 1.0 / 1.1");
0904:                }
0905:                log("Detected Java version: " + javaVersion + " in: "
0906:                        + System.getProperty("java.home"), MSG_VERBOSE);
0907:
0908:                log("Detected OS: " + System.getProperty("os.name"),
0909:                        MSG_VERBOSE);
0910:            }
0911:
0912:            /**
0913:             * Add all system properties which aren't already defined as
0914:             * user properties to the project properties.
0915:             */
0916:            public void setSystemProperties() {
0917:                Properties systemP = System.getProperties();
0918:                Enumeration e = systemP.propertyNames();
0919:                while (e.hasMoreElements()) {
0920:                    String propertyName = (String) e.nextElement();
0921:                    String value = systemP.getProperty(propertyName);
0922:                    this .setPropertyInternal(propertyName, value);
0923:                }
0924:            }
0925:
0926:            /**
0927:             * Add a new task definition to the project.
0928:             * Attempting to override an existing definition with an
0929:             * equivalent one (i.e. with the same classname) results in
0930:             * a verbose log message. Attempting to override an existing definition
0931:             * with a different one results in a warning log message and
0932:             * invalidates any tasks which have already been created with the
0933:             * old definition.
0934:             *
0935:             * @param taskName The name of the task to add.
0936:             *                 Must not be <code>null</code>.
0937:             * @param taskClass The full name of the class implementing the task.
0938:             *                  Must not be <code>null</code>.
0939:             *
0940:             * @exception BuildException if the class is unsuitable for being an Ant
0941:             *                           task. An error level message is logged before
0942:             *                           this exception is thrown.
0943:             *
0944:             * @see #checkTaskClass(Class)
0945:             */
0946:            public void addTaskDefinition(String taskName, Class taskClass)
0947:                    throws BuildException {
0948:                ComponentHelper.getComponentHelper(this ).addTaskDefinition(
0949:                        taskName, taskClass);
0950:            }
0951:
0952:            /**
0953:             * Check whether or not a class is suitable for serving as Ant task.
0954:             * Ant task implementation classes must be public, concrete, and have
0955:             * a no-arg constructor.
0956:             *
0957:             * @param taskClass The class to be checked.
0958:             *                  Must not be <code>null</code>.
0959:             *
0960:             * @exception BuildException if the class is unsuitable for being an Ant
0961:             *                           task. An error level message is logged before
0962:             *                           this exception is thrown.
0963:             */
0964:            public void checkTaskClass(final Class taskClass)
0965:                    throws BuildException {
0966:                ComponentHelper.getComponentHelper(this ).checkTaskClass(
0967:                        taskClass);
0968:
0969:                if (!Modifier.isPublic(taskClass.getModifiers())) {
0970:                    final String message = taskClass + " is not public";
0971:                    log(message, Project.MSG_ERR);
0972:                    throw new BuildException(message);
0973:                }
0974:                if (Modifier.isAbstract(taskClass.getModifiers())) {
0975:                    final String message = taskClass + " is abstract";
0976:                    log(message, Project.MSG_ERR);
0977:                    throw new BuildException(message);
0978:                }
0979:                try {
0980:                    taskClass.getConstructor((Class[]) null);
0981:                    // don't have to check for public, since
0982:                    // getConstructor finds public constructors only.
0983:                } catch (NoSuchMethodException e) {
0984:                    final String message = "No public no-arg constructor in "
0985:                            + taskClass;
0986:                    log(message, Project.MSG_ERR);
0987:                    throw new BuildException(message);
0988:                } catch (LinkageError e) {
0989:                    String message = "Could not load " + taskClass + ": " + e;
0990:                    log(message, Project.MSG_ERR);
0991:                    throw new BuildException(message, e);
0992:                }
0993:                if (!Task.class.isAssignableFrom(taskClass)) {
0994:                    TaskAdapter.checkTaskClass(taskClass, this );
0995:                }
0996:            }
0997:
0998:            /**
0999:             * Return the current task definition hashtable. The returned hashtable is
1000:             * &quot;live&quot; and so should not be modified.
1001:             *
1002:             * @return a map of from task name to implementing class
1003:             *         (String to Class).
1004:             */
1005:            public Hashtable getTaskDefinitions() {
1006:                return ComponentHelper.getComponentHelper(this )
1007:                        .getTaskDefinitions();
1008:            }
1009:
1010:            /**
1011:             * Add a new datatype definition.
1012:             * Attempting to override an existing definition with an
1013:             * equivalent one (i.e. with the same classname) results in
1014:             * a verbose log message. Attempting to override an existing definition
1015:             * with a different one results in a warning log message, but the
1016:             * definition is changed.
1017:             *
1018:             * @param typeName The name of the datatype.
1019:             *                 Must not be <code>null</code>.
1020:             * @param typeClass The full name of the class implementing the datatype.
1021:             *                  Must not be <code>null</code>.
1022:             */
1023:            public void addDataTypeDefinition(String typeName, Class typeClass) {
1024:                ComponentHelper.getComponentHelper(this ).addDataTypeDefinition(
1025:                        typeName, typeClass);
1026:            }
1027:
1028:            /**
1029:             * Return the current datatype definition hashtable. The returned
1030:             * hashtable is &quot;live&quot; and so should not be modified.
1031:             *
1032:             * @return a map of from datatype name to implementing class
1033:             *         (String to Class).
1034:             */
1035:            public Hashtable getDataTypeDefinitions() {
1036:                return ComponentHelper.getComponentHelper(this )
1037:                        .getDataTypeDefinitions();
1038:            }
1039:
1040:            /**
1041:             * Add a <em>new</em> target to the project.
1042:             *
1043:             * @param target The target to be added to the project.
1044:             *               Must not be <code>null</code>.
1045:             *
1046:             * @exception BuildException if the target already exists in the project
1047:             *
1048:             * @see Project#addOrReplaceTarget(Target)
1049:             */
1050:            public void addTarget(Target target) throws BuildException {
1051:                addTarget(target.getName(), target);
1052:            }
1053:
1054:            /**
1055:             * Add a <em>new</em> target to the project.
1056:             *
1057:             * @param targetName The name to use for the target.
1058:             *             Must not be <code>null</code>.
1059:             * @param target The target to be added to the project.
1060:             *               Must not be <code>null</code>.
1061:             *
1062:             * @exception BuildException if the target already exists in the project.
1063:             *
1064:             * @see Project#addOrReplaceTarget(String, Target)
1065:             */
1066:            public void addTarget(String targetName, Target target)
1067:                    throws BuildException {
1068:                if (targets.get(targetName) != null) {
1069:                    throw new BuildException("Duplicate target: `" + targetName
1070:                            + "'");
1071:                }
1072:                addOrReplaceTarget(targetName, target);
1073:            }
1074:
1075:            /**
1076:             * Add a target to the project, or replaces one with the same
1077:             * name.
1078:             *
1079:             * @param target The target to be added or replaced in the project.
1080:             *               Must not be <code>null</code>.
1081:             */
1082:            public void addOrReplaceTarget(Target target) {
1083:                addOrReplaceTarget(target.getName(), target);
1084:            }
1085:
1086:            /**
1087:             * Add a target to the project, or replaces one with the same
1088:             * name.
1089:             *
1090:             * @param targetName The name to use for the target.
1091:             *                   Must not be <code>null</code>.
1092:             * @param target The target to be added or replaced in the project.
1093:             *               Must not be <code>null</code>.
1094:             */
1095:            public void addOrReplaceTarget(String targetName, Target target) {
1096:                String msg = " +Target: " + targetName;
1097:                log(msg, MSG_DEBUG);
1098:                target.setProject(this );
1099:                targets.put(targetName, target);
1100:            }
1101:
1102:            /**
1103:             * Return the hashtable of targets. The returned hashtable
1104:             * is &quot;live&quot; and so should not be modified.
1105:             * @return a map from name to target (String to Target).
1106:             */
1107:            public Hashtable getTargets() {
1108:                return targets;
1109:            }
1110:
1111:            /**
1112:             * Create a new instance of a task, adding it to a list of
1113:             * created tasks for later invalidation. This causes all tasks
1114:             * to be remembered until the containing project is removed
1115:             * @param taskType The name of the task to create an instance of.
1116:             *                 Must not be <code>null</code>.
1117:             *
1118:             * @return an instance of the specified task, or <code>null</code> if
1119:             *         the task name is not recognised.
1120:             *
1121:             * @exception BuildException if the task name is recognised but task
1122:             *                           creation fails.
1123:             */
1124:            public Task createTask(String taskType) throws BuildException {
1125:                return ComponentHelper.getComponentHelper(this ).createTask(
1126:                        taskType);
1127:            }
1128:
1129:            /**
1130:             * Create a new instance of a data type.
1131:             *
1132:             * @param typeName The name of the data type to create an instance of.
1133:             *                 Must not be <code>null</code>.
1134:             *
1135:             * @return an instance of the specified data type, or <code>null</code> if
1136:             *         the data type name is not recognised.
1137:             *
1138:             * @exception BuildException if the data type name is recognised but
1139:             *                           instance creation fails.
1140:             */
1141:            public Object createDataType(String typeName) throws BuildException {
1142:                return ComponentHelper.getComponentHelper(this ).createDataType(
1143:                        typeName);
1144:            }
1145:
1146:            /**
1147:             * Set the Executor instance for this Project.
1148:             * @param e the Executor to use.
1149:             */
1150:            public void setExecutor(Executor e) {
1151:                addReference(MagicNames.ANT_EXECUTOR_REFERENCE, e);
1152:            }
1153:
1154:            /**
1155:             * Get this Project's Executor (setting it if necessary).
1156:             * @return an Executor instance.
1157:             */
1158:            public Executor getExecutor() {
1159:                Object o = getReference(MagicNames.ANT_EXECUTOR_REFERENCE);
1160:                if (o == null) {
1161:                    String classname = getProperty(MagicNames.ANT_EXECUTOR_CLASSNAME);
1162:                    if (classname == null) {
1163:                        classname = DefaultExecutor.class.getName();
1164:                    }
1165:                    log("Attempting to create object of type " + classname,
1166:                            MSG_DEBUG);
1167:                    try {
1168:                        o = Class.forName(classname, true, coreLoader)
1169:                                .newInstance();
1170:                    } catch (ClassNotFoundException seaEnEfEx) {
1171:                        //try the current classloader
1172:                        try {
1173:                            o = Class.forName(classname).newInstance();
1174:                        } catch (Exception ex) {
1175:                            log(ex.toString(), MSG_ERR);
1176:                        }
1177:                    } catch (Exception ex) {
1178:                        log(ex.toString(), MSG_ERR);
1179:                    }
1180:                    if (o == null) {
1181:                        throw new BuildException(
1182:                                "Unable to obtain a Target Executor instance.");
1183:                    }
1184:                    setExecutor((Executor) o);
1185:                }
1186:                return (Executor) o;
1187:            }
1188:
1189:            /**
1190:             * Execute the specified sequence of targets, and the targets
1191:             * they depend on.
1192:             *
1193:             * @param names A vector of target name strings to execute.
1194:             *              Must not be <code>null</code>.
1195:             *
1196:             * @exception BuildException if the build failed.
1197:             */
1198:            public void executeTargets(Vector names) throws BuildException {
1199:                getExecutor().executeTargets(this ,
1200:                        (String[]) (names.toArray(new String[names.size()])));
1201:            }
1202:
1203:            /**
1204:             * Demultiplex output so that each task receives the appropriate
1205:             * messages. If the current thread is not currently executing a task,
1206:             * the message is logged directly.
1207:             *
1208:             * @param output Message to handle. Should not be <code>null</code>.
1209:             * @param isWarning Whether the text represents an warning (<code>true</code>)
1210:             *        or information (<code>false</code>).
1211:             */
1212:            public void demuxOutput(String output, boolean isWarning) {
1213:                Task task = getThreadTask(Thread.currentThread());
1214:                if (task == null) {
1215:                    log(output, isWarning ? MSG_WARN : MSG_INFO);
1216:                } else {
1217:                    if (isWarning) {
1218:                        task.handleErrorOutput(output);
1219:                    } else {
1220:                        task.handleOutput(output);
1221:                    }
1222:                }
1223:            }
1224:
1225:            /**
1226:             * Read data from the default input stream. If no default has been
1227:             * specified, System.in is used.
1228:             *
1229:             * @param buffer the buffer into which data is to be read.
1230:             * @param offset the offset into the buffer at which data is stored.
1231:             * @param length the amount of data to read.
1232:             *
1233:             * @return the number of bytes read.
1234:             *
1235:             * @exception IOException if the data cannot be read.
1236:             * @since Ant 1.6
1237:             */
1238:            public int defaultInput(byte[] buffer, int offset, int length)
1239:                    throws IOException {
1240:                if (defaultInputStream != null) {
1241:                    System.out.flush();
1242:                    return defaultInputStream.read(buffer, offset, length);
1243:                } else {
1244:                    throw new EOFException("No input provided for project");
1245:                }
1246:            }
1247:
1248:            /**
1249:             * Demux an input request to the correct task.
1250:             *
1251:             * @param buffer the buffer into which data is to be read.
1252:             * @param offset the offset into the buffer at which data is stored.
1253:             * @param length the amount of data to read.
1254:             *
1255:             * @return the number of bytes read.
1256:             *
1257:             * @exception IOException if the data cannot be read.
1258:             * @since Ant 1.6
1259:             */
1260:            public int demuxInput(byte[] buffer, int offset, int length)
1261:                    throws IOException {
1262:                Task task = getThreadTask(Thread.currentThread());
1263:                if (task == null) {
1264:                    return defaultInput(buffer, offset, length);
1265:                } else {
1266:                    return task.handleInput(buffer, offset, length);
1267:                }
1268:            }
1269:
1270:            /**
1271:             * Demultiplex flush operations so that each task receives the appropriate
1272:             * messages. If the current thread is not currently executing a task,
1273:             * the message is logged directly.
1274:             *
1275:             * @since Ant 1.5.2
1276:             *
1277:             * @param output Message to handle. Should not be <code>null</code>.
1278:             * @param isError Whether the text represents an error (<code>true</code>)
1279:             *        or information (<code>false</code>).
1280:             */
1281:            public void demuxFlush(String output, boolean isError) {
1282:                Task task = getThreadTask(Thread.currentThread());
1283:                if (task == null) {
1284:                    fireMessageLogged(this , output, isError ? MSG_ERR
1285:                            : MSG_INFO);
1286:                } else {
1287:                    if (isError) {
1288:                        task.handleErrorFlush(output);
1289:                    } else {
1290:                        task.handleFlush(output);
1291:                    }
1292:                }
1293:            }
1294:
1295:            /**
1296:             * Execute the specified target and any targets it depends on.
1297:             *
1298:             * @param targetName The name of the target to execute.
1299:             *                   Must not be <code>null</code>.
1300:             *
1301:             * @exception BuildException if the build failed.
1302:             */
1303:            public void executeTarget(String targetName) throws BuildException {
1304:
1305:                // sanity check ourselves, if we've been asked to build nothing
1306:                // then we should complain
1307:
1308:                if (targetName == null) {
1309:                    String msg = "No target specified";
1310:                    throw new BuildException(msg);
1311:                }
1312:
1313:                // Sort and run the dependency tree.
1314:                // Sorting checks if all the targets (and dependencies)
1315:                // exist, and if there is any cycle in the dependency
1316:                // graph.
1317:                executeSortedTargets(topoSort(targetName, targets, false));
1318:            }
1319:
1320:            /**
1321:             * Execute a <code>Vector</code> of sorted targets.
1322:             * @param sortedTargets   the aforementioned <code>Vector</code>.
1323:             * @throws BuildException on error.
1324:             */
1325:            public void executeSortedTargets(Vector sortedTargets)
1326:                    throws BuildException {
1327:                Set succeededTargets = new HashSet();
1328:                BuildException buildException = null; // first build exception
1329:                for (Enumeration iter = sortedTargets.elements(); iter
1330:                        .hasMoreElements();) {
1331:                    Target curtarget = (Target) iter.nextElement();
1332:                    boolean canExecute = true;
1333:                    for (Enumeration depIter = curtarget.getDependencies(); depIter
1334:                            .hasMoreElements();) {
1335:                        String dependencyName = ((String) depIter.nextElement());
1336:                        if (!succeededTargets.contains(dependencyName)) {
1337:                            canExecute = false;
1338:                            log(curtarget, "Cannot execute '"
1339:                                    + curtarget.getName() + "' - '"
1340:                                    + dependencyName
1341:                                    + "' failed or was not executed.", MSG_ERR);
1342:                            break;
1343:                        }
1344:                    }
1345:                    if (canExecute) {
1346:                        Throwable thrownException = null;
1347:                        try {
1348:                            curtarget.performTasks();
1349:                            succeededTargets.add(curtarget.getName());
1350:                        } catch (RuntimeException ex) {
1351:                            if (!(keepGoingMode)) {
1352:                                throw ex; // throw further
1353:                            }
1354:                            thrownException = ex;
1355:                        } catch (Throwable ex) {
1356:                            if (!(keepGoingMode)) {
1357:                                throw new BuildException(ex);
1358:                            }
1359:                            thrownException = ex;
1360:                        }
1361:                        if (thrownException != null) {
1362:                            if (thrownException instanceof  BuildException) {
1363:                                log(curtarget, "Target '" + curtarget.getName()
1364:                                        + "' failed with message '"
1365:                                        + thrownException.getMessage() + "'.",
1366:                                        MSG_ERR);
1367:                                // only the first build exception is reported
1368:                                if (buildException == null) {
1369:                                    buildException = (BuildException) thrownException;
1370:                                }
1371:                            } else {
1372:                                log(curtarget, "Target '" + curtarget.getName()
1373:                                        + "' failed with message '"
1374:                                        + thrownException.getMessage() + "'.",
1375:                                        MSG_ERR);
1376:                                thrownException.printStackTrace(System.err);
1377:                                if (buildException == null) {
1378:                                    buildException = new BuildException(
1379:                                            thrownException);
1380:                                }
1381:                            }
1382:                        }
1383:                    }
1384:                }
1385:                if (buildException != null) {
1386:                    throw buildException;
1387:                }
1388:            }
1389:
1390:            /**
1391:             * Return the canonical form of a filename.
1392:             * <p>
1393:             * If the specified file name is relative it is resolved
1394:             * with respect to the given root directory.
1395:             *
1396:             * @param fileName The name of the file to resolve.
1397:             *                 Must not be <code>null</code>.
1398:             *
1399:             * @param rootDir  The directory respective to which relative file names
1400:             *                 are resolved. May be <code>null</code>, in which case
1401:             *                 the current directory is used.
1402:             *
1403:             * @return the resolved File.
1404:             *
1405:             * @deprecated since 1.4.x
1406:             */
1407:            public File resolveFile(String fileName, File rootDir) {
1408:                return FILE_UTILS.resolveFile(rootDir, fileName);
1409:            }
1410:
1411:            /**
1412:             * Return the canonical form of a filename.
1413:             * <p>
1414:             * If the specified file name is relative it is resolved
1415:             * with respect to the project's base directory.
1416:             *
1417:             * @param fileName The name of the file to resolve.
1418:             *                 Must not be <code>null</code>.
1419:             *
1420:             * @return the resolved File.
1421:             *
1422:             */
1423:            public File resolveFile(String fileName) {
1424:                return FILE_UTILS.resolveFile(baseDir, fileName);
1425:            }
1426:
1427:            /**
1428:             * Translate a path into its native (platform specific) format.
1429:             * <p>
1430:             * This method uses PathTokenizer to separate the input path
1431:             * into its components. This handles DOS style paths in a relatively
1432:             * sensible way. The file separators are then converted to their platform
1433:             * specific versions.
1434:             *
1435:             * @param toProcess The path to be translated.
1436:             *                  May be <code>null</code>.
1437:             *
1438:             * @return the native version of the specified path or
1439:             *         an empty string if the path is <code>null</code> or empty.
1440:             *
1441:             * @deprecated since 1.7
1442:             *             Use FileUtils.translatePath instead.
1443:             *
1444:             * @see PathTokenizer
1445:             */
1446:            public static String translatePath(String toProcess) {
1447:                return FileUtils.translatePath(toProcess);
1448:            }
1449:
1450:            /**
1451:             * Convenience method to copy a file from a source to a destination.
1452:             * No filtering is performed.
1453:             *
1454:             * @param sourceFile Name of file to copy from.
1455:             *                   Must not be <code>null</code>.
1456:             * @param destFile Name of file to copy to.
1457:             *                 Must not be <code>null</code>.
1458:             *
1459:             * @exception IOException if the copying fails.
1460:             *
1461:             * @deprecated since 1.4.x
1462:             */
1463:            public void copyFile(String sourceFile, String destFile)
1464:                    throws IOException {
1465:                FILE_UTILS.copyFile(sourceFile, destFile);
1466:            }
1467:
1468:            /**
1469:             * Convenience method to copy a file from a source to a destination
1470:             * specifying if token filtering should be used.
1471:             *
1472:             * @param sourceFile Name of file to copy from.
1473:             *                   Must not be <code>null</code>.
1474:             * @param destFile Name of file to copy to.
1475:             *                 Must not be <code>null</code>.
1476:             * @param filtering Whether or not token filtering should be used during
1477:             *                  the copy.
1478:             *
1479:             * @exception IOException if the copying fails.
1480:             *
1481:             * @deprecated since 1.4.x
1482:             */
1483:            public void copyFile(String sourceFile, String destFile,
1484:                    boolean filtering) throws IOException {
1485:                FILE_UTILS.copyFile(sourceFile, destFile,
1486:                        filtering ? globalFilters : null);
1487:            }
1488:
1489:            /**
1490:             * Convenience method to copy a file from a source to a
1491:             * destination specifying if token filtering should be used and if
1492:             * source files may overwrite newer destination files.
1493:             *
1494:             * @param sourceFile Name of file to copy from.
1495:             *                   Must not be <code>null</code>.
1496:             * @param destFile Name of file to copy to.
1497:             *                 Must not be <code>null</code>.
1498:             * @param filtering Whether or not token filtering should be used during
1499:             *                  the copy.
1500:             * @param overwrite Whether or not the destination file should be
1501:             *                  overwritten if it already exists.
1502:             *
1503:             * @exception IOException if the copying fails.
1504:             *
1505:             * @deprecated since 1.4.x
1506:             */
1507:            public void copyFile(String sourceFile, String destFile,
1508:                    boolean filtering, boolean overwrite) throws IOException {
1509:                FILE_UTILS.copyFile(sourceFile, destFile,
1510:                        filtering ? globalFilters : null, overwrite);
1511:            }
1512:
1513:            /**
1514:             * Convenience method to copy a file from a source to a
1515:             * destination specifying if token filtering should be used, if
1516:             * source files may overwrite newer destination files, and if the
1517:             * last modified time of the resulting file should be set to
1518:             * that of the source file.
1519:             *
1520:             * @param sourceFile Name of file to copy from.
1521:             *                   Must not be <code>null</code>.
1522:             * @param destFile Name of file to copy to.
1523:             *                 Must not be <code>null</code>.
1524:             * @param filtering Whether or not token filtering should be used during
1525:             *                  the copy.
1526:             * @param overwrite Whether or not the destination file should be
1527:             *                  overwritten if it already exists.
1528:             * @param preserveLastModified Whether or not the last modified time of
1529:             *                             the resulting file should be set to that
1530:             *                             of the source file.
1531:             *
1532:             * @exception IOException if the copying fails.
1533:             *
1534:             * @deprecated since 1.4.x
1535:             */
1536:            public void copyFile(String sourceFile, String destFile,
1537:                    boolean filtering, boolean overwrite,
1538:                    boolean preserveLastModified) throws IOException {
1539:                FILE_UTILS.copyFile(sourceFile, destFile,
1540:                        filtering ? globalFilters : null, overwrite,
1541:                        preserveLastModified);
1542:            }
1543:
1544:            /**
1545:             * Convenience method to copy a file from a source to a destination.
1546:             * No filtering is performed.
1547:             *
1548:             * @param sourceFile File to copy from.
1549:             *                   Must not be <code>null</code>.
1550:             * @param destFile File to copy to.
1551:             *                 Must not be <code>null</code>.
1552:             *
1553:             * @exception IOException if the copying fails.
1554:             *
1555:             * @deprecated since 1.4.x
1556:             */
1557:            public void copyFile(File sourceFile, File destFile)
1558:                    throws IOException {
1559:                FILE_UTILS.copyFile(sourceFile, destFile);
1560:            }
1561:
1562:            /**
1563:             * Convenience method to copy a file from a source to a destination
1564:             * specifying if token filtering should be used.
1565:             *
1566:             * @param sourceFile File to copy from.
1567:             *                   Must not be <code>null</code>.
1568:             * @param destFile File to copy to.
1569:             *                 Must not be <code>null</code>.
1570:             * @param filtering Whether or not token filtering should be used during
1571:             *                  the copy.
1572:             *
1573:             * @exception IOException if the copying fails.
1574:             *
1575:             * @deprecated since 1.4.x
1576:             */
1577:            public void copyFile(File sourceFile, File destFile,
1578:                    boolean filtering) throws IOException {
1579:                FILE_UTILS.copyFile(sourceFile, destFile,
1580:                        filtering ? globalFilters : null);
1581:            }
1582:
1583:            /**
1584:             * Convenience method to copy a file from a source to a
1585:             * destination specifying if token filtering should be used and if
1586:             * source files may overwrite newer destination files.
1587:             *
1588:             * @param sourceFile File to copy from.
1589:             *                   Must not be <code>null</code>.
1590:             * @param destFile File to copy to.
1591:             *                 Must not be <code>null</code>.
1592:             * @param filtering Whether or not token filtering should be used during
1593:             *                  the copy.
1594:             * @param overwrite Whether or not the destination file should be
1595:             *                  overwritten if it already exists.
1596:             *
1597:             * @exception IOException if the file cannot be copied.
1598:             *
1599:             * @deprecated since 1.4.x
1600:             */
1601:            public void copyFile(File sourceFile, File destFile,
1602:                    boolean filtering, boolean overwrite) throws IOException {
1603:                FILE_UTILS.copyFile(sourceFile, destFile,
1604:                        filtering ? globalFilters : null, overwrite);
1605:            }
1606:
1607:            /**
1608:             * Convenience method to copy a file from a source to a
1609:             * destination specifying if token filtering should be used, if
1610:             * source files may overwrite newer destination files, and if the
1611:             * last modified time of the resulting file should be set to
1612:             * that of the source file.
1613:             *
1614:             * @param sourceFile File to copy from.
1615:             *                   Must not be <code>null</code>.
1616:             * @param destFile File to copy to.
1617:             *                 Must not be <code>null</code>.
1618:             * @param filtering Whether or not token filtering should be used during
1619:             *                  the copy.
1620:             * @param overwrite Whether or not the destination file should be
1621:             *                  overwritten if it already exists.
1622:             * @param preserveLastModified Whether or not the last modified time of
1623:             *                             the resulting file should be set to that
1624:             *                             of the source file.
1625:             *
1626:             * @exception IOException if the file cannot be copied.
1627:             *
1628:             * @deprecated since 1.4.x
1629:             */
1630:            public void copyFile(File sourceFile, File destFile,
1631:                    boolean filtering, boolean overwrite,
1632:                    boolean preserveLastModified) throws IOException {
1633:                FILE_UTILS.copyFile(sourceFile, destFile,
1634:                        filtering ? globalFilters : null, overwrite,
1635:                        preserveLastModified);
1636:            }
1637:
1638:            /**
1639:             * Call File.setLastModified(long time) on Java above 1.1, and logs
1640:             * a warning on Java 1.1.
1641:             *
1642:             * @param file The file to set the last modified time on.
1643:             *             Must not be <code>null</code>.
1644:             *
1645:             * @param time the required modification time.
1646:             *
1647:             * @deprecated since 1.4.x
1648:             *
1649:             * @exception BuildException if the last modified time cannot be set
1650:             *                           despite running on a platform with a version
1651:             *                           above 1.1.
1652:             */
1653:            public void setFileLastModified(File file, long time)
1654:                    throws BuildException {
1655:                FILE_UTILS.setFileLastModified(file, time);
1656:                log("Setting modification time for " + file, MSG_VERBOSE);
1657:            }
1658:
1659:            /**
1660:             * Return the boolean equivalent of a string, which is considered
1661:             * <code>true</code> if either <code>"on"</code>, <code>"true"</code>,
1662:             * or <code>"yes"</code> is found, ignoring case.
1663:             *
1664:             * @param s The string to convert to a boolean value.
1665:             *
1666:             * @return <code>true</code> if the given string is <code>"on"</code>,
1667:             *         <code>"true"</code> or <code>"yes"</code>, or
1668:             *         <code>false</code> otherwise.
1669:             */
1670:            public static boolean toBoolean(String s) {
1671:                return ("on".equalsIgnoreCase(s) || "true".equalsIgnoreCase(s) || "yes"
1672:                        .equalsIgnoreCase(s));
1673:            }
1674:
1675:            /**
1676:             * Topologically sort a set of targets.  Equivalent to calling
1677:             * <code>topoSort(new String[] {root}, targets, true)</code>.
1678:             *
1679:             * @param root The name of the root target. The sort is created in such
1680:             *             a way that the sequence of Targets up to the root
1681:             *             target is the minimum possible such sequence.
1682:             *             Must not be <code>null</code>.
1683:             * @param targetTable A Hashtable mapping names to Targets.
1684:             *                Must not be <code>null</code>.
1685:             * @return a Vector of ALL Target objects in sorted order.
1686:             * @exception BuildException if there is a cyclic dependency among the
1687:             *                           targets, or if a named target does not exist.
1688:             */
1689:            public final Vector topoSort(String root, Hashtable targetTable)
1690:                    throws BuildException {
1691:                return topoSort(new String[] { root }, targetTable, true);
1692:            }
1693:
1694:            /**
1695:             * Topologically sort a set of targets.  Equivalent to calling
1696:             * <code>topoSort(new String[] {root}, targets, returnAll)</code>.
1697:             *
1698:             * @param root The name of the root target. The sort is created in such
1699:             *             a way that the sequence of Targets up to the root
1700:             *             target is the minimum possible such sequence.
1701:             *             Must not be <code>null</code>.
1702:             * @param targetTable A Hashtable mapping names to Targets.
1703:             *                Must not be <code>null</code>.
1704:             * @param returnAll <code>boolean</code> indicating whether to return all
1705:             *                  targets, or the execution sequence only.
1706:             * @return a Vector of Target objects in sorted order.
1707:             * @exception BuildException if there is a cyclic dependency among the
1708:             *                           targets, or if a named target does not exist.
1709:             * @since Ant 1.6.3
1710:             */
1711:            public final Vector topoSort(String root, Hashtable targetTable,
1712:                    boolean returnAll) throws BuildException {
1713:                return topoSort(new String[] { root }, targetTable, returnAll);
1714:            }
1715:
1716:            /**
1717:             * Topologically sort a set of targets.
1718:             *
1719:             * @param root <code>String[]</code> containing the names of the root targets.
1720:             *             The sort is created in such a way that the ordered sequence of
1721:             *             Targets is the minimum possible such sequence to the specified
1722:             *             root targets.
1723:             *             Must not be <code>null</code>.
1724:             * @param targetTable A map of names to targets (String to Target).
1725:             *                Must not be <code>null</code>.
1726:             * @param returnAll <code>boolean</code> indicating whether to return all
1727:             *                  targets, or the execution sequence only.
1728:             * @return a Vector of Target objects in sorted order.
1729:             * @exception BuildException if there is a cyclic dependency among the
1730:             *                           targets, or if a named target does not exist.
1731:             * @since Ant 1.6.3
1732:             */
1733:            public final Vector topoSort(String[] root, Hashtable targetTable,
1734:                    boolean returnAll) throws BuildException {
1735:                Vector ret = new Vector();
1736:                Hashtable state = new Hashtable();
1737:                Stack visiting = new Stack();
1738:
1739:                // We first run a DFS based sort using each root as a starting node.
1740:                // This creates the minimum sequence of Targets to the root node(s).
1741:                // We then do a sort on any remaining unVISITED targets.
1742:                // This is unnecessary for doing our build, but it catches
1743:                // circular dependencies or missing Targets on the entire
1744:                // dependency tree, not just on the Targets that depend on the
1745:                // build Target.
1746:
1747:                for (int i = 0; i < root.length; i++) {
1748:                    String st = (String) (state.get(root[i]));
1749:                    if (st == null) {
1750:                        tsort(root[i], targetTable, state, visiting, ret);
1751:                    } else if (st == VISITING) {
1752:                        throw new RuntimeException(
1753:                                "Unexpected node in visiting state: " + root[i]);
1754:                    }
1755:                }
1756:                StringBuffer buf = new StringBuffer(
1757:                        "Build sequence for target(s)");
1758:
1759:                for (int j = 0; j < root.length; j++) {
1760:                    buf.append((j == 0) ? " `" : ", `").append(root[j]).append(
1761:                            '\'');
1762:                }
1763:                buf.append(" is " + ret);
1764:                log(buf.toString(), MSG_VERBOSE);
1765:
1766:                Vector complete = (returnAll) ? ret : new Vector(ret);
1767:                for (Enumeration en = targetTable.keys(); en.hasMoreElements();) {
1768:                    String curTarget = (String) en.nextElement();
1769:                    String st = (String) state.get(curTarget);
1770:                    if (st == null) {
1771:                        tsort(curTarget, targetTable, state, visiting, complete);
1772:                    } else if (st == VISITING) {
1773:                        throw new RuntimeException(
1774:                                "Unexpected node in visiting state: "
1775:                                        + curTarget);
1776:                    }
1777:                }
1778:                log("Complete build sequence is " + complete, MSG_VERBOSE);
1779:                return ret;
1780:            }
1781:
1782:            /**
1783:             * Perform a single step in a recursive depth-first-search traversal of
1784:             * the target dependency tree.
1785:             * <p>
1786:             * The current target is first set to the &quot;visiting&quot; state, and
1787:             * pushed onto the &quot;visiting&quot; stack.
1788:             * <p>
1789:             * An exception is then thrown if any child of the current node is in the
1790:             * visiting state, as that implies a circular dependency. The exception
1791:             * contains details of the cycle, using elements of the &quot;visiting&quot;
1792:             * stack.
1793:             * <p>
1794:             * If any child has not already been &quot;visited&quot;, this method is
1795:             * called recursively on it.
1796:             * <p>
1797:             * The current target is then added to the ordered list of targets. Note
1798:             * that this is performed after the children have been visited in order
1799:             * to get the correct order. The current target is set to the
1800:             * &quot;visited&quot; state.
1801:             * <p>
1802:             * By the time this method returns, the ordered list contains the sequence
1803:             * of targets up to and including the current target.
1804:             *
1805:             * @param root The current target to inspect.
1806:             *             Must not be <code>null</code>.
1807:             * @param targetTable A mapping from names to targets (String to Target).
1808:             *                Must not be <code>null</code>.
1809:             * @param state   A mapping from target names to states (String to String).
1810:             *                The states in question are &quot;VISITING&quot; and
1811:             *                &quot;VISITED&quot;. Must not be <code>null</code>.
1812:             * @param visiting A stack of targets which are currently being visited.
1813:             *                 Must not be <code>null</code>.
1814:             * @param ret     The list to add target names to. This will end up
1815:             *                containing the complete list of dependencies in
1816:             *                dependency order.
1817:             *                Must not be <code>null</code>.
1818:             *
1819:             * @exception BuildException if a non-existent target is specified or if
1820:             *                           a circular dependency is detected.
1821:             */
1822:            private void tsort(String root, Hashtable targetTable,
1823:                    Hashtable state, Stack visiting, Vector ret)
1824:                    throws BuildException {
1825:                state.put(root, VISITING);
1826:                visiting.push(root);
1827:
1828:                Target target = (Target) targetTable.get(root);
1829:
1830:                // Make sure we exist
1831:                if (target == null) {
1832:                    StringBuffer sb = new StringBuffer("Target \"");
1833:                    sb.append(root);
1834:                    sb.append("\" does not exist in the project \"");
1835:                    sb.append(name);
1836:                    sb.append("\". ");
1837:                    visiting.pop();
1838:                    if (!visiting.empty()) {
1839:                        String parent = (String) visiting.peek();
1840:                        sb.append("It is used from target \"");
1841:                        sb.append(parent);
1842:                        sb.append("\".");
1843:                    }
1844:                    throw new BuildException(new String(sb));
1845:                }
1846:                for (Enumeration en = target.getDependencies(); en
1847:                        .hasMoreElements();) {
1848:                    String cur = (String) en.nextElement();
1849:                    String m = (String) state.get(cur);
1850:                    if (m == null) {
1851:                        // Not been visited
1852:                        tsort(cur, targetTable, state, visiting, ret);
1853:                    } else if (m == VISITING) {
1854:                        // Currently visiting this node, so have a cycle
1855:                        throw makeCircularException(cur, visiting);
1856:                    }
1857:                }
1858:                String p = (String) visiting.pop();
1859:                if (root != p) {
1860:                    throw new RuntimeException(
1861:                            "Unexpected internal error: expected to " + "pop "
1862:                                    + root + " but got " + p);
1863:                }
1864:                state.put(root, VISITED);
1865:                ret.addElement(target);
1866:            }
1867:
1868:            /**
1869:             * Build an appropriate exception detailing a specified circular
1870:             * dependency.
1871:             *
1872:             * @param end The dependency to stop at. Must not be <code>null</code>.
1873:             * @param stk A stack of dependencies. Must not be <code>null</code>.
1874:             *
1875:             * @return a BuildException detailing the specified circular dependency.
1876:             */
1877:            private static BuildException makeCircularException(String end,
1878:                    Stack stk) {
1879:                StringBuffer sb = new StringBuffer("Circular dependency: ");
1880:                sb.append(end);
1881:                String c;
1882:                do {
1883:                    c = (String) stk.pop();
1884:                    sb.append(" <- ");
1885:                    sb.append(c);
1886:                } while (!c.equals(end));
1887:                return new BuildException(new String(sb));
1888:            }
1889:
1890:            /**
1891:             * Inherit the id references.
1892:             * @param parent the parent project of this project.
1893:             */
1894:            public void inheritIDReferences(Project parent) {
1895:                parentIdProject = parent;
1896:            }
1897:
1898:            /**
1899:             * Attempt to resolve an Unknown Reference using the
1900:             * parsed id's - for BC.
1901:             */
1902:            private Object resolveIdReference(String key, Project callerProject) {
1903:                UnknownElement origUE = (UnknownElement) idReferences.get(key);
1904:                if (origUE == null) {
1905:                    return parentIdProject == null ? null : parentIdProject
1906:                            .resolveIdReference(key, callerProject);
1907:                }
1908:                callerProject.log("Warning: Reference " + key
1909:                        + " has not been set at runtime,"
1910:                        + " but was found during" + LINE_SEP
1911:                        + "build file parsing, attempting to resolve."
1912:                        + " Future versions of Ant may support" + LINE_SEP
1913:                        + " referencing ids defined in non-executed targets.",
1914:                        MSG_WARN);
1915:                UnknownElement copyUE = origUE.copy(callerProject);
1916:                copyUE.maybeConfigure();
1917:                return copyUE.getRealThing();
1918:            }
1919:
1920:            /**
1921:             * Add an id reference.
1922:             * Used for broken build files.
1923:             * @param id the id to set.
1924:             * @param value the value to set it to (Unknown element in this case.
1925:             */
1926:            public void addIdReference(String id, Object value) {
1927:                idReferences.put(id, value);
1928:            }
1929:
1930:            /**
1931:             * Add a reference to the project.
1932:             *
1933:             * @param referenceName The name of the reference. Must not be <code>null</code>.
1934:             * @param value The value of the reference.
1935:             */
1936:            public void addReference(String referenceName, Object value) {
1937:                synchronized (references) {
1938:                    Object old = ((AntRefTable) references)
1939:                            .getReal(referenceName);
1940:                    if (old == value) {
1941:                        // no warning, this is not changing anything
1942:                        return;
1943:                    }
1944:                    if (old != null && !(old instanceof  UnknownElement)) {
1945:                        log("Overriding previous definition of reference to "
1946:                                + referenceName, MSG_VERBOSE);
1947:                    }
1948:                    log("Adding reference: " + referenceName, MSG_DEBUG);
1949:                    references.put(referenceName, value);
1950:                }
1951:            }
1952:
1953:            /**
1954:             * Return a map of the references in the project (String to Object).
1955:             * The returned hashtable is &quot;live&quot; and so must not be modified.
1956:             *
1957:             * @return a map of the references in the project (String to Object).
1958:             */
1959:            public Hashtable getReferences() {
1960:                return references;
1961:            }
1962:
1963:            /**
1964:             * Look up a reference by its key (ID).
1965:             *
1966:             * @param key The key for the desired reference.
1967:             *            Must not be <code>null</code>.
1968:             *
1969:             * @return the reference with the specified ID, or <code>null</code> if
1970:             *         there is no such reference in the project.
1971:             */
1972:            public Object getReference(String key) {
1973:                Object ret = references.get(key);
1974:                if (ret != null) {
1975:                    return ret;
1976:                }
1977:                // Check for old id behaviour
1978:                ret = resolveIdReference(key, this );
1979:                if (ret == null
1980:                        && !key.equals(MagicNames.REFID_PROPERTY_HELPER)) {
1981:                    Vector p = new Vector();
1982:                    PropertyHelper.getPropertyHelper(this ).parsePropertyString(
1983:                            key, new Vector(), p);
1984:                    if (p.size() == 1) {
1985:                        log(
1986:                                "Unresolvable reference "
1987:                                        + key
1988:                                        + " might be a misuse of property expansion syntax.",
1989:                                MSG_WARN);
1990:                    }
1991:                }
1992:                return ret;
1993:            }
1994:
1995:            /**
1996:             * Return a description of the type of the given element, with
1997:             * special handling for instances of tasks and data types.
1998:             * <p>
1999:             * This is useful for logging purposes.
2000:             *
2001:             * @param element The element to describe.
2002:             *                Must not be <code>null</code>.
2003:             *
2004:             * @return a description of the element type.
2005:             *
2006:             * @since 1.95, Ant 1.5
2007:             */
2008:            public String getElementName(Object element) {
2009:                return ComponentHelper.getComponentHelper(this ).getElementName(
2010:                        element);
2011:            }
2012:
2013:            /**
2014:             * Send a &quot;build started&quot; event
2015:             * to the build listeners for this project.
2016:             */
2017:            public void fireBuildStarted() {
2018:                BuildEvent event = new BuildEvent(this );
2019:                Iterator iter = listeners.iterator();
2020:                while (iter.hasNext()) {
2021:                    BuildListener listener = (BuildListener) iter.next();
2022:                    listener.buildStarted(event);
2023:                }
2024:            }
2025:
2026:            /**
2027:             * Send a &quot;build finished&quot; event to the build listeners
2028:             * for this project.
2029:             * @param exception an exception indicating a reason for a build
2030:             *                  failure. May be <code>null</code>, indicating
2031:             *                  a successful build.
2032:             */
2033:            public void fireBuildFinished(Throwable exception) {
2034:                BuildEvent event = new BuildEvent(this );
2035:                event.setException(exception);
2036:                Iterator iter = listeners.iterator();
2037:                while (iter.hasNext()) {
2038:                    BuildListener listener = (BuildListener) iter.next();
2039:                    listener.buildFinished(event);
2040:                }
2041:                // Inform IH to clear the cache
2042:                IntrospectionHelper.clearCache();
2043:            }
2044:
2045:            /**
2046:             * Send a &quot;subbuild started&quot; event to the build listeners for
2047:             * this project.
2048:             *
2049:             * @since Ant 1.6.2
2050:             */
2051:            public void fireSubBuildStarted() {
2052:                BuildEvent event = new BuildEvent(this );
2053:                Iterator iter = listeners.iterator();
2054:                while (iter.hasNext()) {
2055:                    Object listener = iter.next();
2056:                    if (listener instanceof  SubBuildListener) {
2057:                        ((SubBuildListener) listener).subBuildStarted(event);
2058:                    }
2059:                }
2060:            }
2061:
2062:            /**
2063:             * Send a &quot;subbuild finished&quot; event to the build listeners for
2064:             * this project.
2065:             * @param exception an exception indicating a reason for a build
2066:             *                  failure. May be <code>null</code>, indicating
2067:             *                  a successful build.
2068:             *
2069:             * @since Ant 1.6.2
2070:             */
2071:            public void fireSubBuildFinished(Throwable exception) {
2072:                BuildEvent event = new BuildEvent(this );
2073:                event.setException(exception);
2074:                Iterator iter = listeners.iterator();
2075:                while (iter.hasNext()) {
2076:                    Object listener = iter.next();
2077:                    if (listener instanceof  SubBuildListener) {
2078:                        ((SubBuildListener) listener).subBuildFinished(event);
2079:                    }
2080:                }
2081:            }
2082:
2083:            /**
2084:             * Send a &quot;target started&quot; event to the build listeners
2085:             * for this project.
2086:             *
2087:             * @param target The target which is starting to build.
2088:             *               Must not be <code>null</code>.
2089:             */
2090:            protected void fireTargetStarted(Target target) {
2091:                BuildEvent event = new BuildEvent(target);
2092:                Iterator iter = listeners.iterator();
2093:                while (iter.hasNext()) {
2094:                    BuildListener listener = (BuildListener) iter.next();
2095:                    listener.targetStarted(event);
2096:                }
2097:            }
2098:
2099:            /**
2100:             * Send a &quot;target finished&quot; event to the build listeners
2101:             * for this project.
2102:             *
2103:             * @param target    The target which has finished building.
2104:             *                  Must not be <code>null</code>.
2105:             * @param exception an exception indicating a reason for a build
2106:             *                  failure. May be <code>null</code>, indicating
2107:             *                  a successful build.
2108:             */
2109:            protected void fireTargetFinished(Target target, Throwable exception) {
2110:                BuildEvent event = new BuildEvent(target);
2111:                event.setException(exception);
2112:                Iterator iter = listeners.iterator();
2113:                while (iter.hasNext()) {
2114:                    BuildListener listener = (BuildListener) iter.next();
2115:                    listener.targetFinished(event);
2116:                }
2117:            }
2118:
2119:            /**
2120:             * Send a &quot;task started&quot; event to the build listeners
2121:             * for this project.
2122:             *
2123:             * @param task The target which is starting to execute.
2124:             *               Must not be <code>null</code>.
2125:             */
2126:            protected void fireTaskStarted(Task task) {
2127:                // register this as the current task on the current thread.
2128:                registerThreadTask(Thread.currentThread(), task);
2129:                BuildEvent event = new BuildEvent(task);
2130:                Iterator iter = listeners.iterator();
2131:                while (iter.hasNext()) {
2132:                    BuildListener listener = (BuildListener) iter.next();
2133:                    listener.taskStarted(event);
2134:                }
2135:            }
2136:
2137:            /**
2138:             * Send a &quot;task finished&quot; event to the build listeners for this
2139:             * project.
2140:             *
2141:             * @param task      The task which has finished executing.
2142:             *                  Must not be <code>null</code>.
2143:             * @param exception an exception indicating a reason for a build
2144:             *                  failure. May be <code>null</code>, indicating
2145:             *                  a successful build.
2146:             */
2147:            protected void fireTaskFinished(Task task, Throwable exception) {
2148:                registerThreadTask(Thread.currentThread(), null);
2149:                System.out.flush();
2150:                System.err.flush();
2151:                BuildEvent event = new BuildEvent(task);
2152:                event.setException(exception);
2153:                Iterator iter = listeners.iterator();
2154:                while (iter.hasNext()) {
2155:                    BuildListener listener = (BuildListener) iter.next();
2156:                    listener.taskFinished(event);
2157:                }
2158:            }
2159:
2160:            /**
2161:             * Send a &quot;message logged&quot; event to the build listeners
2162:             * for this project.
2163:             *
2164:             * @param event    The event to send. This should be built up with the
2165:             *                 appropriate task/target/project by the caller, so that
2166:             *                 this method can set the message and priority, then send
2167:             *                 the event. Must not be <code>null</code>.
2168:             * @param message  The message to send. Should not be <code>null</code>.
2169:             * @param priority The priority of the message.
2170:             */
2171:            private void fireMessageLoggedEvent(BuildEvent event,
2172:                    String message, int priority) {
2173:
2174:                if (message.endsWith(StringUtils.LINE_SEP)) {
2175:                    int endIndex = message.length()
2176:                            - StringUtils.LINE_SEP.length();
2177:                    event.setMessage(message.substring(0, endIndex), priority);
2178:                } else {
2179:                    event.setMessage(message, priority);
2180:                }
2181:                synchronized (this ) {
2182:                    if (loggingMessage) {
2183:                        /*
2184:                         * One of the Listeners has attempted to access
2185:                         * System.err or System.out.
2186:                         *
2187:                         * We used to throw an exception in this case, but
2188:                         * sometimes Listeners can't prevent it(like our own
2189:                         * Log4jListener which invokes getLogger() which in
2190:                         * turn wants to write to the console).
2191:                         *
2192:                         * @see http://marc.theaimsgroup.com/?t=110538624200006&r=1&w=2
2193:                         *
2194:                         * We now (Ant 1.7 and 1.6.3) simply swallow the message.
2195:                         */
2196:                        return;
2197:                    }
2198:                    try {
2199:                        loggingMessage = true;
2200:                        Iterator iter = listeners.iterator();
2201:                        while (iter.hasNext()) {
2202:                            BuildListener listener = (BuildListener) iter
2203:                                    .next();
2204:                            listener.messageLogged(event);
2205:                        }
2206:                    } finally {
2207:                        loggingMessage = false;
2208:                    }
2209:                }
2210:            }
2211:
2212:            /**
2213:             * Send a &quot;message logged&quot; project level event
2214:             * to the build listeners for this project.
2215:             *
2216:             * @param project  The project generating the event.
2217:             *                 Should not be <code>null</code>.
2218:             * @param message  The message to send. Should not be <code>null</code>.
2219:             * @param priority The priority of the message.
2220:             */
2221:            protected void fireMessageLogged(Project project, String message,
2222:                    int priority) {
2223:                fireMessageLogged(project, message, null, priority);
2224:            }
2225:
2226:            /**
2227:             * Send a &quot;message logged&quot; project level event
2228:             * to the build listeners for this project.
2229:             *
2230:             * @param project  The project generating the event.
2231:             *                 Should not be <code>null</code>.
2232:             * @param message  The message to send. Should not be <code>null</code>.
2233:             * @param throwable The exception that caused this message. May be <code>null</code>.
2234:             * @param priority The priority of the message.
2235:             * @since 1.7
2236:             */
2237:            protected void fireMessageLogged(Project project, String message,
2238:                    Throwable throwable, int priority) {
2239:                BuildEvent event = new BuildEvent(project);
2240:                event.setException(throwable);
2241:                fireMessageLoggedEvent(event, message, priority);
2242:            }
2243:
2244:            /**
2245:             * Send a &quot;message logged&quot; target level event
2246:             * to the build listeners for this project.
2247:             *
2248:             * @param target   The target generating the event.
2249:             *                 Must not be <code>null</code>.
2250:             * @param message  The message to send. Should not be <code>null</code>.
2251:             * @param priority The priority of the message.
2252:             */
2253:            protected void fireMessageLogged(Target target, String message,
2254:                    int priority) {
2255:                fireMessageLogged(target, message, null, priority);
2256:            }
2257:
2258:            /**
2259:             * Send a &quot;message logged&quot; target level event
2260:             * to the build listeners for this project.
2261:             *
2262:             * @param target   The target generating the event.
2263:             *                 Must not be <code>null</code>.
2264:             * @param message  The message to send. Should not be <code>null</code>.
2265:             * @param throwable The exception that caused this message. May be <code>null</code>.
2266:             * @param priority The priority of the message.
2267:             * @since 1.7
2268:             */
2269:            protected void fireMessageLogged(Target target, String message,
2270:                    Throwable throwable, int priority) {
2271:                BuildEvent event = new BuildEvent(target);
2272:                event.setException(throwable);
2273:                fireMessageLoggedEvent(event, message, priority);
2274:            }
2275:
2276:            /**
2277:             * Send a &quot;message logged&quot; task level event
2278:             * to the build listeners for this project.
2279:             *
2280:             * @param task     The task generating the event.
2281:             *                 Must not be <code>null</code>.
2282:             * @param message  The message to send. Should not be <code>null</code>.
2283:             * @param priority The priority of the message.
2284:             */
2285:            protected void fireMessageLogged(Task task, String message,
2286:                    int priority) {
2287:                fireMessageLogged(task, message, null, priority);
2288:            }
2289:
2290:            /**
2291:             * Send a &quot;message logged&quot; task level event
2292:             * to the build listeners for this project.
2293:             *
2294:             * @param task     The task generating the event.
2295:             *                 Must not be <code>null</code>.
2296:             * @param message  The message to send. Should not be <code>null</code>.
2297:             * @param throwable The exception that caused this message. May be <code>null</code>.
2298:             * @param priority The priority of the message.
2299:             * @since 1.7
2300:             */
2301:            protected void fireMessageLogged(Task task, String message,
2302:                    Throwable throwable, int priority) {
2303:                BuildEvent event = new BuildEvent(task);
2304:                event.setException(throwable);
2305:                fireMessageLoggedEvent(event, message, priority);
2306:            }
2307:
2308:            /**
2309:             * Register a task as the current task for a thread.
2310:             * If the task is null, the thread's entry is removed.
2311:             *
2312:             * @param thread the thread on which the task is registered.
2313:             * @param task the task to be registered.
2314:             * @since Ant 1.5
2315:             */
2316:            public synchronized void registerThreadTask(Thread thread, Task task) {
2317:                if (task != null) {
2318:                    threadTasks.put(thread, task);
2319:                    threadGroupTasks.put(thread.getThreadGroup(), task);
2320:                } else {
2321:                    threadTasks.remove(thread);
2322:                    threadGroupTasks.remove(thread.getThreadGroup());
2323:                }
2324:            }
2325:
2326:            /**
2327:             * Get the current task associated with a thread, if any.
2328:             *
2329:             * @param thread the thread for which the task is required.
2330:             * @return the task which is currently registered for the given thread or
2331:             *         null if no task is registered.
2332:             */
2333:            public Task getThreadTask(Thread thread) {
2334:                Task task = (Task) threadTasks.get(thread);
2335:                if (task == null) {
2336:                    ThreadGroup group = thread.getThreadGroup();
2337:                    while (task == null && group != null) {
2338:                        task = (Task) threadGroupTasks.get(group);
2339:                        group = group.getParent();
2340:                    }
2341:                }
2342:                return task;
2343:            }
2344:
2345:            // Should move to a separate public class - and have API to add
2346:            // listeners, etc.
2347:            private static class AntRefTable extends Hashtable {
2348:
2349:                AntRefTable() {
2350:                    super ();
2351:                }
2352:
2353:                /** Returns the unmodified original object.
2354:                 * This method should be called internally to
2355:                 * get the &quot;real&quot; object.
2356:                 * The normal get method will do the replacement
2357:                 * of UnknownElement (this is similar with the JDNI
2358:                 * refs behavior).
2359:                 */
2360:                private Object getReal(Object key) {
2361:                    return super .get(key);
2362:                }
2363:
2364:                /** Get method for the reference table.
2365:                 *  It can be used to hook dynamic references and to modify
2366:                 * some references on the fly--for example for delayed
2367:                 * evaluation.
2368:                 *
2369:                 * It is important to make sure that the processing that is
2370:                 * done inside is not calling get indirectly.
2371:                 *
2372:                 * @param key lookup key.
2373:                 * @return mapped value.
2374:                 */
2375:                public Object get(Object key) {
2376:                    //System.out.println("AntRefTable.get " + key);
2377:                    Object o = getReal(key);
2378:                    if (o instanceof  UnknownElement) {
2379:                        // Make sure that
2380:                        UnknownElement ue = (UnknownElement) o;
2381:                        ue.maybeConfigure();
2382:                        o = ue.getRealThing();
2383:                    }
2384:                    return o;
2385:                }
2386:            }
2387:
2388:            /**
2389:             * Set a reference to this Project on the parameterized object.
2390:             * Need to set the project before other set/add elements
2391:             * are called.
2392:             * @param obj the object to invoke setProject(this) on.
2393:             */
2394:            public final void setProjectReference(final Object obj) {
2395:                if (obj instanceof  ProjectComponent) {
2396:                    ((ProjectComponent) obj).setProject(this );
2397:                    return;
2398:                }
2399:                try {
2400:                    Method method = obj.getClass().getMethod("setProject",
2401:                            new Class[] { Project.class });
2402:                    if (method != null) {
2403:                        method.invoke(obj, new Object[] { this  });
2404:                    }
2405:                } catch (Throwable e) {
2406:                    // ignore this if the object does not have
2407:                    // a set project method or the method
2408:                    // is private/protected.
2409:                }
2410:            }
2411:
2412:            /**
2413:             * Resolve the file relative to the project's basedir and return it as a
2414:             * FileResource.
2415:             * @param name the name of the file to resolve.
2416:             * @return the file resource.
2417:             * @since Ant 1.7
2418:             */
2419:            public Resource getResource(String name) {
2420:                return new FileResource(getBaseDir(), name);
2421:            }
2422:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.