Browse Source

Another try with delayed task Class creation and runtime replacement

of UE in refs.

Revert to 1.120 if any problem.

PR:
Obtained from:
Submitted by:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273650 13f79535-47bb-0310-9956-ffa450edef68
master
Costin Manolache 22 years ago
parent
commit
faf03ac9c1
1 changed files with 133 additions and 33 deletions
  1. +133
    -33
      src/main/org/apache/tools/ant/Project.java

+ 133
- 33
src/main/org/apache/tools/ant/Project.java View File

@@ -70,6 +70,7 @@ import org.apache.tools.ant.types.FilterSetCollection;
import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.JavaEnvUtils; import org.apache.tools.ant.util.JavaEnvUtils;
import org.apache.tools.ant.util.WeakishReference; import org.apache.tools.ant.util.WeakishReference;
import org.apache.tools.ant.util.LazyHashtable;


/** /**
* Central representation of an Ant project. This class defines an * Central representation of an Ant project. This class defines an
@@ -168,14 +169,14 @@ public class Project {
*/ */
private Hashtable inheritedProperties = new Hashtable(); private Hashtable inheritedProperties = new Hashtable();
/** Map of references within the project (paths etc) (String to Object). */ /** 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. */ /** Name of the project's default target. */
private String defaultTarget; private String defaultTarget;
/** Map from data type names to implementing classes (String to Class). */ /** 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). */ /** 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 * Map from task names to vectors of created tasks
* (String to Vector of Task). This is used to invalidate tasks if * (String to Vector of Task). This is used to invalidate tasks if
@@ -260,22 +261,9 @@ public class Project {
} }
props.load(in); props.load(in);
in.close(); 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) { } catch (IOException ioe) {
throw new BuildException("Can't load default task list"); throw new BuildException("Can't load default task list");
} }
@@ -291,19 +279,9 @@ public class Project {
props.load(in); props.load(in);
in.close(); 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) { } catch (IOException ioe) {
throw new BuildException("Can't load default datatype list"); throw new BuildException("Can't load default datatype list");
} }
@@ -790,7 +768,7 @@ public class Project {
this.baseDir = baseDir; this.baseDir = baseDir;
setPropertyInternal("basedir", this.baseDir.getPath()); setPropertyInternal("basedir", this.baseDir.getPath());
String msg = "Project base dir set to: " + this.baseDir; 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) { public void addReference(String name, Object value) {
synchronized (references) { synchronized (references) {
Object old = references.get(name);
Object old = ((AntRefTable)references).getReal(name);
if (old == value) { if (old == value) {
// no warning, this is not changing anything // no warning, this is not changing anything
return; 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;
}

}
} }

Loading…
Cancel
Save