No reply to this one yet, so gently asking again whether this will make
it into 1.3, or whether I will need to ship a patched ant.jar with
NetBeans...doable but not desirable.
#1 is the important part, since without this nothing works inside the
IDE. So I am reattaching it, this time as a standalone patch without #2.
Original description below for reference.
For #2, it may suffice for NetBeans to automatically define some
additional properties, like:
-Dnetbeans.filesystems.path=/my/sources/part1:/my/sources/part2
and so on (taken from GUI project configuration). Then
<taskdef name="foo" classname="MyCustomTask"/>
will still not work, but this more explicit version will:
<taskdef name="foo" classname="MyCustomTask">
<classpath>
<pathelement path="${netbeans.filesystems.path}"/>
</classpath>
</taskdef>
I tried this and it seems OK, provided AntClassLoader is patched.
Thanks,
-Jesse
Jesse Glick wrote:
> 1. AntClassLoader. [This patch can actually stand on its own, if the one
> reference to project.getDefaultClassLoader() is changed to e.g.
> AntClassLoader.class.getClassLoader().] AntClassLoader currently when
> trying to resolve "system" classes, uses the primordial classloader. If
> Ant itself was *not* loaded with the primordial classloader, this is
> unworkable: e.g. a user task may be loadable but Task itself is not
> (from within that AntClassLoader) -> NoClassDefFoundError when
> resolving. The patch simply makes the loading work logically, wherever
> Ant itself was loaded from.
>
> Furthermore, previously AntClassLoader under Java 2 would provide no
> permissions for loaded classes. This means that in a VM with an
> installed security manager, any task performing a controlled action
> (pretty much any task at all: e.g. open a file, ...) would throw
> AccessControlException and be useless. The patch (under Java 2) supplies
> loaded classes with the same permissions as Ant itself (matching the
> commandline behavior), under the assumption that tasks and build scripts
> are trusted and there is no sandboxing needed or wanted. Under JDK 1.1,
> it should compile (note the reflection calls) but do nothing different;
> someone with a 1.1 installation, please double-check!
--
Jesse Glick <mailto:[EMAIL PROTECTED]>
NetBeans, Open APIs <http://www.netbeans.org/>
tel (+4202) 3300-9161 Sun Micro x49161 Praha CRIndex: src/main/org/apache/tools/ant/AntClassLoader.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/AntClassLoader.java,v
retrieving revision 1.13
diff -c -t -r1.13 AntClassLoader.java
*** src/main/org/apache/tools/ant/AntClassLoader.java 2001/01/19 13:27:00
1.13
--- src/main/org/apache/tools/ant/AntClassLoader.java 2001/01/31 12:34:27
***************
*** 54,59 ****
--- 54,60 ----
package org.apache.tools.ant;
+ import java.lang.reflect.*;
import java.util.*;
import java.util.zip.*;
import java.io.*;
***************
*** 198,204 ****
Class theClass = findLoadedClass(classname);
if (theClass == null) {
! theClass = findSystemClass(classname);
}
return theClass;
--- 199,205 ----
Class theClass = findLoadedClass(classname);
if (theClass == null) {
! theClass = findBaseClass(classname);
}
return theClass;
***************
*** 325,331 ****
if (theClass == null) {
if (useSystemFirst) {
try {
! theClass = findSystemClass(classname);
project.log("Class " + classname + " loaded from system
loader", Project.MSG_DEBUG);
}
catch (ClassNotFoundException cnfe) {
--- 326,332 ----
if (theClass == null) {
if (useSystemFirst) {
try {
! theClass = findBaseClass(classname);
project.log("Class " + classname + " loaded from system
loader", Project.MSG_DEBUG);
}
catch (ClassNotFoundException cnfe) {
***************
*** 339,345 ****
project.log("Class " + classname + " loaded from ant
loader", Project.MSG_DEBUG);
}
catch (ClassNotFoundException cnfe) {
! theClass = findSystemClass(classname);
project.log("Class " + classname + " loaded from system
loader", Project.MSG_DEBUG);
}
}
--- 340,346 ----
project.log("Class " + classname + " loaded from ant
loader", Project.MSG_DEBUG);
}
catch (ClassNotFoundException cnfe) {
! theClass = findBaseClass(classname);
project.log("Class " + classname + " loaded from system
loader", Project.MSG_DEBUG);
}
}
***************
*** 387,393 ****
byte[] classData = baos.toByteArray();
! return defineClass(classname, classData, 0, classData.length);
}
--- 388,430 ----
byte[] classData = baos.toByteArray();
! // Simply put:
! // defineClass(classname, classData, 0, classData.length,
Project.class.getProtectionDomain());
! // Made more elaborate to be 1.1-safe.
! if (defineClassProtectionDomain != null) {
! try {
! Object domain = getProtectionDomain.invoke(Project.class, new
Object[0]);
! Object[] args = new Object[] {classname, classData, new
Integer(0), new Integer(classData.length), domain};
! return (Class)defineClassProtectionDomain.invoke(this, args);
! }
! catch (InvocationTargetException ite) {
! Throwable t = ite.getTargetException();
! if (t instanceof ClassFormatError) {
! throw (ClassFormatError)t;
! }
! else {
! throw new IOException(t.toString());
! }
! }
! catch (Exception e) {
! throw new IOException(e.toString());
! }
! }
! else {
! return defineClass(classname, classData, 0, classData.length);
! }
! }
!
! private static Method getProtectionDomain = null;
! private static Method defineClassProtectionDomain = null;
! static {
! try {
! getProtectionDomain =
Class.class.getMethod("getProtectionDomain", new Class[0]);
! Class protectionDomain =
Class.forName("java.security.ProtectionDomain");
! Class[] args = new Class[] {String.class, byte[].class,
Integer.TYPE, Integer.TYPE, protectionDomain};
! defineClassProtectionDomain =
ClassLoader.class.getDeclaredMethod("defineClass", args);
! }
! catch (Exception e) {}
}
***************
*** 445,450 ****
--- 482,500 ----
}
}
catch (IOException e) {}
+ }
+ }
+
+ /**
+ * Find a system class (which should be loaded from the same classloader
as the Ant core).
+ */
+ private Class findBaseClass(String name) throws ClassNotFoundException {
+ ClassLoader base = AntClassLoader.class.getClassLoader();
+ if (base == null) {
+ return findSystemClass(name);
+ }
+ else {
+ return base.loadClass(name);
}
}
}