jglick 2005/03/29 11:56:15
Modified: src/main/org/apache/tools/ant AntClassLoader.java
Project.java
src/main/org/apache/tools/ant/loader AntClassLoader2.java
Log:
#27285: simplify AntClassLoader by removing reflection hacks
(and separate ACL2) only needed for JDK 1.1 support.
Revision Changes Path
1.93 +226 -59 ant/src/main/org/apache/tools/ant/AntClassLoader.java
Index: AntClassLoader.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/AntClassLoader.java,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -r1.92 -r1.93
--- AntClassLoader.java 14 Mar 2005 09:19:27 -0000 1.92
+++ AntClassLoader.java 29 Mar 2005 19:56:15 -0000 1.93
@@ -14,6 +14,7 @@
* limitations under the License.
*
*/
+
package org.apache.tools.ant;
import java.io.ByteArrayOutputStream;
@@ -21,14 +22,22 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
+import java.util.StringTokenizer;
import java.util.Vector;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.tools.ant.types.Path;
@@ -192,6 +201,9 @@
*/
private Hashtable zipFiles = new Hashtable();
+ /** Static map of jar file/time to manifiest class-path entries */
+ private static Map/*<String,String>*/ pathMap =
Collections.synchronizedMap(new HashMap());
+
/**
* The context loader saved when setting the thread's current
* context loader.
@@ -203,36 +215,6 @@
private boolean isContextLoaderSaved = false;
/**
- * Reflection method reference for getProtectionDomain;
- * used to avoid 1.1-compatibility problems.
- */
- private static Method getProtectionDomain = null;
-
- /**
- * Reflection method reference for defineClassProtectionDomain;
- * used to avoid 1.1-compatibility problems.
- */
- private static Method defineClassProtectionDomain = null;
-
-
- // Set up the reflection-based Java2 methods if possible
- 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) {
- // ignore failure to get access to 1.2+ methods
- }
- }
-
-
- /**
* Create an Ant Class Loader
*/
public AntClassLoader() {
@@ -452,7 +434,9 @@
}
/**
- * Add a file to the path
+ * Add a file to the path.
+ * Reads the manifest, if available, and adds any additional class path
jars
+ * specified in the manifest.
*
* @param pathComponent the file which is to be added to the path for
* this class loader
@@ -461,6 +445,66 @@
*/
protected void addPathFile(File pathComponent) throws IOException {
pathComponents.addElement(pathComponent);
+ if (pathComponent.isDirectory()) {
+ return;
+ }
+
+ String absPathPlusTimeAndLength =
+ pathComponent.getAbsolutePath() + pathComponent.lastModified() +
"-"
+ + pathComponent.length();
+ String classpath = (String) pathMap.get(absPathPlusTimeAndLength);
+ if (classpath == null) {
+ ZipFile jarFile = null;
+ InputStream manifestStream = null;
+ try {
+ jarFile = new ZipFile(pathComponent);
+ manifestStream
+ = jarFile.getInputStream(new
ZipEntry("META-INF/MANIFEST.MF"));
+
+ if (manifestStream == null) {
+ return;
+ }
+ Reader manifestReader
+ = new InputStreamReader(manifestStream, "UTF-8");
+ org.apache.tools.ant.taskdefs.Manifest manifest
+ = new
org.apache.tools.ant.taskdefs.Manifest(manifestReader);
+ classpath
+ =
manifest.getMainSection().getAttributeValue("Class-Path");
+
+ } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
+ // ignore
+ } finally {
+ if (manifestStream != null) {
+ manifestStream.close();
+ }
+ if (jarFile != null) {
+ jarFile.close();
+ }
+ }
+ if (classpath == null) {
+ classpath = "";
+ }
+ pathMap.put(absPathPlusTimeAndLength, classpath);
+ }
+
+ if (!"".equals(classpath)) {
+ URL baseURL = FILE_UTILS.getFileURL(pathComponent);
+ StringTokenizer st = new StringTokenizer(classpath);
+ while (st.hasMoreTokens()) {
+ String classpathElement = st.nextToken();
+ URL libraryURL = new URL(baseURL, classpathElement);
+ if (!libraryURL.getProtocol().equals("file")) {
+ log("Skipping jar library " + classpathElement
+ + " since only relative URLs are supported by this"
+ + " loader", Project.MSG_VERBOSE);
+ continue;
+ }
+ File libraryFile = new File(libraryURL.getFile());
+ if (libraryFile.exists() && !isInPath(libraryFile)) {
+ addPathFile(libraryFile);
+ }
+ }
+ }
}
/**
@@ -1029,37 +1073,160 @@
*/
protected Class defineClassFromData(File container, byte[] classData,
String classname) throws IOException
{
- // Simply put:
- // defineClass(classname, classData, 0, classData.length,
- // Project.class.getProtectionDomain());
- // Made more elaborate to be 1.1-safe.
- if (defineClassProtectionDomain != null) {
+ definePackage(container, classname);
+ // XXX should instead make a new ProtectionDomain with a CodeSource
+ // corresponding to container.toURI().toURL() and the same
+ // PermissionCollection as Project.class.protectionDomain had
+ return defineClass(classname, classData, 0, classData.length,
+ Project.class.getProtectionDomain());
+ }
+
+ /**
+ * Define the package information associated with a class.
+ *
+ * @param container the file containing the class definition.
+ * @param className the class name of for which the package information
+ * is to be determined.
+ *
+ * @exception IOException if the package information cannot be read from
the
+ * container.
+ */
+ protected void definePackage(File container, String className)
+ throws IOException {
+ int classIndex = className.lastIndexOf('.');
+ if (classIndex == -1) {
+ return;
+ }
+
+ String packageName = className.substring(0, classIndex);
+ if (getPackage(packageName) != null) {
+ // already defined
+ return;
+ }
+
+ // define the package now
+ Manifest manifest = getJarManifest(container);
+
+ if (manifest == null) {
+ definePackage(packageName, null, null, null, null, null,
+ null, null);
+ } else {
+ definePackage(container, packageName, manifest);
+ }
+ }
+
+ /**
+ * Get the manifest from the given jar, if it is indeed a jar and it has
a
+ * manifest
+ *
+ * @param container the File from which a manifest is required.
+ *
+ * @return the jar's manifest or null is the container is not a jar or it
+ * has no manifest.
+ *
+ * @exception IOException if the manifest cannot be read.
+ */
+ private Manifest getJarManifest(File container) throws IOException {
+ if (container.isDirectory()) {
+ return null;
+ }
+ JarFile jarFile = null;
+ try {
+ jarFile = new JarFile(container);
+ return jarFile.getManifest();
+ } finally {
+ if (jarFile != null) {
+ jarFile.close();
+ }
+ }
+ }
+
+ /**
+ * Define the package information when the class comes from a
+ * jar with a manifest
+ *
+ * @param container the jar file containing the manifest
+ * @param packageName the name of the package being defined.
+ * @param manifest the jar's manifest
+ */
+ protected void definePackage(File container, String packageName,
+ Manifest manifest) {
+ String sectionName = packageName.replace('.', '/') + "/";
+
+ String specificationTitle = null;
+ String specificationVendor = null;
+ String specificationVersion = null;
+ String implementationTitle = null;
+ String implementationVendor = null;
+ String implementationVersion = null;
+ String sealedString = null;
+ URL sealBase = null;
+
+ Attributes sectionAttributes = manifest.getAttributes(sectionName);
+ if (sectionAttributes != null) {
+ specificationTitle
+ = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
+ specificationVendor
+ = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
+ specificationVersion
+ = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
+ implementationTitle
+ = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
+ implementationVendor
+ = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
+ implementationVersion
+ = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
+ sealedString
+ = sectionAttributes.getValue(Name.SEALED);
+ }
+
+ Attributes mainAttributes = manifest.getMainAttributes();
+ if (mainAttributes != null) {
+ if (specificationTitle == null) {
+ specificationTitle
+ = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
+ }
+ if (specificationVendor == null) {
+ specificationVendor
+ = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
+ }
+ if (specificationVersion == null) {
+ specificationVersion
+ = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
+ }
+ if (implementationTitle == null) {
+ implementationTitle
+ = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
+ }
+ if (implementationVendor == null) {
+ implementationVendor
+ = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
+ }
+ if (implementationVersion == null) {
+ implementationVersion
+ = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
+ }
+ if (sealedString == null) {
+ sealedString
+ = mainAttributes.getValue(Name.SEALED);
+ }
+ }
+
+ if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
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 if (t instanceof NoClassDefFoundError) {
- throw (NoClassDefFoundError) t;
- } else if (t instanceof SecurityException) {
- throw (SecurityException) t;
- } else {
- throw new IOException(t.toString());
- }
- } catch (Exception e) {
- throw new IOException(e.toString());
+ // XXX should be using FileUtils!
+ sealBase = new URL("file:" + container.getPath());
+ } catch (MalformedURLException e) {
+ // ignore
}
- } else {
- return defineClass(classname, classData, 0, classData.length);
}
+
+ definePackage(packageName, specificationTitle, specificationVersion,
+ specificationVendor, implementationTitle,
+ implementationVersion, implementationVendor, sealBase);
}
+
/**
* Reads a class definition from a stream.
*
1.189 +1 -4 ant/src/main/org/apache/tools/ant/Project.java
Index: Project.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/Project.java,v
retrieving revision 1.188
retrieving revision 1.189
diff -u -r1.188 -r1.189
--- Project.java 9 Mar 2005 00:20:42 -0000 1.188
+++ Project.java 29 Mar 2005 19:56:15 -0000 1.189
@@ -33,7 +33,6 @@
import java.util.HashSet;
import org.apache.tools.ant.input.DefaultInputHandler;
import org.apache.tools.ant.input.InputHandler;
-import org.apache.tools.ant.loader.AntClassLoader2;
import org.apache.tools.ant.helper.DefaultExecutor;
import org.apache.tools.ant.helper.KeepGoingExecutor;
import org.apache.tools.ant.types.FilterSet;
@@ -44,7 +43,6 @@
import org.apache.tools.ant.util.JavaEnvUtils;
import org.apache.tools.ant.util.StringUtils;
-
/**
* Central representation of an Ant project. This class defines an
* Ant project with all of its targets, tasks and various other
@@ -56,7 +54,6 @@
* file paths at runtime.
*
*/
-
public class Project {
/** Message priority of "error". */
public static final int MSG_ERR = 0;
@@ -270,7 +267,7 @@
* @return an appropriate classloader.
*/
public AntClassLoader createClassLoader(Path path) {
- AntClassLoader loader = new AntClassLoader2();
+ AntClassLoader loader = new AntClassLoader();
loader.setProject(this);
loader.setClassPath(path);
return loader;
1.14 +3 -276
ant/src/main/org/apache/tools/ant/loader/AntClassLoader2.java
Index: AntClassLoader2.java
===================================================================
RCS file:
/home/cvs/ant/src/main/org/apache/tools/ant/loader/AntClassLoader2.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- AntClassLoader2.java 6 Jan 2005 12:05:10 -0000 1.13
+++ AntClassLoader2.java 29 Mar 2005 19:56:15 -0000 1.14
@@ -14,287 +14,14 @@
* limitations under the License.
*
*/
+
package org.apache.tools.ant.loader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
import org.apache.tools.ant.AntClassLoader;
-import org.apache.tools.ant.Project;
-import java.util.jar.Manifest;
-import java.util.jar.JarFile;
-import java.util.zip.ZipFile;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.util.zip.ZipEntry;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.StringTokenizer;
-import org.apache.tools.ant.util.FileUtils;
/**
- * An implementation of the AntClassLoader suitable for use on post JDK 1.1
- * platforms
- *
+ * @deprecated Just use [EMAIL PROTECTED] AntClassLoader} itself.
*/
public class AntClassLoader2 extends AntClassLoader {
- /** Instance of a utility class to use for file operations. */
- private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
-
- /** Static map of jar file/time to manifiest class-path entries */
- private static Map pathMap = Collections.synchronizedMap(new HashMap());
-
- /**
- * Constructor
- */
- public AntClassLoader2() {
- }
-
- /**
- * Define a class given its bytes
- *
- * @param container the container from which the class data has been read
- * may be a directory or a jar/zip file.
- *
- * @param classData the bytecode data for the class
- * @param className the name of the class
- *
- * @return the Class instance created from the given data
- *
- * @throws IOException if the class data cannot be read.
- */
- protected Class defineClassFromData(File container, byte[] classData,
- String className) throws IOException
{
-
- definePackage(container, className);
- return defineClass(className, classData, 0, classData.length,
- Project.class.getProtectionDomain());
-
- }
-
- /**
- * Get the manifest from the given jar, if it is indeed a jar and it has
a
- * manifest
- *
- * @param container the File from which a manifest is required.
- *
- * @return the jar's manifest or null is the container is not a jar or it
- * has no manifest.
- *
- * @exception IOException if the manifest cannot be read.
- */
- private Manifest getJarManifest(File container) throws IOException {
- if (container.isDirectory()) {
- return null;
- }
- JarFile jarFile = null;
- try {
- jarFile = new JarFile(container);
- return jarFile.getManifest();
- } finally {
- if (jarFile != null) {
- jarFile.close();
- }
- }
- }
-
- /**
- * Define the package information associated with a class.
- *
- * @param container the file containing the class definition.
- * @param className the class name of for which the package information
- * is to be determined.
- *
- * @exception IOException if the package information cannot be read from
the
- * container.
- */
- protected void definePackage(File container, String className)
- throws IOException {
- int classIndex = className.lastIndexOf('.');
- if (classIndex == -1) {
- return;
- }
-
- String packageName = className.substring(0, classIndex);
- if (getPackage(packageName) != null) {
- // already defined
- return;
- }
-
- // define the package now
- Manifest manifest = getJarManifest(container);
-
- if (manifest == null) {
- definePackage(packageName, null, null, null, null, null,
- null, null);
- } else {
- definePackage(container, packageName, manifest);
- }
- }
-
- /**
- * Define the package information when the class comes from a
- * jar with a manifest
- *
- * @param container the jar file containing the manifest
- * @param packageName the name of the package being defined.
- * @param manifest the jar's manifest
- */
- protected void definePackage(File container, String packageName,
- Manifest manifest) {
- String sectionName = packageName.replace('.', '/') + "/";
-
- String specificationTitle = null;
- String specificationVendor = null;
- String specificationVersion = null;
- String implementationTitle = null;
- String implementationVendor = null;
- String implementationVersion = null;
- String sealedString = null;
- URL sealBase = null;
-
- Attributes sectionAttributes = manifest.getAttributes(sectionName);
- if (sectionAttributes != null) {
- specificationTitle
- = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
- specificationVendor
- = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
- specificationVersion
- = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
- implementationTitle
- = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
- implementationVendor
- = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
- implementationVersion
- = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
- sealedString
- = sectionAttributes.getValue(Name.SEALED);
- }
-
- Attributes mainAttributes = manifest.getMainAttributes();
- if (mainAttributes != null) {
- if (specificationTitle == null) {
- specificationTitle
- = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
- }
- if (specificationVendor == null) {
- specificationVendor
- = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
- }
- if (specificationVersion == null) {
- specificationVersion
- = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
- }
- if (implementationTitle == null) {
- implementationTitle
- = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
- }
- if (implementationVendor == null) {
- implementationVendor
- = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
- }
- if (implementationVersion == null) {
- implementationVersion
- = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
- }
- if (sealedString == null) {
- sealedString
- = mainAttributes.getValue(Name.SEALED);
- }
- }
-
- if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
- try {
- sealBase = new URL("file:" + container.getPath());
- } catch (MalformedURLException e) {
- // ignore
- }
- }
-
- definePackage(packageName, specificationTitle, specificationVersion,
- specificationVendor, implementationTitle,
- implementationVersion, implementationVendor, sealBase);
- }
-
-
- /**
- * Add a file to the path. This classloader reads the manifest, if
- * available, and adds any additional class path jars specified in the
- * manifest.
- *
- * @param pathComponent the file which is to be added to the path for
- * this class loader
- *
- * @throws IOException if data needed from the file cannot be read.
- */
- protected void addPathFile(File pathComponent) throws IOException {
- super.addPathFile(pathComponent);
-
- if (pathComponent.isDirectory()) {
- return;
- }
-
- String absPathPlusTimeAndLength =
- pathComponent.getAbsolutePath() + pathComponent.lastModified() +
"-"
- + pathComponent.length();
- String classpath = (String) pathMap.get(absPathPlusTimeAndLength);
- if (classpath == null) {
- ZipFile jarFile = null;
- InputStream manifestStream = null;
- try {
- jarFile = new ZipFile(pathComponent);
- manifestStream
- = jarFile.getInputStream(new
ZipEntry("META-INF/MANIFEST.MF"));
-
- if (manifestStream == null) {
- return;
- }
- Reader manifestReader
- = new InputStreamReader(manifestStream, "UTF-8");
- org.apache.tools.ant.taskdefs.Manifest manifest
- = new
org.apache.tools.ant.taskdefs.Manifest(manifestReader);
- classpath
- =
manifest.getMainSection().getAttributeValue("Class-Path");
-
- } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
- // ignore
- } finally {
- if (manifestStream != null) {
- manifestStream.close();
- }
- if (jarFile != null) {
- jarFile.close();
- }
- }
- if (classpath == null) {
- classpath = "";
- }
- pathMap.put(absPathPlusTimeAndLength, classpath);
- }
-
- if (!"".equals(classpath)) {
- URL baseURL = FILE_UTILS.getFileURL(pathComponent);
- StringTokenizer st = new StringTokenizer(classpath);
- while (st.hasMoreTokens()) {
- String classpathElement = st.nextToken();
- URL libraryURL = new URL(baseURL, classpathElement);
- if (!libraryURL.getProtocol().equals("file")) {
- log("Skipping jar library " + classpathElement
- + " since only relative URLs are supported by this"
- + " loader", Project.MSG_VERBOSE);
- continue;
- }
- File libraryFile = new File(libraryURL.getFile());
- if (libraryFile.exists() && !isInPath(libraryFile)) {
- addPathFile(libraryFile);
- }
- }
- }
- }
+ public AntClassLoader2() {}
}
-
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]