Want to define your own selectors? It's easy!
First, pick the type of selector that you want to define. There are three types, and a recipe for each one follows. Chances are you'll want to work with the first one, Custom Selectors.
This is the category that Apache Ant provides specifically for you to
        define your own Selectors. Anywhere you want to use your selector
        you use the <custom> element and specify
        the class name of your selector within it. See the
        Custom Selectors
        section of the Selector page for details. The
        <custom> element can be used anywhere
        the core selectors can be used. It can be contained within
        Selector Containers,
        for example.
To create a new Custom Selector, you have to create a class that
        implements
        org.apache.tools.ant.types.selectors.ExtendFileSelector.
        The easiest way to do that is through the convenience base class
        org.apache.tools.ant.types.selectors.BaseExtendSelector,
        which provides all of the methods for supporting
        <param> tags. First, override the
        isSelected() method, and optionally the
        verifySettings() method. If your custom
        selector requires parameters to be set, you can also override
        the setParameters() 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.
These are the selectors used by Ant itself. To implement one of these, you will have to alter some of the classes contained within Ant.
First, create a class that implements
            org.apache.tools.ant.types.selectors.FileSelector.
            You can either choose to implement all methods yourself from
            scratch, or you can extend
            org.apache.tools.ant.types.selectors.BaseSelector
            instead, a convenience class that provides reasonable default
            behaviour for many methods.
There is only one method required.
            public boolean isSelected(File basedir, String filename,
              File file)
              is the real purpose of the whole exercise. It returns true
              or false depending on whether the given file should be
              selected from the list or not.
If you are using
            org.apache.tools.ant.types.selectors.BaseSelector
            there are also 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
            isSelected() method call validate() and
            a BuildException will be thrown with the contents of your error
            message. The validate() method also gives you a
            last chance to check your settings for consistency because it
            calls verifySettings(). Override this method and
            call setError() within it if you detect any
            problems in how your selector is set up.
You may also want to override toString().
Put an add method for your selector in
            org.apache.tools.ant.types.selectors.SelectorContainer.
            This is an interface, so you will also have to add an implementation
            for the method in the classes which implement it, namely
            org.apache.tools.ant.types.AbstractFileSet,
            org.apache.tools.ant.taskdefs.MatchingTask and
            org.apache.tools.ant.types.selectors.BaseSelectorContainer.
            Once it is in there, it will be available everywhere that core
            selectors are appropriate.
Got an idea for a new Selector Container? Creating a new one is no problem:
Create a new class that implements
            org.apache.tools.ant.types.selectors.SelectorContainer.
            This will ensure that your new
            Container can access any new selectors that come along. Again, there
            is a convenience class available for you called
            org.apache.tools.ant.types.selectors.BaseSelectorContainer.
            
Implement the
            public boolean isSelected(String filename, File file)
            method to do the right thing. Chances are you'll want to iterate
            over the selectors under you, so use
            selectorElements() to get an iterator that will do
            that.
Again, put an add method for your container in
            org.apache.tools.ant.types.selectors.SelectorContainer
            and its implementations
            org.apache.tools.ant.types.AbstractFileSet and
            org.apache.tools.ant.types.selectors.BaseSelectorContainer.
            
For a robust component (and selectors are (Project)Components) tests are necessary. For testing Tasks we use JUnit TestCases - more specific org.apache.tools.ant.BuildFileRule extends org.junit.rules.ExternalResource. Some of its features like configure the (test) project by reading its buildfile and execute targets we need for selector tests also. Therefore we use that BuildFileRule. But testing selectors requires some more work: having a set of files, instantiate and configure the selector, check the selection work and more. Because we usually extend BaseExtendSelector its features have to be tested also (e.g. setError()).
That's why we have a test rule for doing our selector tests: org.apache.tools.ant.types.selectors.BaseSelectorRule.
This class extends ExternalResource and therefore can included in the set of Ant's unit tests. It holds an instance of preconfigured BuildFileRule. Configuration is done by parsing the src/etc/testcases/types/selectors.xml. BaseSelectorRule then gives us helper methods for handling multiple selections.
Because the term "testcase" or "testenvironment" are so often used, this special testenvironment got a new name: bed. The setup and cleanup of the bed is all handled by the BaseSelectorRule so any test only has to handle the actual test scenarios
A usual test scenario is:
An example test would be:
package org.apache.tools.ant.types.selectors;
public class MySelectorTest {
    @Rule
    public final BaseSelectorRule selectorRule = new BaseSelectorRule();
    @Test
    public void testCase1() {
        // Configure the selector
        MySelector s = new MySelector();
        s.addParam("key1", "value1");
        s.addParam("key2", "value2");
        s.setXX(true);
        s.setYY("a value");
        // do the tests
        assertEquals("FTTTTTTTT", selectorRule.selectionString(s));
    }
}
    
    As an example of an error JUnit could log
    [junit]     FAILED
    [junit] Error for files: .;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz
    [junit] expected:<FTTTFTTTF...> but was:<TTTTTTTTT...>
    [junit] junit.framework.ComparisonFailure: Error for files: .;copy.filterset.filtered;tar/gz/asf-logo.gif.tar.gz
    [junit] expected:<FTTTFTTTF...> but was:<TTTTTTTTT...>
    [junit]     at junit.framework.Assert.assertEquals(Assert.java:81)
    [junit]     at org.apache.tools.ant.types.selectors.BaseSelectorTest.performTest(BaseSelectorTest.java:194)
    
    Described above the test class should provide a getInstance() method. But that isn't used here. The used getSelector() method is implemented in the base class and gives an instance of an Ant Project to the selector. This is usually done inside normal build file runs, but not inside this special environment, so this method gives the selector the ability to use its own Project object (getProject()), for example for logging.
During development and maybe later you sometimes need the output of information.
    Therefore Logging is needed. Because the selector extends BaseExtendSelector or directly
    BaseSelector it is an Ant DataType and therefore a ProjectComponent. 
    That means that you have access to the project object and its logging capability.
    ProjectComponent itself provides log methods which will do the
    access to the project instance. Logging is therefore done simply with:
    
        log( "message" );
    
    or
    
        log( "message" , loglevel );
    
    where the loglevel is one of the values