Fields Summary |
---|
private AntTypeTable | antTypeTableMap from component name to anttypedefinition |
private Hashtable | taskClassDefinitionsMap of tasks generated from antTypeTable |
private boolean | rebuildTaskClassDefinitionsflag to rebuild taskClassDefinitions |
private Hashtable | typeClassDefinitionsMap of types generated from antTypeTable |
private boolean | rebuildTypeClassDefinitionsflag to rebuild typeClassDefinitions |
private Set | checkedNamespacesSet of namespaces that have been checked for antlibs |
private Stack | antLibStackStack of antlib contexts used to resolve definitions while
processing antlib |
private String | antLibCurrentUricurrent antlib uri |
private ComponentHelper | nextthis does not appear to be used anywhere in the Ant codebase
even via its accessors |
private Project | projectProject that owns a component helper |
private static final String | ERROR_NO_TASK_LIST_LOADError string when the file taskdefs/defaults.properties cannot be found |
private static final String | ERROR_NO_TYPE_LIST_LOADError string when the typedefs/defaults.properties cannot be found |
public static final String | COMPONENT_HELPER_REFERENCEreference under which we register ourselves with a project -{@value} |
private static final String | BUILD_SYSCLASSPATH_ONLYstring used to control build.syspath policy {@value} |
private static final String | ANT_PROPERTY_TASKspecial name of ant's property task -{@value}. There is some
contrived work here to enable this early. |
private static Properties[] | defaultDefinitions |
Methods Summary |
---|
public void | addDataTypeDefinition(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.
AntTypeDefinition def = new AntTypeDefinition();
def.setName(typeName);
def.setClass(typeClass);
updateDataTypeDefinition(def);
project.log(" +User datatype: " + typeName + " "
+ typeClass.getName(), Project.MSG_DEBUG);
|
public void | addDataTypeDefinition(AntTypeDefinition def)Describe addDataTypeDefinition method here.
updateDataTypeDefinition(def);
|
public void | addTaskDefinition(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.
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 void | checkNamespace(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 void | checkTaskClass(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.
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.Object | createComponent(UnknownElement ue, java.lang.String ns, java.lang.String componentType)Factory method to create the components.
This should be called by UnknownElement.
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.Object | createComponent(java.lang.String componentName)Create an object for a component.
AntTypeDefinition def = getDefinition(componentName);
return (def == null) ? null : def.create(project);
|
public java.lang.Object | createDataType(java.lang.String typeName)Creates a new instance of a data type.
return createComponent(typeName);
|
private Task | createNewTask(java.lang.String taskType)Creates a new instance of a task.
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 Task | createTask(java.lang.String taskType)Creates a new instance of a task.
Called from Project.createTask(), which can be called by tasks.
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.String | diagnoseCreationFailure(java.lang.String componentName, java.lang.String type)Handler called to do decent diagnosis on instantiation failure.
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 void | enterAntLib(java.lang.String uri)Called at the start of processing an antlib.
antLibCurrentUri = uri;
antLibStack.push(uri);
|
public void | exitAntLib()Called at the end of processing an antlib.
antLibStack.pop();
antLibCurrentUri = (antLibStack.size() == 0)
? null : (String) antLibStack.peek();
|
public java.util.Hashtable | getAntTypeTable()Returns the current datatype definition hashtable. The returned
hashtable is "live" and so should not be modified.
return antTypeTable;
|
private java.lang.ClassLoader | getClassLoader(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.Class | getComponentClass(java.lang.String componentName)Return the class of the component name.
AntTypeDefinition def = getDefinition(componentName);
return (def == null) ? null : def.getExposedClass(project);
|
public static org.apache.tools.ant.ComponentHelper | getComponentHelper(Project project)Find a project component for a specific project, creating
it if it does not exist.
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.String | getCurrentAntlibUri()
return antLibCurrentUri;
|
public java.util.Hashtable | getDataTypeDefinitions()Returns the current type definition hashtable. The returned hashtable is
"live" and so should not be modified.
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.Properties | getDefaultDefinitions(boolean type)Load default task or type definitions - just the names,
no class loading.
Caches results between calls to reduce overhead.
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 AntTypeDefinition | getDefinition(java.lang.String componentName)Return the antTypeDefinition for a componentName.
checkNamespace(componentName);
return antTypeTable.getDefinition(componentName);
|
public java.lang.String | getElementName(java.lang.Object element)Returns a description of the type of the given element.
This is useful for logging purposes.
return getElementName(element, false);
|
public java.lang.String | getElementName(java.lang.Object o, boolean brief)Returns a description of the type of the given element.
This is useful for logging purposes.
// 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.String | getElementName(Project p, java.lang.Object o, boolean brief)Convenient way to get some element name even when you may not have a
Project context.
if (p == null) {
p = getProject(o);
}
return p == null ? getUnmappedElementName(o.getClass(), brief)
: getComponentHelper(p).getElementName(o, brief);
|
public org.apache.tools.ant.ComponentHelper | getNext()Get the next chained component helper.
return next;
|
private static Project | getProject(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.Hashtable | getTaskDefinitions()Returns the current task definition hashtable. The returned hashtable is
"live" and so should not be modified.
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.String | getUnmappedElementName(java.lang.Class c, boolean brief)
if (brief) {
String name = c.getName();
return name.substring(name.lastIndexOf('.") + 1);
}
return c.toString();
|
public void | initDefaultDefinitions()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 void | initSubProject(org.apache.tools.ant.ComponentHelper helper)Used with creating child projects. Each child
project inherits the component definitions
from its parent.
// 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 void | initTasks()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 void | initTypes()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 boolean | sameDefinition(AntTypeDefinition def, AntTypeDefinition old)Check if 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 void | setNext(org.apache.tools.ant.ComponentHelper next)Set the next chained component helper.
this.next = next;
|
public void | setProject(Project project)Sets the project for this component helper.
this.project = project;
antTypeTable = new AntTypeTable(project);
|
private void | updateDataTypeDefinition(AntTypeDefinition def)Update the component definition table with a new or
modified definition.
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 boolean | validDefinition(AntTypeDefinition def)Check if definition is a valid definition--it may be a
definition of an optional task that does not exist.
return !(def.getTypeClass(project) == null
|| def.getExposedClass(project) == null);
|