@@ -70,6 +70,7 @@ import org.apache.tools.ant.types.FilterSetCollection;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.apache.tools.ant.util.WeakishReference;
import org.apache.tools.ant.util.LazyHashtable;
/**
* Central representation of an Ant project. This class defines an
@@ -168,14 +169,14 @@ public class Project {
*/
private Hashtable inheritedProperties = new Hashtable();
/** Map of references within the project (paths etc) (String to Object). */
private Hashtable references = new Hashtable( );
private Hashtable references = new AntRefTable(this );
/** Name of the project's default target. */
private String defaultTarget;
/** Map from data type names to implementing classes (String to Class). */
private Hashtable dataClassDefinitions = new Hashtable( );
private Hashtable dataClassDefinitions = new AntTaskTable(this, false );
/** Map from task names to implementing classes (String to Class). */
private Hashtable taskClassDefinitions = new Hashtable( );
private Hashtable taskClassDefinitions = new AntTaskTable(this, true );
/**
* Map from task names to vectors of created tasks
* (String to Vector of Task). This is used to invalidate tasks if
@@ -260,22 +261,9 @@ public class Project {
}
props.load(in);
in.close();
((AntTaskTable)taskClassDefinitions).addDefinitions( props );
Enumeration enum = props.propertyNames();
while (enum.hasMoreElements()) {
String key = (String) enum.nextElement();
String value = props.getProperty(key);
try {
Class taskClass = Class.forName(value);
addTaskDefinition(key, taskClass);
} catch (NoClassDefFoundError ncdfe) {
log("Could not load a dependent class ("
+ ncdfe.getMessage() + ") for task " + key, MSG_DEBUG);
} catch (ClassNotFoundException cnfe) {
log("Could not load class (" + value
+ ") for task " + key, MSG_DEBUG);
}
}
} catch (IOException ioe) {
throw new BuildException("Can't load default task list");
}
@@ -291,19 +279,9 @@ public class Project {
props.load(in);
in.close();
Enumeration enum = props.propertyNames();
while (enum.hasMoreElements()) {
String key = (String) enum.nextElement();
String value = props.getProperty(key);
try {
Class dataClass = Class.forName(value);
addDataTypeDefinition(key, dataClass);
} catch (NoClassDefFoundError ncdfe) {
// ignore...
} catch (ClassNotFoundException cnfe) {
// ignore...
}
}
((AntTaskTable)dataClassDefinitions).addDefinitions(props);
} catch (IOException ioe) {
throw new BuildException("Can't load default datatype list");
}
@@ -790,7 +768,7 @@ public class Project {
this.baseDir = baseDir;
setPropertyInternal("basedir", this.baseDir.getPath());
String msg = "Project base dir set to: " + this.baseDir;
log(msg, MSG_VERBOSE);
log(msg, MSG_VERBOSE);
}
/**
@@ -1793,7 +1771,7 @@ public class Project {
*/
public void addReference(String name, Object value) {
synchronized (references) {
Object old = references.get(name);
Object old = ((AntRefTable) references) .getReal (name);
if (old == value) {
// no warning, this is not changing anything
return;
@@ -2075,4 +2053,126 @@ public class Project {
}
// Should move to a separate public class - and have API to add
// listeners, etc.
private static class AntRefTable extends Hashtable {
Project project;
public AntRefTable(Project project) {
super();
this.project=project;
}
/** Returns the unmodified original object.
* This method should be called internally to
* get the 'real' object.
* The normal get method will do the replacement
* of UnknownElement ( this is similar with the JDNI
* refs behavior )
*/
public Object getReal(Object key ) {
return super.get( key );
}
/** Get method for the reference table.
* It can be used to hook dynamic references and to modify
* some references on the fly - for example for delayed
* evaluation.
*
* It is important to make sure that the processing that is
* done inside is not calling get indirectly.
*
* @param key
* @return
*/
public Object get(Object key) {
//System.out.println("AntRefTable.get " + key);
Object o=super.get(key);
if( o instanceof UnknownElement ) {
// Make sure that
((UnknownElement)o).maybeConfigure();
o=((UnknownElement)o).getTask();
}
return o;
}
}
private static class AntTaskTable extends LazyHashtable {
Project project;
Properties props;
boolean tasks=false;
public AntTaskTable( Project p, boolean tasks ) {
this.project=p;
this.tasks=tasks;
}
public void addDefinitions( Properties props ) {
this.props=props;
}
protected void initAll( ) {
if( initAllDone ) return;
project.log("InitAll", Project.MSG_DEBUG);
if( props==null ) return;
Enumeration enum = props.propertyNames();
while (enum.hasMoreElements()) {
String key = (String) enum.nextElement();
Class taskClass=getTask( key );
if( taskClass!=null ) {
// This will call a get() and a put()
if( tasks )
project.addTaskDefinition(key, taskClass);
else
project.addDataTypeDefinition(key, taskClass );
}
}
initAllDone=true;
}
protected Class getTask(String key) {
if( props==null ) return null; // for tasks loaded before init()
String value=props.getProperty(key);
if( value==null) {
//project.log( "No class name for " + key, Project.MSG_VERBOSE );
return null;
}
try {
Class taskClass=null;
if( project.getCoreLoader() != null &&
!("only".equals(project.getProperty("build.sysclasspath")))) {
try {
taskClass=project.getCoreLoader().loadClass(value);
if( taskClass != null ) return taskClass;
} catch( Exception ex ) {
}
}
taskClass = Class.forName(value);
return taskClass;
} catch (NoClassDefFoundError ncdfe) {
project.log("Could not load a dependent class ("
+ ncdfe.getMessage() + ") for task " + key, Project.MSG_DEBUG);
} catch (ClassNotFoundException cnfe) {
project.log("Could not load class (" + value
+ ") for task " + key, Project.MSG_DEBUG);
}
return null;
}
// Hashtable implementation
public Object get( Object key ) {
Object orig=super.get( key );
if( orig!= null ) return orig;
if( ! (key instanceof String) ) return null;
project.log("Get task " + key, Project.MSG_DEBUG );
Object taskClass=getTask( (String) key);
if( taskClass != null)
super.put( key, taskClass );
return taskClass;
}
public boolean contains( Object key ) {
return get( key ) != null;
}
}
}