FileDocCategorySizeDatePackage
ComponentHelper.javaAPI DocApache Ant 1.7038939Wed Dec 13 06:16:24 GMT 2006org.apache.tools.ant

ComponentHelper

public class ComponentHelper extends Object
Component creation and configuration. The class is based around handing component definitions in an AntTypeTable. The old task/type methods have been kept for backward compatibly. Project will just delegate its calls to this class. A very simple hook mechanism is provided that allows users to plug in custom code. It is also possible to replace the default behavior ( for example in an app embedding ant )
since
Ant1.6

Fields Summary
private AntTypeTable
antTypeTable
Map from component name to anttypedefinition
private Hashtable
taskClassDefinitions
Map of tasks generated from antTypeTable
private boolean
rebuildTaskClassDefinitions
flag to rebuild taskClassDefinitions
private Hashtable
typeClassDefinitions
Map of types generated from antTypeTable
private boolean
rebuildTypeClassDefinitions
flag to rebuild typeClassDefinitions
private Set
checkedNamespaces
Set of namespaces that have been checked for antlibs
private Stack
antLibStack
Stack of antlib contexts used to resolve definitions while processing antlib
private String
antLibCurrentUri
current antlib uri
private ComponentHelper
next
this does not appear to be used anywhere in the Ant codebase even via its accessors
private Project
project
Project that owns a component helper
private static final String
ERROR_NO_TASK_LIST_LOAD
Error string when the file taskdefs/defaults.properties cannot be found
private static final String
ERROR_NO_TYPE_LIST_LOAD
Error string when the typedefs/defaults.properties cannot be found
public static final String
COMPONENT_HELPER_REFERENCE
reference under which we register ourselves with a project -{@value}
private static final String
BUILD_SYSCLASSPATH_ONLY
string used to control build.syspath policy {@value}
private static final String
ANT_PROPERTY_TASK
special name of ant's property task -{@value}. There is some contrived work here to enable this early.
private static Properties[]
defaultDefinitions
Constructors Summary
protected ComponentHelper()
Creates a new ComponentHelper instance.

    
Methods Summary
public voidaddDataTypeDefinition(java.lang.String typeName, java.lang.Class typeClass)
Adds a new datatype definition. Attempting to override an existing definition with an equivalent one (i.e. with the same classname) results in a verbose log message. Attempting to override an existing definition with a different one results in a warning log message, but the definition is changed.

param
typeName The name of the datatype. Must not be null.
param
typeClass The full name of the class implementing the datatype. Must not be null.

        AntTypeDefinition def = new AntTypeDefinition();
        def.setName(typeName);
        def.setClass(typeClass);
        updateDataTypeDefinition(def);
        project.log(" +User datatype: " + typeName + "     "
                + typeClass.getName(), Project.MSG_DEBUG);
    
public voidaddDataTypeDefinition(AntTypeDefinition def)
Describe addDataTypeDefinition method here.

param
def an AntTypeDefinition value.

        updateDataTypeDefinition(def);
    
public voidaddTaskDefinition(java.lang.String taskName, java.lang.Class taskClass)
Adds a new task definition to the project. Attempting to override an existing definition with an equivalent one (i.e. with the same classname) results in a verbose log message. Attempting to override an existing definition with a different one results in a warning log message.

param
taskName The name of the task to add. Must not be null.
param
taskClass The full name of the class implementing the task. Must not be null.
exception
BuildException if the class is unsuitable for being an Ant task. An error level message is logged before this exception is thrown.
see
#checkTaskClass(Class)

        checkTaskClass(taskClass);
        AntTypeDefinition def = new AntTypeDefinition();
        def.setName(taskName);
        def.setClassLoader(taskClass.getClassLoader());
        def.setClass(taskClass);
        def.setAdapterClass(TaskAdapter.class);
        def.setClassName(taskClass.getName());
        def.setAdaptToClass(Task.class);
        updateDataTypeDefinition(def);
    
private synchronized voidcheckNamespace(java.lang.String componentName)
Called for each component name, check if the associated URI has been examined for antlibs.

        String uri = ProjectHelper.extractUriFromComponentName(componentName);
        if ("".equals(uri)) {
            uri = ProjectHelper.ANT_CORE_URI;
        }
        if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) {
            return; // namespace that does not contain antlib
        }
        if (checkedNamespaces.contains(uri)) {
            return; // Already processed
        }
        checkedNamespaces.add(uri);
        Typedef definer = new Typedef();
        definer.setProject(project);
        definer.init();
        definer.setURI(uri);
        //there to stop error messages being "null"
        definer.setTaskName(uri);
        //if this is left out, bad things happen. like all build files break
        //on the first element encountered.
        definer.setResource(Definer.makeResourceFromURI(uri));
        // a fishing expedition :- ignore errors if antlib not present
        definer.setOnError(new Typedef.OnError(Typedef.OnError.POLICY_IGNORE));
        definer.execute();
    
public voidcheckTaskClass(java.lang.Class taskClass)
Checks whether or not a class is suitable for serving as Ant task. Ant task implementation classes must be public, concrete, and have a no-arg constructor.

param
taskClass The class to be checked. Must not be null.
exception
BuildException if the class is unsuitable for being an Ant task. An error level message is logged before this exception is thrown.

        if (!Modifier.isPublic(taskClass.getModifiers())) {
            final String message = taskClass + " is not public";
            project.log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        if (Modifier.isAbstract(taskClass.getModifiers())) {
            final String message = taskClass + " is abstract";
            project.log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        try {
            taskClass.getConstructor((Class[]) null);
            // don't have to check for public, since
            // getConstructor finds public constructors only.
        } catch (NoSuchMethodException e) {
            final String message = "No public no-arg constructor in "
                    + taskClass;
            project.log(message, Project.MSG_ERR);
            throw new BuildException(message);
        }
        if (!Task.class.isAssignableFrom(taskClass)) {
            TaskAdapter.checkTaskClass(taskClass, project);
        }
    
public java.lang.ObjectcreateComponent(UnknownElement ue, java.lang.String ns, java.lang.String componentType)
Factory method to create the components. This should be called by UnknownElement.

param
ue The Unknown Element creating this component.
param
ns Namespace URI. Also available as ue.getNamespace().
param
componentType The component type, Also available as ue.getComponentName().
return
the created component.
throws
BuildException if an error occurs.

        Object component = createComponent(componentType);
        if (component instanceof Task) {
            Task task = (Task) component;
            task.setLocation(ue.getLocation());
            task.setTaskType(componentType);
            task.setTaskName(ue.getTaskName());
            task.setOwningTarget(ue.getOwningTarget());
            task.init();
        }
        return component;
    
public java.lang.ObjectcreateComponent(java.lang.String componentName)
Create an object for a component.

param
componentName the name of the component, if the component is in a namespace, the name is prefixed with the namespace uri and ":".
return
the class if found or null if not.

        AntTypeDefinition def = getDefinition(componentName);
        return (def == null) ? null : def.create(project);
    
public java.lang.ObjectcreateDataType(java.lang.String typeName)
Creates a new instance of a data type.

param
typeName The name of the data type to create an instance of. Must not be null.
return
an instance of the specified data type, or null if the data type name is not recognised.
exception
BuildException if the data type name is recognised but instance creation fails.

        return createComponent(typeName);
    
private TaskcreateNewTask(java.lang.String taskType)
Creates a new instance of a task.

since
ant1.6
param
taskType The name of the task to create an instance of. Must not be null.
return
an instance of the specified task, or null if the task name is not recognised.
exception
BuildException if the task name is recognised but task creation fails.

        Class c = getComponentClass(taskType);
        if (c == null || !(Task.class.isAssignableFrom(c))) {
            return null;
        }
        Object obj = createComponent(taskType);
        if (obj == null) {
            return null;
        }
        if (!(obj instanceof Task)) {
            throw new BuildException(
                "Expected a Task from '" + taskType
                + "' but got an instance of " + obj.getClass().getName()
                + " instead");
        }
        Task task = (Task) obj;
        task.setTaskType(taskType);

        // set default value, can be changed by the user
        task.setTaskName(taskType);

        project.log("   +Task: " + taskType, Project.MSG_DEBUG);
        return task;
    
public TaskcreateTask(java.lang.String taskType)
Creates a new instance of a task. Called from Project.createTask(), which can be called by tasks.

param
taskType The name of the task to create an instance of. Must not be null.
return
an instance of the specified task, or null if the task name is not recognised.
exception
BuildException if the task name is recognised but task creation fails.

        Task task = createNewTask(taskType);
        if (task == null && taskType.equals(ANT_PROPERTY_TASK)) {
            // quick fix for Ant.java use of property before
            // initializing the project
            addTaskDefinition(ANT_PROPERTY_TASK,
                              org.apache.tools.ant.taskdefs.Property.class);
            task = createNewTask(taskType);
        }
        return task;
    
public java.lang.StringdiagnoseCreationFailure(java.lang.String componentName, java.lang.String type)
Handler called to do decent diagnosis on instantiation failure.

param
componentName component name.
param
type component type, used in error messages
return
a string containing as much diagnostics info as possible.

        StringWriter errorText = new StringWriter();
        PrintWriter out = new PrintWriter(errorText);
        out.println("Problem: failed to create " + type + " " + componentName);
        //class of problem
        boolean lowlevel = false;
        boolean jars = false;
        boolean definitions = false;
        boolean antTask;
        String home = System.getProperty(Launcher.USER_HOMEDIR);
        File libDir = new File(home, Launcher.USER_LIBDIR);
        String antHomeLib;
        boolean probablyIDE = false;
        String anthome = System.getProperty(MagicNames.ANT_HOME);
        if (anthome != null) {
            File antHomeLibDir = new File(anthome, "lib");
            antHomeLib = antHomeLibDir.getAbsolutePath();
        } else {
            //running under an IDE that doesn't set ANT_HOME
            probablyIDE = true;
            antHomeLib = "ANT_HOME" + File.separatorChar + "lib";
        }
        StringBuffer dirListingText = new StringBuffer();
        final String tab = "        -";
        dirListingText.append(tab);
        dirListingText.append(antHomeLib);
        dirListingText.append('\n");
        if (probablyIDE) {
            dirListingText.append(tab);
            dirListingText.append("the IDE Ant configuration dialogs");
        } else {
            dirListingText.append(tab);
            dirListingText.append(libDir);
            dirListingText.append('\n");
            dirListingText.append(tab);
            dirListingText.append(
                    "a directory added on the command line with the -lib argument");
        }

        String dirListing = dirListingText.toString();

        //look up the name
        AntTypeDefinition def = getDefinition(componentName);
        if (def == null) {
            //not a known type
            boolean isAntlib = componentName.indexOf(MagicNames.ANTLIB_PREFIX) == 0;
            out.println("Cause: The name is undefined.");
            out.println("Action: Check the spelling.");
            out.println("Action: Check that any custom tasks/types have been declared.");
            out.println("Action: Check that any <presetdef>/<macrodef>"
                        + " declarations have taken place.");
            if (isAntlib) {
                out.println();
                out.println("This appears to be an antlib declaration. ");
                out.println("Action: Check that the implementing library exists in one of:");
                out.println(dirListing);
            }
            definitions = true;
        } else {
            //we are defined, so it is an instantiation problem
            final String classname = def.getClassName();
            antTask = classname.startsWith("org.apache.tools.ant.");
            boolean optional = classname.startsWith("org.apache.tools.ant.taskdefs.optional");
            optional |= classname.startsWith("org.apache.tools.ant.types.optional");

            //start with instantiating the class.
            Class clazz = null;
            try {
                clazz = def.innerGetTypeClass();
            } catch (ClassNotFoundException e) {
                out.println("Cause: the class " + classname + " was not found.");
                jars = true;
                if (optional) {
                    out.println("        This looks like one of Ant's optional components.");
                    out.println("Action: Check that the appropriate optional JAR exists in");
                    out.println(dirListing);
                } else {
                    out.println("Action: Check that the component has been correctly declared");
                    out.println("        and that the implementing JAR is in one of:");
                    out.println(dirListing);
                    definitions = true;
                }
            } catch (NoClassDefFoundError ncdfe) {
                jars = true;
                out.println("Cause: Could not load a dependent class "
                        +  ncdfe.getMessage());
                if (optional) {
                    out.println("       It is not enough to have Ant's optional JARs");
                    out.println("       you need the JAR files that the"
                                + " optional tasks depend upon.");
                    out.println("       Ant's optional task dependencies are"
                                + " listed in the manual.");
                } else {
                    out.println("       This class may be in a separate JAR"
                                + " that is not installed.");
                }
                out.println("Action: Determine what extra JAR files are"
                            + " needed, and place them in one of:");
                out.println(dirListing);
            }
            //here we successfully loaded the class or failed.
            if (clazz != null) {
                //success: proceed with more steps
                try {
                    def.innerCreateAndSet(clazz, project);
                    //hey, there is nothing wrong with us
                    out.println("The component could be instantiated.");
                } catch (NoSuchMethodException e) {
                    lowlevel = true;
                    out.println("Cause: The class " + classname
                            + " has no compatible constructor.");

                } catch (InstantiationException e) {
                    lowlevel = true;
                    out.println("Cause: The class " + classname
                            + " is abstract and cannot be instantiated.");
                } catch (IllegalAccessException e) {
                    lowlevel = true;
                    out.println("Cause: The constructor for " + classname
                            + " is private and cannot be invoked.");
                } catch (InvocationTargetException ex) {
                    lowlevel = true;
                    Throwable t = ex.getTargetException();
                    out.println("Cause: The constructor threw the exception");
                    out.println(t.toString());
                    t.printStackTrace(out);
                }  catch (NoClassDefFoundError ncdfe) {
                    jars = true;
                    out.println("Cause:  A class needed by class "
                            + classname + " cannot be found: ");
                    out.println("       " + ncdfe.getMessage());
                    out.println("Action: Determine what extra JAR files are"
                                + " needed, and place them in:");
                    out.println(dirListing);
                }
            }
            out.println();
            out.println("Do not panic, this is a common problem.");
            if (definitions) {
                out.println("It may just be a typographical error in the build file "
                        + "or the task/type declaration.");
            }
            if (jars) {
                out.println("The commonest cause is a missing JAR.");
            }
            if (lowlevel) {
                out.println("This is quite a low level problem, which may need "
                        + "consultation with the author of the task.");
                if (antTask) {
                    out.println("This may be the Ant team. Please file a "
                            + "defect or contact the developer team.");
                } else {
                    out.println("This does not appear to be a task bundled with Ant.");
                    out.println("Please take it up with the supplier of the third-party "
                            + type + ".");
                    out.println("If you have written it yourself, you probably have a bug to fix.");
                }
            } else {
                out.println();
                out.println("This is not a bug; it is a configuration problem");
            }
        }
        out.flush();
        out.close();
        return errorText.toString();
    
public voidenterAntLib(java.lang.String uri)
Called at the start of processing an antlib.

param
uri the uri that is associated with this antlib.

        antLibCurrentUri = uri;
        antLibStack.push(uri);
    
public voidexitAntLib()
Called at the end of processing an antlib.

        antLibStack.pop();
        antLibCurrentUri = (antLibStack.size() == 0)
            ? null : (String) antLibStack.peek();
    
public java.util.HashtablegetAntTypeTable()
Returns the current datatype definition hashtable. The returned hashtable is "live" and so should not be modified.

return
a map of from datatype name to implementing class (String to Class).

        return antTypeTable;
    
private java.lang.ClassLoadergetClassLoader(java.lang.ClassLoader classLoader)

        String buildSysclasspath = project.getProperty(MagicNames.BUILD_SYSCLASSPATH);
        if (project.getCoreLoader() != null
            && !(BUILD_SYSCLASSPATH_ONLY.equals(buildSysclasspath))) {
            classLoader = project.getCoreLoader();
        }
        return classLoader;
    
public java.lang.ClassgetComponentClass(java.lang.String componentName)
Return the class of the component name.

param
componentName the name of the component, if the component is in a namespace, the name is prefixed with the namespace uri and ":".
return
the class if found or null if not.

        AntTypeDefinition def = getDefinition(componentName);
        return (def == null) ? null : def.getExposedClass(project);
    
public static org.apache.tools.ant.ComponentHelpergetComponentHelper(Project project)
Find a project component for a specific project, creating it if it does not exist.

param
project the project.
return
the project component for a specific project.



                                    
         
        if (project == null) {
            return null;
        }
        // Singleton for now, it may change ( per/classloader )
        ComponentHelper ph = (ComponentHelper) project.getReference(
                COMPONENT_HELPER_REFERENCE);
        if (ph != null) {
            return ph;
        }
        ph = new ComponentHelper();
        ph.setProject(project);

        project.addReference(COMPONENT_HELPER_REFERENCE, ph);
        return ph;
    
public java.lang.StringgetCurrentAntlibUri()

return
the current antlib uri.

        return antLibCurrentUri;
    
public java.util.HashtablegetDataTypeDefinitions()
Returns the current type definition hashtable. The returned hashtable is "live" and so should not be modified.

return
a map of from type name to implementing class (String to Class).

        synchronized (typeClassDefinitions) {
            synchronized (antTypeTable) {
                if (rebuildTypeClassDefinitions) {
                    typeClassDefinitions.clear();
                    for (Iterator i = antTypeTable.keySet().iterator();
                         i.hasNext();) {
                        String name = (String) i.next();
                        Class clazz = antTypeTable.getExposedClass(name);
                        if (clazz == null) {
                            continue;
                        }
                        if (!(Task.class.isAssignableFrom(clazz))) {
                            typeClassDefinitions.put(
                                name, antTypeTable.getTypeClass(name));
                        }
                    }
                    rebuildTypeClassDefinitions = false;
                }
            }
        }
        return typeClassDefinitions;
    
private static synchronized java.util.PropertiesgetDefaultDefinitions(boolean type)
Load default task or type definitions - just the names, no class loading. Caches results between calls to reduce overhead.

param
type true for typedefs, false for taskdefs
return
a mapping from definition names to class names
throws
BuildException if there was some problem loading or parsing the definitions list

        int idx = type ? 1 : 0;
        if (defaultDefinitions[idx] == null) {
            String resource = type
                ? MagicNames.TYPEDEFS_PROPERTIES_RESOURCE
                : MagicNames.TASKDEF_PROPERTIES_RESOURCE;
            String errorString = type
                ? ERROR_NO_TYPE_LIST_LOAD
                : ERROR_NO_TASK_LIST_LOAD;
            InputStream in = null;
            try {
                in = ComponentHelper.class.getResourceAsStream(
                    resource);
                if (in == null) {
                    throw new BuildException(errorString);
                }
                Properties p = new Properties();
                p.load(in);
                defaultDefinitions[idx] = p;
            } catch (IOException e) {
                throw new BuildException(errorString, e);
            } finally {
                FileUtils.close(in);
            }
        }
        return defaultDefinitions[idx];
    
public AntTypeDefinitiongetDefinition(java.lang.String componentName)
Return the antTypeDefinition for a componentName.

param
componentName the name of the component.
return
the ant definition or null if not present.

        checkNamespace(componentName);
        return antTypeTable.getDefinition(componentName);
    
public java.lang.StringgetElementName(java.lang.Object element)
Returns a description of the type of the given element.

This is useful for logging purposes.

param
element The element to describe. Must not be null.
return
a description of the element type.
since
Ant 1.6

        return getElementName(element, false);
    
public java.lang.StringgetElementName(java.lang.Object o, boolean brief)
Returns a description of the type of the given element.

This is useful for logging purposes.

param
o The element to describe. Must not be null.
param
brief whether to use a brief description.
return
a description of the element type.
since
Ant 1.7

        //  PR: I do not know what to do if the object class
        //      has multiple defines
        //      but this is for logging only...
        Class elementClass = o.getClass();
        String elementClassname = elementClass.getName();
        for (Iterator i = antTypeTable.values().iterator(); i.hasNext();) {
            AntTypeDefinition def = (AntTypeDefinition) i.next();
            if (elementClassname.equals(def.getClassName())
                    && (elementClass == def.getExposedClass(project))) {
                String name = def.getName();
                return brief ? name : "The <" + name + "> type";
            }
        }
        return getUnmappedElementName(o.getClass(), brief);
    
public static java.lang.StringgetElementName(Project p, java.lang.Object o, boolean brief)
Convenient way to get some element name even when you may not have a Project context.

param
p The optional Project instance.
param
o The element to describe. Must not be null.
param
brief whether to use a brief description.
return
a description of the element type.
since
Ant 1.7

        if (p == null) {
            p = getProject(o);
        }
        return p == null ? getUnmappedElementName(o.getClass(), brief)
                : getComponentHelper(p).getElementName(o, brief);
    
public org.apache.tools.ant.ComponentHelpergetNext()
Get the next chained component helper.

return
the next chained component helper.

        return next;
    
private static ProjectgetProject(java.lang.Object o)

        if (o instanceof ProjectComponent) {
            return ((ProjectComponent) o).getProject();
        }
        try {
            Method m = o.getClass().getMethod("getProject", (Class[]) null);
            if (Project.class == m.getReturnType()) {
                return (Project) m.invoke(o, (Object[]) null);
            }
        } catch (Exception e) {
            //too bad
        }
        return null;
    
public java.util.HashtablegetTaskDefinitions()
Returns the current task definition hashtable. The returned hashtable is "live" and so should not be modified.

return
a map of from task name to implementing class (String to Class).

        synchronized (taskClassDefinitions) {
            synchronized (antTypeTable) {
                if (rebuildTaskClassDefinitions) {
                    taskClassDefinitions.clear();
                    for (Iterator i = antTypeTable.keySet().iterator();
                         i.hasNext();) {
                        String name = (String) i.next();
                        Class clazz = antTypeTable.getExposedClass(name);
                        if (clazz == null) {
                            continue;
                        }
                        if (Task.class.isAssignableFrom(clazz)) {
                            taskClassDefinitions.put(
                                name, antTypeTable.getTypeClass(name));
                        }
                    }
                    rebuildTaskClassDefinitions = false;
                }
            }
        }
        return taskClassDefinitions;
    
private static java.lang.StringgetUnmappedElementName(java.lang.Class c, boolean brief)

        if (brief) {
            String name = c.getName();
            return name.substring(name.lastIndexOf('.") + 1);
        }
        return c.toString();
    
public voidinitDefaultDefinitions()
This method is initialization code implementing the original ant component loading from /org/apache/tools/ant/taskdefs/default.properties and /org/apache/tools/ant/types/default.properties.

        initTasks();
        initTypes();
    
public voidinitSubProject(org.apache.tools.ant.ComponentHelper helper)
Used with creating child projects. Each child project inherits the component definitions from its parent.

param
helper the component helper of the parent project.

        // add the types of the parent project
        AntTypeTable typeTable = helper.antTypeTable;
        for (Iterator i = typeTable.values().iterator(); i.hasNext();) {
            AntTypeDefinition def = (AntTypeDefinition) i.next();
            antTypeTable.put(def.getName(), def);
        }
        // add the parsed namespaces of the parent project
        for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) {
            checkedNamespaces.add(i.next());
        }
    
private voidinitTasks()
Load ant's tasks.

        ClassLoader classLoader = getClassLoader(null);
        Properties props = getDefaultDefinitions(false);
        Enumeration e = props.propertyNames();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            String className = props.getProperty(name);
            AntTypeDefinition def = new AntTypeDefinition();
            def.setName(name);
            def.setClassName(className);
            def.setClassLoader(classLoader);
            def.setAdaptToClass(Task.class);
            def.setAdapterClass(TaskAdapter.class);
            antTypeTable.put(name, def);
        }
    
private voidinitTypes()
Load ant's datatypes.

        ClassLoader classLoader = getClassLoader(null);
        Properties props = getDefaultDefinitions(true);
        Enumeration e = props.propertyNames();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            String className = props.getProperty(name);
            AntTypeDefinition def = new AntTypeDefinition();
            def.setName(name);
            def.setClassName(className);
            def.setClassLoader(classLoader);
            antTypeTable.put(name, def);
        }
    
private booleansameDefinition(AntTypeDefinition def, AntTypeDefinition old)
Check if two definitions are the same.

param
def the new definition.
param
old the old definition.
return
true if the two definitions are the same.

        boolean defValid = validDefinition(def);
        boolean sameValidity = (defValid == validDefinition(old));
        //must have same validity; then if they are valid they must also be the same:
        return sameValidity && (!defValid || def.sameDefinition(old, project));
    
public voidsetNext(org.apache.tools.ant.ComponentHelper next)
Set the next chained component helper.

param
next the next chained component helper.

        this.next = next;
    
public voidsetProject(Project project)
Sets the project for this component helper.

param
project the project for this helper.

        this.project = project;
        antTypeTable = new AntTypeTable(project);
    
private voidupdateDataTypeDefinition(AntTypeDefinition def)
Update the component definition table with a new or modified definition.

param
def the definition to update or insert.

        String name = def.getName();
        synchronized (antTypeTable) {
            rebuildTaskClassDefinitions = true;
            rebuildTypeClassDefinitions = true;
            AntTypeDefinition old = antTypeTable.getDefinition(name);
            if (old != null) {
                if (sameDefinition(def, old)) {
                    return;
                }
                Class oldClass = antTypeTable.getExposedClass(name);
                boolean isTask =
                    (oldClass != null && Task.class.isAssignableFrom(oldClass));
                project.log("Trying to override old definition of "
                    + (isTask ? "task " : "datatype ") + name,
                    (def.similarDefinition(old, project))
                    ? Project.MSG_VERBOSE : Project.MSG_WARN);
            }
            project.log(" +Datatype " + name + " " + def.getClassName(),
                        Project.MSG_DEBUG);
            antTypeTable.put(name, def);
        }
    
private booleanvalidDefinition(AntTypeDefinition def)
Check if definition is a valid definition--it may be a definition of an optional task that does not exist.

param
def the definition to test.
return
true if exposed type of definition is present.

        return !(def.getTypeClass(project) == null
            || def.getExposedClass(project) == null);