peterreilly    2003/07/24 06:48:46

  Modified:    docs/manual/CoreTasks typedef.html
               src/main/org/apache/tools/ant/helper ProjectHelper2.java
               src/main/org/apache/tools/ant/taskdefs Definer.java
  Added:       src/etc/testcases/taskdefs antlib.xml test.antlib.xml
               src/main/org/apache/tools/ant/taskdefs Antlib.java
               src/testcases/org/apache/tools/ant/taskdefs AntlibTest.java
  Log:
  Add antlib xml functionality
  This is patch 7204 the fourth patch of the antlib + ns enhancement. The
  issues reported by Stephan will need be
  addressed, so the implementation may change
  before ant 1.6 is released.
  PR: 19897
  
  Revision  Changes    Path
  1.8       +94 -25    ant/docs/manual/CoreTasks/typedef.html
  
  Index: typedef.html
  ===================================================================
  RCS file: /home/cvs/ant/docs/manual/CoreTasks/typedef.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- typedef.html      26 Jun 2003 08:54:27 -0000      1.7
  +++ typedef.html      24 Jul 2003 13:48:45 -0000      1.8
  @@ -9,23 +9,43 @@
   
   <h2><a name="typedef">Typedef</a></h2>
   <h3>Description</h3>
  -<p>Adds a data type definition to the current project, such that this
  -new type can be used in the current project. Two attributes are
  -needed, the name that identifies this data type uniquely, and the full
  -name of the class (including the packages) that implements this
  -type.</p>
  -<p>You can also define a group of data types at once using the file or
  -resource attributes.  These attributes point to files in the format of
  -Java property files.  Each line defines a single data type in the
  -format:</p>
  -<pre>
  -typename=fully.qualified.java.classname
  -</pre>
  -<p>Typedef should be used to add your own tasks and types to the system. Data
  -types are things like <a href="../using.html#path">paths</a> or <a
  -href="../CoreTypes/fileset.html">filesets</a> that can be defined at
  -the project level and referenced via their ID attribute.</p>
  -<p>Custom data types usually need custom tasks to put them to good use.</p>
  +  <p>
  +    Adds a task or a data type definition to the current project
  +    such that this new type or task can be used in the current project.
  +  </p>
  +  <p>
  +    Tasks are any class that extend org.apache.tools.ant.Task or
  +    a class that is adapted to a Task using an adapter class.
  +  </p>
  +  <p>
  +    Data types are things like <a href="../using.html#path">paths</a> or
  +    <a href="../CoreTypes/fileset.html">filesets</a> that can be defined at
  +    the project level and referenced via their ID attribute.
  +    Custom data types usually need custom tasks to put them to good use.
  +  </p>
  +  <p>
  +    Two attributes are needed to make a definition,
  +    the name that identifies this data type uniquely, and the full
  +    name of the class (including the packages) that implements this
  +    type.
  +  </p>
  +  <p>
  +    You can also define a group of definitions at once using the file or
  +    resource attributes.  These attributes point to files in the format of
  +    Java property files or an xml format.
  +  </p>
  +  <p>
  +    For property files each line defines a single data type in the
  +    format:</p>
  +  <pre>
  +    typename=fully.qualified.java.classname
  +  </pre>
  +    
  +  <p>
  +    The xml format is described below in the <a href="#antlib">Antlib</a>
  +    section.
  +  </p>
  +
   <h3>Parameters</h3>
   <table border="1" cellpadding="2" cellspacing="0">
     <tr>
  @@ -56,6 +76,19 @@
       <td valign="top" align="center">No</td>
     </tr>
     <tr>
  +    <td valign="top">format</td>
  +    <td valign="top">The format of the file or resource. The values
  +      are "properties" or "xml". If the value is "properties" the 
file/resource
  +      is a property file contains name to classname pairs. If the value
  +      is "xml", the file/resource is an xml file/resource structured 
according
  +      to   <a href="#antlib">Antlib</a>.
  +      The default is "properties" unless the file/resorce name ends with
  +      ".xml", in which case the format attribute will have the value "xml".
  +      (introduced in ant1.6)
  +    </td>
  +    <td valign="top" align="center">No</td>
  +  </tr>
  +  <tr>
       <td valign="top">classpath</td> <td valign="top">the classpath to
         use when looking up <code>classname</code>.</td> <td
       align="center" valign="top">No</td>
  @@ -102,15 +135,51 @@
       <td valign="top" align="center">No</td>
     </tr>
   </table>
  -<h3>Parameters specified as nested elements</h3>
  -<h4>classpath</h4>
  -<p><code>Typedef</code>'s <i>classpath</i> attribute is a 
  -<a href="../using.html#path">PATH like structure</a> and can also be set
  -via a nested <i>classpath</i> element.</p>
  +  <h3>Parameters specified as nested elements</h3>
  +  <h4>classpath</h4>
  +  <p><code>Typedef</code>'s <i>classpath</i> attribute is a 
  +    <a href="../using.html#path">PATH like structure</a> and can also be set
  +    via a nested <i>classpath</i> element.</p>
  +
   <h3>Examples</h3>
  -<pre>  &lt;typedef name=&quot;urlset&quot; 
classname=&quot;com.mydomain.URLSet&quot;/&gt;</pre>
  -<p>makes a data type called <code>urlset</code> available to Ant. The
  -class <code>com.mydomain.URLSet</code> implements this type.</p>
  +  The following fragment defines define a type called <i>urlset</i>.
  +  <pre>
  +    &lt;typedef name="urlset" classname="com.mydomain.URLSet"/&gt; </pre>
  +  The data type is now availabe to Ant. The
  +  class <code>com.mydomain.URLSet</code> implements this type.</p>
  +  <p>
  +    Assuming a class <i>org.acme.ant.RunnableAdapter</i> that
  +    extends Task and implements <i>org.apache.tools.ant.TypeAdapter</i>,
  +    and in the execute method invokes <i>run</i> on the proxied object,
  +    one may use a Runnable class as an Ant task. The following fragment
  +    defines  a task called <i>runclock</i>.
  +    <pre>
  +    &lt;typedef name="runclock"
  +             classname="com.acme.ant.RunClock"
  +             adapter="org.acme.ant.RunnableAdapter"/&gt;
  +  </pre>
  +  <h3><a name="antlib">Antlib xml format</a></h3>
  +  An antlib file is an xml file with a root element of "antlib".
  +  Antlib is actually a <a href="sequential.html">Sequential</a> task with
  +  special treatment for tasks that are ant definition tasks - like typedef
  +  and <a href="taskdef.html">Taskdef</a>.
  +
  +    A group of tasks and types may be defined together in an antlib
  +    file. For example the file <i>sample.xml</i> contains the following:
  +  <pre>
  +    &lt;?xml version="1.0"?&gt;
  +    &lt;antlib&gt;
  +      &lt;typedef name="if" classname="org.acme.ant.If"/&gt;
  +      &lt;typedef name="scriptpathmapper"
  +               classname="org.acme.ant.ScriptPathMapper"
  +               onerror="ignore"/&gt;
  +    &lt;/antlib&gt;
  +  </pre>
  +    It defines two types or tasks, <i>if</i> and <i>scriptpathmapper</i>.
  +    This antlib file may be used in a build script as follows:
  +    <pre>
  +      &lt;typedef file="sample.xml"/&gt;
  +    </pre>
   
   <hr>
   <p align="center">Copyright &copy; 2001-2003 Apache Software
  
  
  
  1.1                  ant/src/etc/testcases/taskdefs/antlib.xml
  
  Index: antlib.xml
  ===================================================================
  <?xml version="1.0"?>
  <project name="test">
  
    <property name="testcases.dir" location="../../../../build/testcases"/>
  
    <path id="testclasses">
      <pathelement location="${testcases.dir}" />
      <pathelement path="${java.class.path}" />
    </path>
  
    <target name="antlib.file">
      <typedef file="test.antlib.xml"
               classpathref="testclasses"/>
      <mytask/>
    </target>
  
  </project>
  
  
  1.1                  ant/src/etc/testcases/taskdefs/test.antlib.xml
  
  Index: test.antlib.xml
  ===================================================================
  <?xml version="1.0"?>
  <antlib>
    <typedef 
      name="mytask" onerror="ignore"
      classname="org.apache.tools.ant.taskdefs.AntlibTest$MyTask"/>
  </antlib>
  
  
  
  1.27      +72 -16    
ant/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
  
  Index: ProjectHelper2.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/helper/ProjectHelper2.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- ProjectHelper2.java       23 Jul 2003 10:24:39 -0000      1.26
  +++ ProjectHelper2.java       24 Jul 2003 13:48:45 -0000      1.27
  @@ -57,8 +57,10 @@
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.FileNotFoundException;
  +import java.io.InputStream;
   import java.io.IOException;
   import java.io.UnsupportedEncodingException;
  +import java.net.URL;
   import java.util.Hashtable;
   import java.util.Stack;
   
  @@ -75,6 +77,7 @@
   import org.apache.tools.ant.ProjectHelper;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.Target;
  +import org.apache.tools.ant.Task;
   import org.apache.tools.ant.RuntimeConfigurable;
   import org.apache.tools.ant.BuildException;
   import org.apache.tools.ant.Location;
  @@ -103,6 +106,31 @@
       private static FileUtils fu = FileUtils.newFileUtils();
   
       /**
  +     * Parse an unknown element from a url
  +     *
  +     * @param project the current project
  +     * @param source  the url containing the task
  +     * @return a configured task
  +     * @exception BuildException if an error occurs
  +     */
  +    public UnknownElement parseUnknownElement(Project project, URL source)
  +        throws BuildException {
  +        Target dummyTarget = new Target();
  +        dummyTarget.setProject(project);
  +
  +        AntXMLContext context = new AntXMLContext(project);
  +        context.addTarget(dummyTarget);
  +        context.setImplicitTarget(dummyTarget);
  +
  +        parse(context.getProject(), source,
  +              new RootHandler(context, elementHandler));
  +        Task[] tasks = dummyTarget.getTasks();
  +        if (tasks.length != 1) {
  +            throw new BuildException("No tasks defined");
  +        }
  +        return (UnknownElement) tasks[0];
  +    }
  +    /**
        * Parse a source xml input.
        *
        * @param project the current project
  @@ -127,11 +155,11 @@
               // we are in an imported file.
               context.setIgnoreProjectTag(true);
               context.getCurrentTarget().startImportedTasks();
  -            parse(project, source, new RootHandler(context));
  +            parse(project, source, new RootHandler(context, mainHandler));
               context.getCurrentTarget().endImportedTasks();
           } else {
               // top level file
  -            parse(project, source, new RootHandler(context));
  +            parse(project, source, new RootHandler(context, mainHandler));
               // Execute the top-level target
               context.getImplicitTarget().execute();
           }
  @@ -152,22 +180,33 @@
           AntXMLContext context = handler.context;
   
           File buildFile = null;
  +        URL  url = null;
  +        String buildFileName = null;
   
           if (source instanceof File) {
               buildFile = (File) source;
  -//         } else if (source instanceof InputStream) {
  -//         } else if (source instanceof URL) {
  -//         } else if (source instanceof InputSource) {
  +            buildFile = new File(buildFile.getAbsolutePath());
  +            context.setBuildFile(buildFile);
  +            buildFileName = buildFile.toString();
  +//         } else if (source instanceof InputStream ) {
  +        } else if (source instanceof URL) {
  +            if (handler.getCurrentAntHandler() != elementHandler) {
  +                throw new BuildException(
  +                    "Source " + source.getClass().getName()
  +                    + " not supported by this plugin for "
  +                    + " non task xml");
  +            }
  +            url = (URL) source;
  +            buildFileName = url.toString();
  +//         } else if (source instanceof InputSource ) {
           } else {
               throw new BuildException("Source " + source.getClass().getName()
  -                + " not supported by this plugin");
  +                                     + " not supported by this plugin");
           }
   
  -        FileInputStream inputStream = null;
  +        InputStream inputStream = null;
           InputSource inputSource = null;
   
  -        buildFile = new File(buildFile.getAbsolutePath());
  -        context.setBuildFile(buildFile);
   
           try {
               /**
  @@ -175,13 +214,21 @@
                */
               XMLReader parser = JAXPUtils.getNamespaceXMLReader();
   
  -            String uri = fu.toURI(buildFile.getAbsolutePath());
  +            String uri = null;
  +            if (buildFile != null) {
  +                uri = fu.toURI(buildFile.getAbsolutePath());
  +                inputStream = new FileInputStream(buildFile);
  +            } else {
  +                inputStream = url.openStream();
  +                uri = url.toString(); // ?? OK ??
  +            }
   
  -            inputStream = new FileInputStream(buildFile);
               inputSource = new InputSource(inputStream);
  -            inputSource.setSystemId(uri);
  -            project.log("parsing buildfile " + buildFile
  -                + " with URI = " + uri, Project.MSG_VERBOSE);
  +            if (uri != null) {
  +                inputSource.setSystemId(uri);
  +            }
  +            project.log("parsing buildfile " + buildFileName
  +                        + "with URI = " + uri, Project.MSG_VERBOSE);
   
               DefaultHandler hb = handler;
   
  @@ -357,11 +404,20 @@
            * Creates a new RootHandler instance.
            *
            * @param context The context for the handler.
  +         * @param rootHandler The handler for the root element.
            */
  -        public RootHandler(AntXMLContext context) {
  -            currentHandler = ProjectHelper2.mainHandler;
  +        public RootHandler(AntXMLContext context, AntHandler rootHandler) {
  +            currentHandler = rootHandler;
               antHandlers.push(currentHandler);
               this.context = context;
  +        }
  +
  +        /**
  +         * Returns the current ant handler object.
  +         * @return the current ant handler.
  +         */
  +        public AntHandler getCurrentAntHandler() {
  +            return currentHandler;
           }
   
           /**
  
  
  
  1.39      +63 -2     ant/src/main/org/apache/tools/ant/taskdefs/Definer.java
  
  Index: Definer.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Definer.java,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- Definer.java      22 Jul 2003 16:40:32 -0000      1.38
  +++ Definer.java      24 Jul 2003 13:48:45 -0000      1.39
  @@ -59,12 +59,14 @@
   import java.io.InputStream;
   import java.net.URL;
   import java.util.Enumeration;
  +import java.util.Locale;
   import java.util.Properties;
   
   import org.apache.tools.ant.AntTypeDefinition;
   import org.apache.tools.ant.AntClassLoader;
   import org.apache.tools.ant.ComponentHelper;
   import org.apache.tools.ant.BuildException;
  +import org.apache.tools.ant.Location;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.Task;
   import org.apache.tools.ant.types.Path;
  @@ -88,6 +90,7 @@
       private String resource;
       private ClasspathUtils.Delegate cpDelegate;
   
  +    private   int    format = Format.PROPERTIES;
       private   boolean definerSet = false;
       private   ClassLoader internalClassLoader;
       private   int         onError = OnError.FAIL;
  @@ -130,6 +133,24 @@
       }
   
       /**
  +     * Enumerated type for format attribute
  +     *
  +     * @see EnumeratedAttribute
  +     */
  +    public static class Format extends EnumeratedAttribute {
  +        /** Enumerated values */
  +        public static final int PROPERTIES = 0, XML = 1;
  +
  +        /**
  +         * get the values
  +         * @return an array of the allowed values for this attribute.
  +         */
  +        public String[] getValues() {
  +            return new String[] {"properties", "xml"};
  +        }
  +    }
  +
  +    /**
        * What to do if there is an error in loading the class.
        * <dl>
        *   <li>error - throw build exception</li>
  @@ -144,6 +165,14 @@
       }
   
       /**
  +     * Sets the format of the file or resource
  +     * @param format the enumerated value - xml or properties
  +     */
  +    public void setFormat(Format format) {
  +        this.format = format.getIndex();
  +    }
  +
  +    /**
        * @param reverseLoader if true a delegated loader will take precedence 
over
        *                      the parent
        * @deprecated stop using this attribute
  @@ -289,7 +318,15 @@
                   return;
               }
   
  -            loadProperties(al, url);
  +            if (url.toString().toLowerCase(Locale.US).endsWith(".xml")) {
  +                format = Format.XML;
  +            }
  +
  +            if (format == Format.PROPERTIES) {
  +                loadProperties(al, url);
  +            } else {
  +                loadAntlib(al, url);
  +            }
           }
       }
   
  @@ -360,6 +397,30 @@
       }
   
       /**
  +     * Load an antlib from a url.
  +     *
  +     * @param classLoader the classloader to use.
  +     * @param url the url to load the definitions from.
  +     */
  +    private void loadAntlib(ClassLoader classLoader, URL url) {
  +        try {
  +            Antlib antlib = Antlib.createAntlib(getProject(), url);
  +            antlib.setClassLoader(classLoader);
  +            antlib.perform();
  +        } catch (BuildException ex) {
  +            Location location = ex.getLocation();
  +            if (location == null) {
  +                throw ex;
  +            }
  +            throw new BuildException(
  +                "Error in "
  +                + System.getProperty("line.separator")
  +                + getLocation().toString()
  +                + " " + ex.getMessage());
  +        }
  +    }
  +
  +    /**
        * create a classloader for this definition
        * @return the classloader from the cpDelegate
        */
  @@ -543,7 +604,7 @@
               } catch (NoClassDefFoundError ncdfe) {
                   String msg = getTaskName() + " A class needed by class "
                       + classname + " cannot be found: " + ncdfe.getMessage();
  -                throw new BuildException(msg, ncdfe, location);
  +                throw new BuildException(msg, ncdfe, getLocation());
               }
           } catch (BuildException ex) {
               switch (onError) {
  
  
  
  1.3       +146 -667  ant/src/main/org/apache/tools/ant/taskdefs/Antlib.java
  
  
  
  
  1.1                  
ant/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java
  
  Index: AntlibTest.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "Ant" and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs;
  
  import org.apache.tools.ant.BuildFileTest;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  
  /**
   * @author Peter Reilly
   */
  public class AntlibTest extends BuildFileTest {
      public AntlibTest(String name) {
          super(name);
      }
  
      public void setUp() {
          configureProject("src/etc/testcases/taskdefs/antlib.xml");
      }
  
      public void testAntlibFile() {
          expectLog("antlib.file", "MyTask called");
      }
  
      public static class MyTask extends Task {
          public void execute() {
              log("MyTask called");
          }
      }
  
  }
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to