ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peterrei...@apache.org
Subject cvs commit: ant/src/testcases/org/apache/tools/ant/taskdefs MacroDefTest.java
Date Thu, 27 May 2004 14:38:46 GMT
peterreilly    2004/05/27 07:38:46

  Modified:    docs/manual/CoreTasks macrodef.html
               src/etc/testcases/taskdefs macrodef.xml
               src/main/org/apache/tools/ant IntrospectionHelper.java
                        UnknownElement.java
               src/main/org/apache/tools/ant/taskdefs MacroDef.java
                        MacroInstance.java
               src/testcases/org/apache/tools/ant/taskdefs
                        MacroDefTest.java
  Added:       src/main/org/apache/tools/ant DynamicAttribute.java
                        DynamicAttributeNS.java DynamicElement.java
                        DynamicElementNS.java
  Log:
  add implicit element to macrodef
  PR:  25633
  
  Revision  Changes    Path
  1.21      +50 -0     ant/docs/manual/CoreTasks/macrodef.html
  
  Index: macrodef.html
  ===================================================================
  RCS file: /home/cvs/ant/docs/manual/CoreTasks/macrodef.html,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- macrodef.html	26 May 2004 12:25:20 -0000	1.20
  +++ macrodef.html	27 May 2004 14:38:45 -0000	1.21
  @@ -132,6 +132,17 @@
           <td valign="top" align="center">No</td>
         </tr>
         <tr>
  +        <td valign="top">implicit</td>
  +        <td valign="top">
  +          If true this nested element is implicit. This means that
  +          any nested elements of the macrodef instance will be placed
  +          in the element indicated by the name of this element.
  +          There can only be one element if an element is implicit.
  +          The default value is false. <em>since ant 1.6.2</em>
  +        </td>
  +        <td valign="top" align="center">No</td>
  +      </tr>
  +      <tr>
           <td valign="top">description</td>
           <td valign="top">
             This contains a description
  @@ -253,6 +264,45 @@
         &lt;fileset dir="${gen.dir}" includes = "*.cpp"/&gt;
         &lt;linker refid="linker-libs"/&gt;
      &lt;/cc-elements&gt;
  +&lt;/call-cc&gt;
  +</pre>
  +    </blockquote>
  +    <p>
  +      The following fragment shows &lt;call-cc&gt;, but this time
  +      using an implicit element and with the link and target.dir arguments
  +      having default values.
  +    </p>
  +    <blockquote>
  +<pre class="code">
  +&lt;macrodef name="call-cc"&gt;
  +   &lt;attribute name="target"/&gt;
  +   &lt;attribute name="link" default="executable"/&gt;
  +   &lt;attribute name="target.dir" default="${build.bin.dir}"/&gt;
  +   &lt;element name="cc-elements" implicit="yes"/&gt;
  +   &lt;sequential&gt;
  +      &lt;mkdir dir="${obj.dir}/@{target}"/&gt;
  +      &lt;mkdir dir="@{target.dir}"/&gt;
  +         &lt;cc link="@{link}" objdir="${obj.dir}/@{target}"
  +             outfile="@{target.dir}/@{target}"&gt;
  +            &lt;compiler refid="compiler.options"/&gt;
  +            &lt;cc-elements/&gt;
  +         &lt;/cc&gt;
  +      &lt;/sequential&gt;
  +&lt;/macrodef&gt;
  +</pre>
  +    </blockquote>
  +    <p>
  +      This then can be used as follows, note that &lt;cc-elements&gt;
  +      is not specified.
  +    </p>
  +    <blockquote>
  +<pre class="code">
  +&lt;call-cc target="unittests"/&gt;
  +   &lt;includepath location="${gen.dir}"/&gt;
  +   &lt;includepath location="test"/&gt;
  +   &lt;fileset dir="test/unittest" includes = "**/*.cpp"/&gt;
  +   &lt;fileset dir="${gen.dir}" includes = "*.cpp"/&gt;
  +   &lt;linker refid="linker-libs"/&gt;
   &lt;/call-cc&gt;
   </pre>
       </blockquote>
  
  
  
  1.12      +55 -0     ant/src/etc/testcases/taskdefs/macrodef.xml
  
  Index: macrodef.xml
  ===================================================================
  RCS file: /home/cvs/ant/src/etc/testcases/taskdefs/macrodef.xml,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- macrodef.xml	24 Feb 2004 09:30:30 -0000	1.11
  +++ macrodef.xml	27 May 2004 14:38:46 -0000	1.12
  @@ -168,4 +168,59 @@
       <d description="hello world"/>
     </target>
   
  +  <target name="implicit">
  +    <macrodef name="implicit">
  +      <element name="implicit" implicit="yes"/>
  +      <sequential>
  +        <echo>Before implicit</echo>
  +        <implicit/>
  +        <echo>After implicit</echo>
  +      </sequential>
  +    </macrodef>
  +
  +    <implicit>
  +      <echo>In implicit</echo>
  +    </implicit>
  +  </target>
  +
  +  <target name="implicit.notoptional">
  +    <macrodef name="implicit">
  +      <element name="implicit" implicit="yes"/>
  +      <sequential>
  +        <echo>Before implicit</echo>
  +        <implicit/>
  +        <echo>After implicit</echo>
  +      </sequential>
  +    </macrodef>
  +
  +    <implicit>
  +    </implicit>
  +  </target>
  +
  +  <target name="implicit.optional">
  +    <macrodef name="implicit">
  +      <element name="implicit" optional="yes" implicit="yes"/>
  +      <sequential>
  +        <echo>Before implicit</echo>
  +        <implicit/>
  +        <echo>After implicit</echo>
  +      </sequential>
  +    </macrodef>
  +
  +    <implicit>
  +    </implicit>
  +  </target>
  +
  +  <target name="implicit.explicit">
  +    <macrodef name="implicit">
  +      <element name="explicit" optional="yes"/>
  +      <element name="implicit" optional="yes" implicit="yes"/>
  +      <sequential>
  +        <implicit/>
  +        <explicit/>
  +      </sequential>
  +    </macrodef>
  +
  +  </target>
  +
   </project>
  
  
  
  1.84      +12 -12    ant/src/main/org/apache/tools/ant/IntrospectionHelper.java
  
  Index: IntrospectionHelper.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/IntrospectionHelper.java,v
  retrieving revision 1.83
  retrieving revision 1.84
  diff -u -r1.83 -r1.84
  --- IntrospectionHelper.java	25 May 2004 08:25:00 -0000	1.83
  +++ IntrospectionHelper.java	27 May 2004 14:38:46 -0000	1.84
  @@ -489,8 +489,8 @@
               = (AttributeSetter) attributeSetters.get(
                   attributeName.toLowerCase(Locale.US));
           if (as == null) {
  -            if (element instanceof DynamicConfiguratorNS) {
  -                DynamicConfiguratorNS dc = (DynamicConfiguratorNS) element;
  +            if (element instanceof DynamicAttributeNS) {
  +                DynamicAttributeNS dc = (DynamicAttributeNS) element;
                   String uriPlusPrefix =
                       ProjectHelper.extractUriFromComponentName(attributeName);
                   String uri =
  @@ -502,8 +502,8 @@
   
                   dc.setDynamicAttribute(uri, localName, qName, value);
                   return;
  -            } else if (element instanceof DynamicConfigurator) {
  -                DynamicConfigurator dc = (DynamicConfigurator) element;
  +            } else if (element instanceof DynamicAttribute) {
  +                DynamicAttribute dc = (DynamicAttribute) element;
                   dc.setDynamicAttribute(attributeName.toLowerCase(Locale.US), value);
                   return;
               } else {
  @@ -611,8 +611,8 @@
           if (nc == null) {
               nc = createAddTypeCreator(project, parent, elementName);
           }
  -        if (nc == null && parent instanceof DynamicConfiguratorNS) {
  -            DynamicConfiguratorNS dc = (DynamicConfiguratorNS) parent;
  +        if (nc == null && parent instanceof DynamicElementNS) {
  +            DynamicElementNS dc = (DynamicElementNS) parent;
               String qName = (child == null ? name : child.getQName());
               final Object nestedElement =
                   dc.createDynamicElement(
  @@ -640,8 +640,8 @@
                   };
               }
           }
  -        if (nc == null && parent instanceof DynamicConfigurator) {
  -            DynamicConfigurator dc = (DynamicConfigurator) parent;
  +        if (nc == null && parent instanceof DynamicElement) {
  +            DynamicElement dc = (DynamicElement) parent;
               final Object nestedElement =
                   dc.createDynamicElement(name.toLowerCase(Locale.US));
               if (nestedElement != null) {
  @@ -749,8 +749,8 @@
        */
       public boolean supportsNestedElement(String elementName) {
           return nestedCreators.containsKey(elementName.toLowerCase(Locale.US))
  -            || DynamicConfigurator.class.isAssignableFrom(bean)
  -            || DynamicConfiguratorNS.class.isAssignableFrom(bean)
  +            || DynamicElement.class.isAssignableFrom(bean)
  +            || DynamicElementNS.class.isAssignableFrom(bean)
               || addTypeMethods.size() != 0;
       }
   
  @@ -776,8 +776,8 @@
           return (
               nestedCreators.containsKey(name.toLowerCase(Locale.US))
               && (uri.equals(parentUri))) // || uri.equals("")))
  -            || DynamicConfigurator.class.isAssignableFrom(bean)
  -            || DynamicConfiguratorNS.class.isAssignableFrom(bean)
  +            || DynamicElement.class.isAssignableFrom(bean)
  +            || DynamicElementNS.class.isAssignableFrom(bean)
               || addTypeMethods.size() != 0;
       }
   
  
  
  
  1.80      +7 -0      ant/src/main/org/apache/tools/ant/UnknownElement.java
  
  Index: UnknownElement.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/UnknownElement.java,v
  retrieving revision 1.79
  retrieving revision 1.80
  diff -u -r1.79 -r1.80
  --- UnknownElement.java	7 Apr 2004 12:11:17 -0000	1.79
  +++ UnknownElement.java	27 May 2004 14:38:46 -0000	1.80
  @@ -72,6 +72,13 @@
       }
   
       /**
  +     * @return the list of nested UnknownElements for this UnknownElement.
  +     */
  +    public List getChildren() {
  +        return children;
  +    }
  +
  +    /**
        * Returns the name of the XML element which generated this unknown
        * element.
        *
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/DynamicAttribute.java
  
  Index: DynamicAttribute.java
  ===================================================================
  /*
   * Copyright  2002-2004 The Apache Software Foundation
   *
   *  Licensed 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.
   *
   */
  
  package org.apache.tools.ant;
  
  /**
   * Enables a task to control unknown attributes
   *
   * @since Ant 1.5
   */
  public interface DynamicAttribute {
  
      /**
       * Set a named attribute to the given value
       *
       * @param name the name of the attribute
       * @param value the new value of the attribute
       * @throws BuildException when any error occurs
       */
      void setDynamicAttribute(String name, String value)
              throws BuildException;
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/DynamicAttributeNS.java
  
  Index: DynamicAttributeNS.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed 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.
   *
   */
  package org.apache.tools.ant;
  
  /**
   * Enables a task to control unknown attributes.
   *
   * @since Ant 1.7
   */
  public interface DynamicAttributeNS {
  
      /**
       * Set a named attribute to the given value
       *
       * @param uri The namespace uri for this attribute, "" is
       *            used if there is no namespace uri.
       * @param localName The localname of this attribute.
       * @param qName The qualified name for this attribute
       * @param value The value of this attribute.
       * @throws BuildException when any error occurs
       */
      void setDynamicAttribute(
          String uri, String localName, String qName, String value)
              throws BuildException;
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/DynamicElement.java
  
  Index: DynamicElement.java
  ===================================================================
  /*
   * Copyright  2002-2004 The Apache Software Foundation
   *
   *  Licensed 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.
   *
   */
  
  package org.apache.tools.ant;
  
  /**
   * Enables a task to control unknown elements.
   *
   * @since Ant 1.5
   */
  public interface DynamicElement {
  
      /**
       * Create an element with the given name
       *
       * @param name the element nbame
       * @throws BuildException when any error occurs
       * @return the element created
       */
      Object createDynamicElement(String name) throws BuildException;
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/DynamicElementNS.java
  
  Index: DynamicElementNS.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed 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.
   *
   */
  package org.apache.tools.ant;
  
  /**
   * Enables a task to control unknown elements.
   *
   * @since Ant 1.7
   */
  public interface DynamicElementNS {
      /**
       * Create an element with the given name
       *
       * @param uri The namespace uri for this attribute.
       * @param localName The localname of this attribute.
       * @param qName The qualified name for this element.
       * @throws BuildException when any error occurs
       * @return the element created for this element.
       */
      Object createDynamicElement(
          String uri, String localName, String qName) throws BuildException;
  }
  
  
  
  1.26      +28 -2     ant/src/main/org/apache/tools/ant/taskdefs/MacroDef.java
  
  Index: MacroDef.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/MacroDef.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- MacroDef.java	17 May 2004 13:30:17 -0000	1.25
  +++ MacroDef.java	27 May 2004 14:38:46 -0000	1.26
  @@ -46,6 +46,7 @@
       private Map        elements   = new HashMap();
       private String     textName   = null;
       private Text       text       = null;
  +    private boolean    hasImplicitElement = false;
   
       /**
        * Name of the definition
  @@ -254,6 +255,12 @@
                   "the element " + element.getName()
                   + " has already been specified");
           }
  +        if (hasImplicitElement
  +            || (element.isImplicit() && elements.size() != 0)) {
  +            throw new BuildException(
  +                "Only one element allowed when using implicit elements");
  +        }
  +        hasImplicitElement = element.isImplicit();
           elements.put(element.getName(), element);
       }
   
  @@ -507,6 +514,7 @@
       public static class TemplateElement {
           private String name;
           private boolean optional = false;
  +        private boolean implicit = false;
           private String description;
   
           /**
  @@ -547,6 +555,23 @@
           }
   
           /**
  +         * is this element implicit ?
  +         *
  +         * @param implicit if true this element may be left out, default
  +         *                 is false.
  +         */
  +        public void setImplicit(boolean implicit) {
  +            this.implicit = implicit;
  +        }
  +
  +        /**
  +         * @return the implicit attribute
  +         */
  +        public boolean isImplicit() {
  +            return implicit;
  +        }
  +
  +        /**
            * @param desc Description of the element.
            * @since ant 1.6.1
            */
  @@ -584,14 +609,15 @@
               } else if (!name.equals(other.name)) {
                   return false;
               }
  -            return optional == other.optional;
  +            return optional == other.optional && implicit == other.implicit;
           }
   
           /**
            * @return a hash code value for this object.
            */
           public int hashCode() {
  -            return objectHashCode(name) + (optional ? 1 : 0);
  +            return objectHashCode(name)
  +                + (optional ? 1 : 0) + (implicit ? 1 : 0);
           }
       }
   
  
  
  
  1.27      +59 -19    ant/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
  
  Index: MacroInstance.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- MacroInstance.java	7 Apr 2004 12:39:12 -0000	1.26
  +++ MacroInstance.java	27 May 2004 14:38:46 -0000	1.27
  @@ -29,7 +29,7 @@
   import java.util.Enumeration;
   
   import org.apache.tools.ant.BuildException;
  -import org.apache.tools.ant.DynamicConfigurator;
  +import org.apache.tools.ant.DynamicAttribute;
   import org.apache.tools.ant.ProjectHelper;
   import org.apache.tools.ant.RuntimeConfigurable;
   import org.apache.tools.ant.Target;
  @@ -44,13 +44,15 @@
    * the parameter values in attributes and text.
    * @since Ant 1.6
    */
  -public class MacroInstance extends Task implements DynamicConfigurator {
  +public class MacroInstance extends Task implements DynamicAttribute, TaskContainer {
       private MacroDef macroDef;
       private Map      map = new HashMap();
       private Map      nsElements = null;
       private Map      presentElements = new HashMap();
       private Hashtable localProperties = new Hashtable();
       private String    text = null;
  +    private String    implicitTag =     null;
  +    private List      unknownElements = new ArrayList();
   
       /**
        * Called from MacroDef.MyAntTypeDefinition#create()
  @@ -79,22 +81,14 @@
       }
   
       /**
  -     * Add an element.
  -     * @param name the name of the element
  -     * @return an inner Element type
  -     * @throws BuildException if the name is not known or if this element
  -     *                        has already been seen
  +     * Method present for BC purposes.
  +     * @param name not used
  +     * @return nothing
  +     * @deprecated
  +     * @throws BuildException always
        */
       public Object createDynamicElement(String name) throws BuildException {
  -        if (getNsElements().get(name) == null) {
  -            throw new BuildException("unsupported element " + name);
  -        }
  -        if (presentElements.get(name) != null) {
  -            throw new BuildException("Element " + name + " already present");
  -        }
  -        Element ret = new Element();
  -        presentElements.put(name, ret);
  -        return ret;
  +        throw new BuildException("Not implemented any more");
       }
   
       private Map getNsElements() {
  @@ -105,12 +99,44 @@
                   Map.Entry entry = (Map.Entry) i.next();
                   nsElements.put((String) entry.getKey(),
                                  entry.getValue());
  +                MacroDef.TemplateElement te = (MacroDef.TemplateElement)
  +                    entry.getValue();
  +                if (te.isImplicit()) {
  +                    implicitTag = te.getName();
  +                }
               }
           }
           return nsElements;
       }
   
       /**
  +     * Add a unknownElement for the macro instances nested elements.
  +     *
  +     * @param nestedTask a nested element.
  +     */
  +    public void addTask(Task nestedTask) {
  +        unknownElements.add(nestedTask);
  +    }
  +
  +    private void processTasks() {
  +        if (implicitTag != null) {
  +            return;
  +        }
  +        for (Iterator i = unknownElements.iterator(); i.hasNext();) {
  +            UnknownElement ue = (UnknownElement) i.next();
  +            String name = ProjectHelper.extractNameFromComponentName(
  +                ue.getTag()).toLowerCase(Locale.US);
  +            if (getNsElements().get(name) == null) {
  +                throw new BuildException("unsupported element " + name);
  +            }
  +            if (presentElements.get(name) != null) {
  +                throw new BuildException("Element " + name + " already present");
  +            }
  +            presentElements.put(name, ue.getChildren());
  +        }
  +    }
  +
  +    /**
        * Embedded element in macro instance
        */
       public static class Element implements TaskContainer {
  @@ -255,9 +281,21 @@
                   UnknownElement child = copy(unknownElement);
                   rc.addChild(child.getWrapper());
                   ret.addChild(child);
  +            } else if (templateElement.isImplicit()) {
  +                if (unknownElements.size() == 0 && !templateElement.isOptional())
{
  +                    throw new BuildException(
  +                        "Missing nested elements for implicit element "
  +                        + templateElement.getName());
  +                }
  +                for (Iterator i = unknownElements.iterator();
  +                     i.hasNext();) {
  +                    UnknownElement child = (UnknownElement) i.next();
  +                    rc.addChild(child.getWrapper());
  +                    ret.addChild(child);
  +                }
               } else {
  -                Element element = (Element) presentElements.get(tag);
  -                if (element == null) {
  +                List list = (List) presentElements.get(tag);
  +                if (list == null) {
                       if (!templateElement.isOptional()) {
                           throw new BuildException(
                               "Required nested element "
  @@ -265,7 +303,7 @@
                       }
                       continue;
                   }
  -                for (Iterator i = element.getUnknownElements().iterator();
  +                for (Iterator i = list.iterator();
                        i.hasNext();) {
                       UnknownElement child = (UnknownElement) i.next();
                       rc.addChild(child.getWrapper());
  @@ -283,6 +321,8 @@
        *
        */
       public void execute() {
  +        getNsElements();
  +        processTasks();
           localProperties = new Hashtable();
           Set copyKeys = new HashSet(map.keySet());
           for (Iterator i = macroDef.getAttributes().iterator(); i.hasNext();) {
  
  
  
  1.17      +20 -0     ant/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java
  
  Index: MacroDefTest.java
  ===================================================================
  RCS file: /home/cvs/ant/src/testcases/org/apache/tools/ant/taskdefs/MacroDefTest.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- MacroDefTest.java	9 Mar 2004 16:48:57 -0000	1.16
  +++ MacroDefTest.java	27 May 2004 14:38:46 -0000	1.17
  @@ -108,5 +108,25 @@
               "attribute.description",
               "description is hello world");
       }
  +    public void testImplicit() {
  +        expectLog(
  +            "implicit", "Before implicitIn implicitAfter implicit");
  +    }
  +    public void testImplicitNotOptional() {
  +        expectSpecificBuildException(
  +            "implicit.notoptional",
  +            "Missing nested elements for implicit element implicit",
  +            "Missing nested elements for implicit element implicit");
  +    }
  +    public void testImplicitOptional() {
  +        expectLog(
  +            "implicit.optional", "Before implicitAfter implicit");
  +    }
  +    public void testImplicitExplicit() {
  +        expectSpecificBuildException(
  +            "implicit.explicit",
  +            "Only one element allowed when using implicit elements",
  +            "Only one element allowed when using implicit elements");
  +    }
   }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message