ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hi...@apache.org
Subject svn commit: r819284 - in /ant/core/trunk: ./ docs/manual/ src/main/org/apache/tools/ant/ src/main/org/apache/tools/ant/taskdefs/ src/main/org/apache/tools/ant/types/
Date Sun, 27 Sep 2009 10:59:49 GMT
Author: hibou
Date: Sun Sep 27 10:59:48 2009
New Revision: 819284

URL: http://svn.apache.org/viewvc?rev=819284&view=rev
Log:
PR 47830 : implementation of the ProjectHelperRepository to make Ant able to choose a ProjectHelper,
and some doc about it

Added:
    ant/core/trunk/docs/manual/projecthelper.html   (with props)
    ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java   (with props)
Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/docs/manual/developlist.html
    ant/core/trunk/docs/manual/running.html
    ant/core/trunk/src/main/org/apache/tools/ant/Main.java
    ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Ant.java
    ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
    ant/core/trunk/src/main/org/apache/tools/ant/types/Description.java

Modified: ant/core/trunk/WHATSNEW
URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Sun Sep 27 10:59:48 2009
@@ -174,6 +174,11 @@
    (i.e. in a very unlikely event) then the new syntax would yield a
    different result (an expanded property) than Ant 1.7.1 did.
 
+ * A ProjectHelper implementation can now provide the default build file
+   name it is expecting, and can specify if they can support a specific build
+   file. So Ant is now capable of supporting several ProjectHelper
+   implementations, deciding on which to use depending of the input build file.
+
 Fixed bugs:
 -----------
 

Modified: ant/core/trunk/docs/manual/developlist.html
URL: http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/developlist.html?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/developlist.html (original)
+++ ant/core/trunk/docs/manual/developlist.html Sun Sep 27 10:59:48 2009
@@ -37,6 +37,7 @@
 <a href="develop.html#integration">Source-code Integration</a><br/>
 <a href="inputhandler.html">InputHandler</a><br/>
 <a href="antexternal.html">Using Ant Tasks Outside of Ant</a><br/>
+<a href="projecthelper.html">The Ant frontend: ProjectHelper</a><br/>
 
 <br/>Tutorials<br/>
 <a href="tutorial-HelloWorldWithAnt.html">Hello World with Ant</a><br/>

Added: ant/core/trunk/docs/manual/projecthelper.html
URL: http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/projecthelper.html?rev=819284&view=auto
==============================================================================
--- ant/core/trunk/docs/manual/projecthelper.html (added)
+++ ant/core/trunk/docs/manual/projecthelper.html Sun Sep 27 10:59:48 2009
@@ -0,0 +1,131 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
+<title>The Ant frontend: ProjectHelper</title>
+</head>
+
+<body>
+<h1>The Ant frontend: ProjectHelper</h1>
+
+<h2><a name="definition">What is a ProjectHelper?</a></h2>
+
+<p>
+The <code>ProjectHelper</code> in Ant is responsible to parse the build file
+and create java instances representing the build workflow. It also declares which
+kind of file it can parse, and which file name it expects as default input file.
+</p>
+<p>
+So in Ant there is a default <code>ProjectHelper</code>
+(<code>org.apache.tools.ant.helper.ProjectHelper2</code>) which will parse the
+usual build.xml files. And if no build file is specified on the command line, it
+will expect to find a build.xml file.
+</p>
+
+<p>
+The immediate benefit of a such abstraction it that it is possible to make Ant
+understand other kind of descriptive language than XML. Some experiment have
+been done around a pure java frontend, and a groovy one too (ask the dev mailing
+list for further info about these).
+</p>
+
+<h2><a name="repository">How is Ant is selecting the proper ProjectHelper</a></h2>
+
+<p>
+Ant can now know about several implementations of <code>ProjectHelper</code>
+and have to decide which to use for each build file.
+</p>
+
+<p>So Ant at startup will list the found implementations and will keep it
+ordered as it finds them in an internal 'repository':
+<ul>
+    <li>the first to be searched for is the one declared by the system property
+        <code>org.apache.tools.ant.ProjectHelper</code> (see
+        <a href="running.html#sysprops">Java System Properties</a>);</li>
+    <li>then it searches with its class loader for a <code>ProjectHelper</code>
+        service declarations in the META-INF: it searches in the classpath for a
+        file <code>META-INF/services/org.apache.tools.ant.ProjectHelper</code>.
+        This file will just contain the fully qualified name of the
+        implementation of <code>ProjectHelper</code> to instanciate;</li>
+    <li>it will also search with the system class loader for
+        <code>ProjectHelper</code> service declarations in the META-INF;</li>
+    <li>last but not least it will add its default <code>ProjectHelper</code>
+        that can parse classical build.xml files.</li>
+</ul>
+In case of error while trying to instanciate a <code>ProjectHelper</code>, Ant
+will log an error but still won't stop. If you want further debugging
+info about the <code>ProjectHelper</code> internal 'repository', use the system
+property <code>ant.project-helper-repo.debug</code> and set it to
+<code>true</code>; the full stack trace will then also be printed.
+</p>
+
+<p>
+Then when Ant is expected to parse a file, it will ask the
+<code>ProjectHelper</code> repository to found an implementation that will be
+able to parse the input file. Actually it will just iterate on the ordered list
+and the first implementation that returns <code>true</code> to
+<code>supportsBuildFile(File buildFile)</code> will be selected.
+</p>
+
+<p>
+And when Ant is launching and there is no input file specified, it will search for
+a default input file. It will iterate on the list of <code>ProjectHelper</code>
+and will select the first one that expects a default file that actually exist.
+</p>
+
+<h2><a name="writing">Writing your own ProjectHelper</a></h2>
+
+<p>
+The class <code>org.apache.tools.ant.ProjectHelper</code> is the API expected
to
+be implemented. So write your own <code>ProjectHelper</code> by extending that
+abstract class. You are then expected to implement at least the function
+<code>parse(Project project, Object source)</code>. Note also that your
+implementation will be instanciated by Ant, and it is expecting a default
+constructor with no arguments.
+</p>
+
+<p>
+Then there are some functions that will help you define what your helper is
+capable of and what is is expecting:
+<ul>
+    <li><code>getDefaultBuildFile()</code>: defines which file name is
expected if
+    none provided</li>
+    <li><code>supportsBuildFile(File buildFile)</code>: defines if your
parser
+    can parse the input file</li>
+</ul>
+</p>
+
+<p>
+Now that you have your implementation ready, you have to declare it to Ant. Two
+solutions here:
+<ul>
+    <li>use the system property <code>org.apache.tools.ant.ProjectHelper</code>
+        (see also the <a href="running.html#sysprops">Java System Properties</a>);</li>
+    <li>use the service file in META-INF: in the jar you will build with your
+        implementation, add a file
+        <code>META-INF/services/org.apache.tools.ant.ProjectHelper</code>.
+        And then in this file just put the fully qualified name of your
+        implementation</li>
+</ul>
+</p>
+
+</body>
+</html>
+

Propchange: ant/core/trunk/docs/manual/projecthelper.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ant/core/trunk/docs/manual/projecthelper.html
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: ant/core/trunk/docs/manual/projecthelper.html
------------------------------------------------------------------------------
    svn:mime-type = text/html

Modified: ant/core/trunk/docs/manual/running.html
URL: http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/running.html?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/running.html (original)
+++ ant/core/trunk/docs/manual/running.html Sun Sep 27 10:59:48 2009
@@ -415,7 +415,6 @@
   <td>see <a href="sysclasspath.html">its dedicated page</a>, no
     default value</td>
   <td>see <a href="sysclasspath.html">its dedicated page</a></td>
-  </td>
 </tr>
 <tr>
   <td><code>file.encoding</code></td>
@@ -455,18 +454,25 @@
   </td>
 </tr>
 <tr>
-  <td><code>websphere.home
+  <td><code>websphere.home</code></td>
   <td>path</td>
   <td>Points to home directory of websphere.
       see <a href="OptionalTasks/ejb.html#ejbjar_websphere">EJB Tasks</a>
   </td>
 </tr>
 <tr>
-  <td><code>XmlLogger.file
+  <td><code>XmlLogger.file</code></td>
   <td>filename (default 'log.xml')</td>
   <td>Name for the logfile for <a href="listeners.html#MailLogger">MailLogger</a>.
   </td>
 </tr>
+<tr>
+  <td><code>ant.project-helper-repo.debug</code></td>
+  <td>boolean (default 'false')</td>
+  <td>Set it to true to enable debuging with Ant's
+  <a href="projecthelper.html#repository">ProjectHelper internal repository</a>.
+  </td>
+</tr>
 </table>
 
 <p>
@@ -529,7 +535,7 @@
     Unix(-like) systems</a></h2>
 
 <p>If you start Ant as a background process (like in <code>ant
-    &</code>) and the build process creates another process, Ant will
+    &amp;</code>) and the build process creates another process, Ant will
     immediately try to read from standard input, which in turn will
     most likely suspend the process.  In order to avoid this, you must
     redirect Ant's standard input or explicitly provide input to each

Modified: ant/core/trunk/src/main/org/apache/tools/ant/Main.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/Main.java?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/Main.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/Main.java Sun Sep 27 10:59:48 2009
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -301,6 +302,7 @@
      */
     private void processArgs(String[] args) {
         String searchForThis = null;
+        boolean searchForFile = false;
         PrintStream logTo = null;
 
         // cycle through given args
@@ -359,11 +361,10 @@
                 // set the flag to display the targets and quit
                 projectHelp = true;
             } else if (arg.equals("-find") || arg.equals("-s")) {
+                searchForFile = true;
                 // eat up next arg if present, default to build.xml
                 if (i < args.length - 1) {
                     searchForThis = args[++i];
-                } else {
-                    searchForThis = DEFAULT_BUILD_FILENAME;
                 }
             } else if (arg.startsWith("-propertyfile")) {
                 i = handleArgPropertyFile(args, i);
@@ -411,11 +412,37 @@
         // if buildFile was not specified on the command line,
         if (buildFile == null) {
             // but -find then search for it
-            if (searchForThis != null) {
-                buildFile = findBuildFile(System.getProperty("user.dir"),
-                                          searchForThis);
+            if (searchForFile) {
+                if (searchForThis != null) {
+                    buildFile = findBuildFile(System.getProperty("user.dir"), searchForThis);
+                    if (buildFile == null) {
+                        throw new BuildException("Could not locate a build file!");
+                    }
+                } else {
+                    // no search file specified: so search an existing default file
+                    Iterator it = ProjectHelperRepository.getInstance().getHelpers();
+                    do {
+                        ProjectHelper helper = (ProjectHelper) it.next();
+                        searchForThis = helper.getDefaultBuildFile();
+                        if (msgOutputLevel >= Project.MSG_VERBOSE) {
+                            System.out.println("Searching the default build file: " + searchForThis);
+                        }
+                        buildFile = findBuildFile(System.getProperty("user.dir"), searchForThis);
+                    } while (buildFile == null && it.hasNext());
+                    if (buildFile == null) {
+                        throw new BuildException("Could not locate a build file!");
+                    }
+                }
             } else {
-                buildFile = new File(DEFAULT_BUILD_FILENAME);
+                // no build file specified: so search an existing default file
+                Iterator it = ProjectHelperRepository.getInstance().getHelpers();
+                do {
+                    ProjectHelper helper = (ProjectHelper) it.next();
+                    buildFile = new File(helper.getDefaultBuildFile());
+                    if (msgOutputLevel >= Project.MSG_VERBOSE) {
+                        System.out.println("Trying the default build file: " + buildFile);
+                    }
+                } while (!buildFile.exists() && it.hasNext());
             }
         }
 
@@ -633,20 +660,17 @@
      * <p>
      * Takes the given target as a suffix to append to each
      * parent directory in search of a build file.  Once the
-     * root of the file-system has been reached an exception
-     * is thrown.
+     * root of the file-system has been reached <code>null</code>
+     * is returned.
      *
      * @param start  Leaf directory of search.
      *               Must not be <code>null</code>.
      * @param suffix  Suffix filename to look for in parents.
      *                Must not be <code>null</code>.
      *
-     * @return A handle to the build file if one is found
-     *
-     * @exception BuildException if no build file is found
+     * @return A handle to the build file if one is found, <code>null</code>
if not
      */
-    private File findBuildFile(String start, String suffix)
-         throws BuildException {
+    private File findBuildFile(String start, String suffix) {
         if (msgOutputLevel >= Project.MSG_INFO) {
             System.out.println("Searching for " + suffix + " ...");
         }
@@ -662,7 +686,7 @@
             // if parent is null, then we are at the root of the fs,
             // complain that we can't find the build file.
             if (parent == null) {
-                throw new BuildException("Could not locate a build file!");
+                return null;
             }
 
             // refresh our file handle

Modified: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java Sun Sep 27 10:59:48 2009
@@ -17,37 +17,21 @@
  */
 package org.apache.tools.ant;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.net.URL;
 import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Vector;
 
-import org.xml.sax.AttributeList;
-
-import org.apache.tools.ant.helper.ProjectHelper2;
 import org.apache.tools.ant.util.LoaderUtils;
+import org.xml.sax.AttributeList;
 
 /**
  * Configures a Project (complete with Targets and Tasks) based on
- * a XML build file. It'll rely on a plugin to do the actual processing
- * of the xml file.
- *
+ * a build file. It'll rely on a plugin to do the actual processing
+ * of the file.
+ * <p>
  * This class also provide static wrappers for common introspection.
- *
- * All helper plugins must provide backward compatibility with the
- * original ant patterns, unless a different behavior is explicitly
- * specified. For example, if namespace is used on the &lt;project&gt; tag
- * the helper can expect the entire build file to be namespace-enabled.
- * Namespaces or helper-specific tags can provide meta-information to
- * the helper, allowing it to use new ( or different policies ).
- *
- * However, if no namespace is used the behavior should be exactly
- * identical with the default helper.
- *
  */
 public class ProjectHelper {
     /** The URI for ant name space */
@@ -89,7 +73,7 @@
      * @exception BuildException if the configuration is invalid or cannot be read
      */
     public static void configureProject(Project project, File buildFile) throws BuildException
{
-        ProjectHelper helper = ProjectHelper.getProjectHelper();
+        ProjectHelper helper = ProjectHelperRepository.getInstance().getProjectHelper(buildFile);
         project.addReference(PROJECTHELPER_REFERENCE, helper);
         helper.parse(project, buildFile);
     }
@@ -224,103 +208,13 @@
     }
 
     /**
-     * Discovers a project helper instance. Uses the same patterns
-     * as JAXP, commons-logging, etc: a system property, a JDK1.3
-     * service discovery, default.
-     *
-     * @return a ProjectHelper, either a custom implementation
-     * if one is available and configured, or the default implementation
-     * otherwise.
-     *
-     * @exception BuildException if a specified helper class cannot
-     * be loaded/instantiated.
-     */
-    public static ProjectHelper getProjectHelper() throws BuildException {
-        // Identify the class loader we will be using. Ant may be
-        // in a webapp or embedded in a different app
-        ProjectHelper helper = null;
-
-        // First, try the system property
-        String helperClass = System.getProperty(HELPER_PROPERTY);
-        try {
-            if (helperClass != null) {
-                helper = newHelper(helperClass);
-            }
-        } catch (SecurityException e) {
-            System.out.println("Unable to load ProjectHelper class \""
-                + helperClass + " specified in system property "
-                + HELPER_PROPERTY);
-        }
-
-        // A JDK1.3 'service' ( like in JAXP ). That will plug a helper
-        // automatically if in CLASSPATH, with the right META-INF/services.
-        if (helper == null) {
-            try {
-                ClassLoader classLoader = LoaderUtils.getContextClassLoader();
-                InputStream is = null;
-                if (classLoader != null) {
-                    is = classLoader.getResourceAsStream(SERVICE_ID);
-                }
-                if (is == null) {
-                    is = ClassLoader.getSystemResourceAsStream(SERVICE_ID);
-                }
-                if (is != null) {
-                    // This code is needed by EBCDIC and other strange systems.
-                    // It's a fix for bugs reported in xerces
-                    InputStreamReader isr;
-                    try {
-                        isr = new InputStreamReader(is, "UTF-8");
-                    } catch (java.io.UnsupportedEncodingException e) {
-                        isr = new InputStreamReader(is);
-                    }
-                    BufferedReader rd = new BufferedReader(isr);
-
-                    String helperClassName = rd.readLine();
-                    rd.close();
-
-                    if (helperClassName != null && !"".equals(helperClassName)) {
-                        helper = newHelper(helperClassName);
-                    }
-                }
-            } catch (Exception ex) {
-                System.out.println("Unable to load ProjectHelper from service " + SERVICE_ID);
-            }
-        }
-        return helper == null ? new ProjectHelper2() : helper;
-    }
-
-    /**
-     * Creates a new helper instance from the name of the class.
-     * It'll first try the thread class loader, then Class.forName()
-     * will load from the same loader that loaded this class.
-     *
-     * @param helperClass The name of the class to create an instance
-     *                    of. Must not be <code>null</code>.
-     *
-     * @return a new instance of the specified class.
-     *
-     * @exception BuildException if the class cannot be found or
-     * cannot be appropriate instantiated.
+     * Get the first project helper found in the classpath
+     * 
+     * @return an project helper, never <code>null</code>
+     * @see #getHelpers()
      */
-    private static ProjectHelper newHelper(String helperClass)
-        throws BuildException {
-        ClassLoader classLoader = LoaderUtils.getContextClassLoader();
-        try {
-            Class clazz = null;
-            if (classLoader != null) {
-                try {
-                    clazz = classLoader.loadClass(helperClass);
-                } catch (ClassNotFoundException ex) {
-                    // try next method
-                }
-            }
-            if (clazz == null) {
-                clazz = Class.forName(helperClass);
-            }
-            return ((ProjectHelper) clazz.newInstance());
-        } catch (Exception e) {
-            throw new BuildException(e);
-        }
+    public static ProjectHelper getProjectHelper() {
+        return (ProjectHelper) ProjectHelperRepository.getInstance().getHelpers().next();
     }
 
     /**
@@ -618,4 +512,27 @@
                                                 URL source) {
         throw new BuildException("can't parse antlib descriptors");
     }
+
+    /**
+     * Check if the helper supports the kind of file. Some basic check on the
+     * extension's file should be done here.
+     * 
+     * @param buildFile
+     *            the file expected to be parsed (never <code>null</code>)
+     * @return true if the helper supports it
+     * @since Ant 1.8.0
+     */
+    public boolean supportsBuildFile(File buildFile) {
+        return true;
+    }
+
+    /**
+     * The file name of the build script to be parsed if none specified on the command line
+     * 
+     * @return the name of the default file (never <code>null</code>)
+     * @since Ant 1.8.0
+     */
+    public String getDefaultBuildFile() {
+        return Main.DEFAULT_BUILD_FILENAME;
+    }
 }

Added: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java?rev=819284&view=auto
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java (added)
+++ ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java Sun Sep 27 10:59:48
2009
@@ -0,0 +1,203 @@
+package org.apache.tools.ant;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.apache.tools.ant.util.LoaderUtils;
+
+/**
+ * Repository of {@link ProjectHelper} found in the classpath or via some System
+ * properties.
+ * <p>
+ * See the ProjectHelper documentation in the manual.
+ * 
+ * @since Ant 1.8.0
+ */
+public class ProjectHelperRepository {
+
+    private static final String DEBUG_PROJECT_HELPER_REPOSITORY = "ant.project-helper-repo.debug";
+
+    // The message log level is not accessible here because everything is instanciated statically
+    private static final boolean DEBUG = "true".equals(System.getProperty(DEBUG_PROJECT_HELPER_REPOSITORY));
+
+    private static ProjectHelperRepository instance = new ProjectHelperRepository();
+
+    private List/* <ProjectHelper> */helpers = new ArrayList();
+
+    public static ProjectHelperRepository getInstance() {
+        return instance;
+    }
+
+    private ProjectHelperRepository() {
+        collectProjectHelpers();
+    }
+
+    private void collectProjectHelpers() {
+        // First, try the system property
+        ProjectHelper projectHelper = getProjectHelperBySystemProperty();
+        registerProjectHelper(projectHelper);
+
+        // A JDK1.3 'service' ( like in JAXP ). That will plug a helper
+        // automatically if in CLASSPATH, with the right META-INF/services.
+        try {
+            ClassLoader classLoader = LoaderUtils.getContextClassLoader();
+            if (classLoader != null) {
+                Enumeration resources = classLoader.getResources(ProjectHelper.SERVICE_ID);
+                while (resources.hasMoreElements()) {
+                    URL resource = (URL) resources.nextElement();
+                    projectHelper = getProjectHelperBySerice(resource.openStream());
+                    registerProjectHelper(projectHelper);
+                }
+            }
+
+            InputStream systemResource = ClassLoader.getSystemResourceAsStream(ProjectHelper.SERVICE_ID);
+            if (systemResource != null) {
+                projectHelper = getProjectHelperBySerice(systemResource);
+                registerProjectHelper(projectHelper);
+            }
+        } catch (Exception e) {
+            System.err.println("Unable to load ProjectHelper from service "
+                    + ProjectHelper.SERVICE_ID + " (" + e.getClass().getName() + ": "
+                    + e.getMessage() + ")");
+            if (DEBUG) {
+                e.printStackTrace(System.err);
+            }
+        }
+
+        // last but not least, ant default project helper
+        projectHelper = new ProjectHelper2();
+        registerProjectHelper(projectHelper);
+    }
+
+    private void registerProjectHelper(ProjectHelper projectHelper) {
+        if (projectHelper == null) {
+            return;
+        }
+        if (DEBUG) {
+            System.out.println("ProjectHelper " +
+                    projectHelper.getClass().getName() + " registered.");
+        }
+        helpers.add(projectHelper);
+    }
+
+    private ProjectHelper getProjectHelperBySystemProperty() {
+        String helperClass = System.getProperty(ProjectHelper.HELPER_PROPERTY);
+        try {
+            if (helperClass != null) {
+                return newHelper(helperClass);
+            }
+        } catch (SecurityException e) {
+            System.err.println("Unable to load ProjectHelper class \""
+                    + helperClass + " specified in system property "
+                    + ProjectHelper.HELPER_PROPERTY + " (" + e.getMessage() + ")");
+            if (DEBUG) {
+                e.printStackTrace(System.err);
+            }
+        }
+        return null;
+    }
+
+    private ProjectHelper getProjectHelperBySerice(InputStream is) {
+        try {
+            // This code is needed by EBCDIC and other strange systems.
+            // It's a fix for bugs reported in xerces
+            InputStreamReader isr;
+            try {
+                isr = new InputStreamReader(is, "UTF-8");
+            } catch (java.io.UnsupportedEncodingException e) {
+                isr = new InputStreamReader(is);
+            }
+            BufferedReader rd = new BufferedReader(isr);
+
+            String helperClassName = rd.readLine();
+            rd.close();
+
+            if (helperClassName != null && !"".equals(helperClassName)) {
+                return newHelper(helperClassName);
+            }
+        } catch (Exception e) {
+            System.out.println("Unable to load ProjectHelper from service "
+                    + ProjectHelper.SERVICE_ID + " (" + e.getMessage() + ")");
+            if (DEBUG) {
+                e.printStackTrace(System.err);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Creates a new helper instance from the name of the class. It'll first try
+     * the thread class loader, then Class.forName() will load from the same
+     * loader that loaded this class.
+     * 
+     * @param helperClass
+     *            The name of the class to create an instance of. Must not be
+     *            <code>null</code>.
+     * 
+     * @return a new instance of the specified class.
+     * 
+     * @exception BuildException
+     *                if the class cannot be found or cannot be appropriate
+     *                instantiated.
+     */
+    private ProjectHelper newHelper(String helperClass) throws BuildException {
+        ClassLoader classLoader = LoaderUtils.getContextClassLoader();
+        try {
+            Class clazz = null;
+            if (classLoader != null) {
+                try {
+                    clazz = classLoader.loadClass(helperClass);
+                } catch (ClassNotFoundException ex) {
+                    // try next method
+                }
+            }
+            if (clazz == null) {
+                clazz = Class.forName(helperClass);
+            }
+            return ((ProjectHelper) clazz.newInstance());
+        } catch (Exception e) {
+            throw new BuildException(e);
+        }
+    }
+
+    /**
+     * Get the helper that will be able to parse the specified file. The helper
+     * will be chosen among the ones found in the classpath
+     * 
+     * @return the first ProjectHelper that fit the requirement (never <code>null</code>).
+     */
+    public ProjectHelper getProjectHelper(File buildFile) throws BuildException {
+        Iterator it = helpers.iterator();
+        while (it.hasNext()) {
+            ProjectHelper helper = (ProjectHelper) it.next();
+            if (helper.supportsBuildFile(buildFile)) {
+                if (DEBUG) {
+                    System.out.println("ProjectHelper "
+                            + helper.getClass().getName() + " selected for the file "
+                            + buildFile);
+                }
+                return helper;
+            }
+        }
+        throw new RuntimeException("BUG: at least the ProjectHelper2 should have supported
the file " + buildFile);
+    }
+
+    /**
+     * Get an iterator on the list of project helpers configured. The iterator
+     * will always return at least one element as there will always be the
+     * default project helper configured.
+     * 
+     * @return an iterator of {@link ProjectHelper}
+     */
+    public Iterator getHelpers() {
+        return helpers.iterator();
+    }
+}

Propchange: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelperRepository.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Ant.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Ant.java?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Ant.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Ant.java Sun Sep 27 10:59:48 2009
@@ -359,7 +359,7 @@
             overrideProperties();
 
             if (antFile == null) {
-                antFile = Main.DEFAULT_BUILD_FILENAME;
+                antFile = getDefaultBuildFile();
             }
 
             File file = FILE_UTILS.resolveFile(dir, antFile);
@@ -470,6 +470,19 @@
     }
 
     /**
+     * Get the default build file name to use when launching the task.
+     * <p>
+     * This function may be overrided by providers of custom ProjectHelper so they can implement
easily their sub
+     * launcher.
+     * 
+     * @return the name of the default file
+     * @since Ant 1.8.0
+     */
+    protected String getDefaultBuildFile() {
+        return Main.DEFAULT_BUILD_FILENAME;
+    }
+
+    /**
      * Override the properties in the new project with the one
      * explicitly defined as nested elements here.
      * @throws BuildException under unknown circumstances.

Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SubAnt.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SubAnt.java?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SubAnt.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/SubAnt.java Sun Sep 27 10:59:48
2009
@@ -67,7 +67,7 @@
 
     private Ant ant = null;
     private String subTarget = null;
-    private String antfile = Main.DEFAULT_BUILD_FILENAME;
+    private String antfile = getDefaultBuildFile();
     private File genericantfile = null;
     private boolean verbose = false;
     private boolean inheritAll = false;
@@ -83,6 +83,19 @@
     private Vector/*<TargetElement>*/ targets = new Vector();
 
     /**
+     * Get the default build file name to use when launching the task.
+     * <p>
+     * This function may be overrided by providers of custom ProjectHelper so they can implement
easily their sub
+     * launcher.
+     * 
+     * @return the name of the default file
+     * @since Ant 1.8.0
+     */
+    protected String getDefaultBuildFile() {
+        return Main.DEFAULT_BUILD_FILENAME;
+    }
+
+    /**
      * Pass output sent to System.out to the new project.
      *
      * @param output a line of output

Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/Description.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/Description.java?rev=819284&r1=819283&r2=819284&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/Description.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/Description.java Sun Sep 27 10:59:48
2009
@@ -50,7 +50,7 @@
      */
     public void addText(String text) {
 
-        ProjectHelper ph = ProjectHelper.getProjectHelper();
+        ProjectHelper ph = (ProjectHelper) getProject().getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
         if (!(ph instanceof ProjectHelperImpl)) {
             // New behavior for delayed task creation. Description
             // will be evaluated in Project.getDescription()



Mime
View raw message