Hi,

One big problem with taskdef is that each task is created in a separate
class loader. This patch solves this by keeping caching the classloader
by the refid.

It also allows to define multiple tasks from a properties file ( the same
as native ant tasks are defined, or <property> reads properties ).

( I'm not sure what's my status, I used to have commit access on ant, but
it's a long time since I looked at the code - so I think it's better to
send a patch for someone more familiar with the code to commit. Strangely,
I'm listed as author on this file - but I can hardly recognize few lines
of code, it looks to good :-)

Thanks,
Costin

Index: src/main/org/apache/tools/ant/AntClassLoader.java
===================================================================
RCS file: 
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/AntClassLoader.java,v
retrieving revision 1.28
diff -u -r1.28 AntClassLoader.java
--- src/main/org/apache/tools/ant/AntClassLoader.java   2001/07/17 14:32:04     
1.28
+++ src/main/org/apache/tools/ant/AntClassLoader.java   2001/07/17 21:26:48
@@ -573,7 +573,6 @@

             if (file.isDirectory()) {
                 File resource = new File(file, resourceName);
-
                 if (resource.exists()) {
                     return new FileInputStream(resource);
                 }
Index: src/main/org/apache/tools/ant/taskdefs/Definer.java
===================================================================
RCS file: 
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Definer.java,v
retrieving revision 1.5
diff -u -r1.5 Definer.java
--- src/main/org/apache/tools/ant/taskdefs/Definer.java 2001/07/11 16:11:39     
1.5
+++ src/main/org/apache/tools/ant/taskdefs/Definer.java 2001/07/17 21:26:49
@@ -57,18 +57,28 @@
 import org.apache.tools.ant.*;
 import org.apache.tools.ant.types.*;

+import java.util.*;
+import java.io.*;
+
 /**
  * Base class for Taskdef and Typedef - does all the classpath
  * handling and and class loading.
  *
- * @author [EMAIL PROTECTED]
+ * @author Costin Manolache
  * @author <a href="[EMAIL PROTECTED]">Stefan Bodewig</a>
  */
 public abstract class Definer extends Task {
     private String name;
     private String value;
     private Path classpath;
+    private File file;
+    private String resource;

+    // used to load in the same classloader if the same path is used
+    // this works for classpathRef
+    private String refId;
+    private static Hashtable classLoaders=new Hashtable();
+
     public void setClasspath(Path classpath) {
         if (this.classpath == null) {
             this.classpath = classpath;
@@ -86,41 +96,96 @@

     public void setClasspathRef(Reference r) {
         createClasspath().setRefid(r);
+       refId=r.getRefId();
     }

     public void execute() throws BuildException {
-        if (name==null || value==null ) {
-            String msg = "name or classname attributes of "
-                + getTaskName() + " element "
-                + "are undefined";
-            throw new BuildException(msg);
-        }
-        try {
-            AntClassLoader al = null;
-            if (classpath != null) {
-                al = new AntClassLoader(project, classpath);
-            } else {
-                al = new AntClassLoader(project, Path.systemClasspath);
-            }
-            // need to load Task via system classloader or the new
-            // task we want to define will never be a Task but always
-            // be wrapped into a TaskAdapter.
-            al.addSystemPackageRoot("org.apache.tools.ant");
-
-            Class c = al.loadClass(value);
-            AntClassLoader.initializeClass(c);
-            addDefinition(name, c);
-        } catch (ClassNotFoundException cnfe) {
-            String msg = getTaskName()+" class " + value +
-                " cannot be found";
-            throw new BuildException(msg, cnfe, location);
-        } catch (NoClassDefFoundError ncdfe) {
-            String msg = getTaskName()+" class " + value +
-                " cannot be found";
-            throw new BuildException(msg, ncdfe, location);
-        }
+       AntClassLoader al=createLoader();
+
+       if (file==null && resource==null ) {
+           // simple case - one definition
+           if ( name==null || value==null  ) {
+               String msg = "name or classname attributes of "
+                   + getTaskName() + " element "
+                   + "are undefined";
+               throw new BuildException(msg);
+           }
+
+           addDefinition( al, name, value );
+       }
+
+       try {
+           Properties props=new Properties();
+           InputStream is=null;
+           if( file != null ) {
+               log("File Loading " + file, Project.MSG_VERBOSE);
+               is=new FileInputStream( file );
+           }
+           if( resource!=null ) {
+               log("Resource Loading " + resource, Project.MSG_VERBOSE);
+               is=al.getResourceAsStream( resource );
+           }
+           if( is!=null ) {
+               props.load( is );
+               Enumeration keys=props.keys();
+               while( keys.hasMoreElements() ) {
+                   String n=(String)keys.nextElement();
+                   String v=props.getProperty( n );
+                   addDefinition( al, n, v );
+               }
+           }
+       } catch( IOException ex ) {
+           throw new BuildException( ex );
+       }
+
     }
-
+
+    private void addDefinition( ClassLoader al, String name, String value ) {
+       try {
+           Class c = al.loadClass(value);
+           AntClassLoader.initializeClass(c);
+           addDefinition(name, c);
+       } catch (ClassNotFoundException cnfe) {
+           String msg = getTaskName()+" class " + value +
+               " cannot be found";
+           throw new BuildException(msg, cnfe, location);
+       } catch (NoClassDefFoundError ncdfe) {
+           String msg = getTaskName()+" class " + value +
+               " cannot be found";
+           throw new BuildException(msg, ncdfe, location);
+       }
+    }
+
+
+    private AntClassLoader createLoader() {
+       // XXX Why do we need a separate loader if no cpath is specified ??
+       AntClassLoader al = null;
+       if( refId != null )
+           al=(AntClassLoader)classLoaders.get( refId );
+       if( al!=null ) return al;
+       if (classpath != null) {
+           al = new AntClassLoader(project, classpath);
+       } else {
+           al = new AntClassLoader(project, Path.systemClasspath);
+       }
+       // need to load Task via system classloader or the new
+       // task we want to define will never be a Task but always
+       // be wrapped into a TaskAdapter.
+       al.addSystemPackageRoot("org.apache.tools.ant");
+
+       if( refId!=null )
+           classLoaders.put( refId, al );
+       return al;
+    }
+
+    public void setFile( File file ) {
+       this.file=file;
+    }
+
+    public void setResource( String res ) {
+       this.resource=res;
+    }
+
     public void setName( String name) {
         this.name = name;
     }

Reply via email to