ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peterrei...@apache.org
Subject cvs commit: ant/docs/manual/CoreTypes custom-programming.html
Date Wed, 13 Aug 2003 08:35:01 GMT
peterreilly    2003/08/13 01:35:01

  Added:       docs/manual/CoreTypes custom-programming.html
  Log:
  initial attempt to describe introspection based components
  
  Revision  Changes    Path
  1.1                  ant/docs/manual/CoreTypes/custom-programming.html
  
  Index: custom-programming.html
  ===================================================================
  <html>
    <head>
      <meta http-equiv="Content-Language" content="en-us"></meta>
      <title>Custom Components</title>
    </head>
  
    <body>
      <h2>Custom Components</h2>
      <h3>Overview</h3>
      <p>
        Custom components are conditions, selectors, filters and other
        objects that are defined outside ant core.
      </p>
      <p>
        In Ant 1.6 custom conditions, selectors and filters has
        been overhauled.
      </p>
      <p>
        It is now possible to define custom conditions, selectors and filters
        that behave like Ant Core components.
        This is achieved by allowing datatypes defined in build scripts
        to be used as custom components if the class of the datatype
        is compatible, or has been adapted by an adapter class.
      </p>
      <p>
        The old methods of defining custom components are still supported.
      </p>
      <h3>Definition and use</h3>
      <p>
        A custom component is a normal Java class that implements a particular
        interface or extends a  particular class, or has been adapted to the
        interface or class.
      </p>
      <p>
        It is exactly like writing a
        <a href="../develop.html#writingowntask">custom task</a>.
        One defines attributes and nested elements by writing <i>setter</i>
        methods and <i>add</i> methods.
      </p>
      <p>
        After the class has been written, it is added to the ant system
        by using <code>&lt;typedef&gt;</code>.
      </p>
      <h3><a name="customconditions">Custom Conditions</a></h3>
      <p>
        Custom conditions are datatypes that implement
        <code>org.apache.tools.ant.taskdefs.condition.Condition</code>.
        For example a custom condition that returns true if a
        string is all upper case could be written as:
      </p>
      <blockquote>
        <pre>
  package com.mydomain;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.taskdefs.condition.Condition;
  
  public class AllUpperCaseCondition extends Condition {
      private String value;
  
      // The setter for the &quot;value&quot; attribute
      public void setValue(String value) {
          this.value = value;
      }
  
      // This method evaluates the condition
      public boolean eval() {
          if (value == null) {
              throw new BuildException("value attribute is not set");
          }
          return value.toUpperCase().equals(value);
     }        
  }
        </pre>
      </blockquote>
  
      <p>
        Adding the condition to the system is achieved as follows:
      </p>
      <blockquote>
        <pre>
  &lt;typedef
      name="alluppercase"
      classname="com.mydomain.AllUpperCaseCondition"
      classpath="${mydomain.classes"/&gt;
        </pre>
      </blockquote>
      <p>
        This condition can now be used wherever a Core Ant condition
        is used.
      </p>
      <blockquote>
        <pre>
  &lt;condition property="allupper"&gt;
     &lt;alluppercase value="THIS IS ALL UPPER CASE"/&gt;
  &lt;/condition&gt;
        </pre>
      </blockquote>
      <h3><a name="customselectors">Custom Selectors</a></h3>
      <p>
        Custom selectors are datatypes that implement
        <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
        <p>There is only one method required.
          <code>public boolean isSelected(File basedir, String filename,
            File file)</code>.
          It returns true
          or false depending on whether the given file should be
          selected or not.
        </p>
      <p>
        An example of a custom selection that selects filenames ending
        in ".java" would be:
      </p>
      <blockquote>
        <pre>
  package com.mydomain;
  import org.apache.tools.ant.types.selectors.FileSelector;
  public class JavaSelector {
      public boolean isSelected(File b, String filename, File f) {
         return filename.toLowerCase().endsWith(".java");
      }
  }
        </pre>
      </blockquote>
      <p>
      </p>
      <p>
        Adding the selector to the system is achieved as follows:
      </p>
      <blockquote>
        <pre>
  &lt;typedef
      name="javaselector"
      classname="com.mydomain.JavaSelector"
      classpath="${mydomain.classes"/&gt;
        </pre>
      </blockquote>
      <p>
        This selector can now be used wherever a Core Ant selector
        is used.
      </p>
        <p>
          One may use
          <code>org.apache.tools.ant.types.selectors.BaseSelector</code>,
          a convenience class that provides reasonable default
          behaviour.
          It has some predefined behaviours you can take advantage
          of. Any time you encounter a problem when setting attributes or
          adding tags, you can call setError(String errmsg) and the class
          will know that there is a problem. Then, at the top of your
          <code>isSelected()</code> method call <code>validate()</code>
and
          a BuildException will be thrown with the contents of your error
          message. The <code>validate()</code> method also gives you a
          last chance to check your settings for consistency because it
          calls <code>verifySettings()</code>. Override this method and
          call <code>setError()</code> within it if you detect any
          problems in how your selector is set up.</p>
      </p>
      <p>
        To write custom selector containers one should extend
        <code>org.apache.tools.ant.types.selectors.BaseSelectorContainer</code>.
        Implement the
        <code>public boolean isSelected(File baseDir, String filename, File file)</code>
        method to do the right thing. Chances are you'll want to iterate
        over the selectors under you, so use
        <code>selectorElements()</code> to get an iterator that will do
        that.
      </p>
      <p>
        For example to create a selector container that will select files
        if a certain number of contained selectors select, one could write
        a selector as follows:
      </p>
      <blockquote>
        <pre>
  public class MatchNumberSelectors extends BaseSelectorContainer {
      private int number = -1;
      public void setNumber(int number) {
          this.number = number;
      }
      public void verifySettings() {
          if (number &lt; 0) {
             throw new BuildException("Number attribute should be set");
          }
      }
      public boolean isSelected(File baseDir, String filename, File file) {
          validate();
          int numberSelected = 0;
          for (Enumeration e = selectorElements(); e.hasNextElement();) {
              FileSelector s = (FileSelector) e.nextElement();
              if (s.isSelected(baseDir, filename, file)) {
                  numberSelected++;
              }
          }
          return numberSelected == number;
      }
  }
        </pre>
      </blockquote>
      <p>
        To define and use this selector one could do:
      </p>
      <blockquote>
        <pre>
  &lt;typedef name="numberselected"
           classname="com.mydomain.MatchNumberSelectors"/&gt;
  ...
  &lt;fileset dir="${src.path}"&gt;
     &lt;numberselected number="2"&gt;
        &lt;contains text="script" casesensitive="no"/&gt;
        &lt;size value="4" units="Ki" when="more"/&gt;
        &lt;javaselector/&gt;
     &lt;/numberselected&gt;
  &lt;/fileset&gt;
        </pre>
      </blockquote>
      <p>
        <i>The custom selector</i>
      </p>
      <p>
        The custom selector was the pre ant 1.6 way of defining custom selectors.
        This method is still supported for backward compatiblity.
      </p>
      <p>You can write your own selectors and use them within the selector
        containers by specifying them within the &lt;custom&gt; tag.</p>
  
          <p>To create a new Custom Selector, you have to create a class that
          implements
          <code>org.apache.tools.ant.types.selectors.ExtendFileSelector</code>.
          The easiest way to do that is through the convenience base class
          <code>org.apache.tools.ant.types.selectors.BaseExtendSelector</code>,
          which provides all of the methods for supporting
          <code>&lt;param&gt;</code> tags. First, override the
          <code>isSelected()</code> method, and optionally the
          <code>verifySettings()</code> method. If your custom
          selector requires parameters to be set, you can also override
          the <code>setParameters()</code> method and interpret the
          parameters that are passed in any way you like. Several of the
          core selectors demonstrate how to do that because they can
          also be used as custom selectors.</p>
  
  
      <p>Once that is written, you include it in your build file by using
        the <code>&lt;custom&gt;</code> tag.
      </p>
  
      <table border="1" cellpadding="2" cellspacing="0">
        <tr>
          <td valign="top"><b>Attribute</b></td>
          <td valign="top"><b>Description</b></td>
          <td align="center" valign="top"><b>Required</b></td>
        </tr>
        <tr>
          <td valign="top">classname</td>
          <td valign="top">The name of your class that implements
            <code>org.apache.tools.ant.types.selectors.FileSelector</code>.
          </td>
          <td valign="top" align="center">Yes</td>
        </tr>
        <tr>
          <td valign="top">classpath</td>
          <td valign="top">The classpath to use in order to load the
            custom selector class. If neither this classpath nor the
            classpathref are specified, the class will be
            loaded from the classpath that Ant uses.
          </td>
          <td valign="top" align="center">No</td>
        </tr>
        <tr>
          <td valign="top">classpathref</td>
          <td valign="top">A reference to a classpath previously
            defined. If neither this reference nor the
            classpath above are specified, the class will be
            loaded from the classpath that Ant uses.
          </td>
          <td valign="top" align="center">No</td>
        </tr>
      </table>
  
      <p>Here is how you use <code>&lt;custom&gt;</code> to
        use your class as a selector:
      </p>
  
      <blockquote><pre>
  &lt;fileset dir=&quot;${mydir}&quot; includes=&quot;**/*&quot;&gt;
      &lt;custom classname=&quot;com.mydomain.MySelector&quot;&gt;
          &lt;param name=&quot;myattribute&quot; value=&quot;myvalue&quot;/&gt;
      &lt;/custom&gt;
  &lt;/fileset&gt;
        </pre></blockquote>
  
      
      <p>The core selectors that can also be used as custom selectors
        are</p>
  
      <ul>
        <li><a href="selectors.html#containsselect">Contains Selector</a>
with
          classname <code>org.apache.tools.ant.types.selectors.ContainsSelector</code>
        </li>
        <li><a href="selectors.html#dateselect">Date Selector</a> with
          classname <code>org.apache.tools.ant.types.selectors.DateSelector</code>
        </li>
        <li><a href="selectors.html#depthselect">Depth Selector</a> with
          classname <code>org.apache.tools.ant.types.selectors.DepthSelector</code>
        </li>
        <li><a href="selectors.html#filenameselect">Filename Selector</a>
with
          classname <code>org.apache.tools.ant.types.selectors.FilenameSelector</code>
        </li>
        <li><a href="selectors.html#sizeselect">Size Selector</a> with
          classname <code>org.apache.tools.ant.types.selectors.SizeSelector</code>
        </li>
      </ul>
  
      <p>Here is the example from the Depth Selector section rewritten
      to use the selector through <code>&lt;custom&gt;</code>.</p>
  
      <blockquote><pre>
  &lt;fileset dir=&quot;${doc.path}&quot; includes=&quot;**/*&quot;&gt;
      &lt;custom classname=&quot;org.apache.tools.ant.types.selectors.DepthSelector&quot;&gt;
          &lt;param name=&quot;max&quot; value=&quot;1&quot;/&gt;
      &lt;/custom&gt;
  &lt;/fileset&gt;
        </pre></blockquote>
  
      <p>Selects all files in the base directory and one directory below
        that.</p>
  
      <h3><a name="filterreaders">Custom Filter Readers</a></h3>
      <p>
        Custom filter readers selectors are datatypes that implement
        <code>org.apache.tools.ant.types.filters.ChainableReader</code>.
      </p>
      <p>There is only one method required.
        <code>Reader chain(Reader reader)</code>.
        This returns a reader that filters input from the specified
        reader.
      </p>
      <p>
        For example a filterreader that removes every second character
        could be:
      </p>
      <blockquote>
        <pre>
  public class RemoveOddCharacters implements ChainableReader {
     public Reader chain(Reader reader) {
        return new BaseFilterReader(reader) {
            int count = 0;
            public int read() throws IOException {
                while (true) {
                  int c = in.read();
                  if (c == -1) {
                      return c;
                  }
                  count++;
                  if ((count % 2) == 1) {
                      return c;
                  }   
                }
            }
        }
     }
  }
        </pre>
      </blockquote>
      <p>
        For line oriented filters it may be easier to extend
        <code>ChainableFilterReader</code> an inner class of
        <code>org.apache.tools.ant.filters.TokenFilter</code>.
      </p>
      <p>
        For example a filter that appends the line number could be
      </p>
      <blockquote>
        <pre>
  public class AddLineNumber extends ChainableReaderFilter {
     private void lineNumber = 0;
     public String filter(String string) {
        lineNumber++;
        return "" + lineNumber + "\t" + string;
     }
  }
        </pre>
      </blockquote>
        
        
      <hr></hr>
      <p align="center">Copyright &copy; 2003 Apache Software Foundation. All rights
        Reserved.</p>
    </body>
  </html>
  
  
  
  

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


Mime
View raw message