Patch for ClassLoader

Niklas Mehner <[email protected]>
Newsgroups gmane.comp.jakarta.bcel.devel
Message-ID <[email protected]>
Hi!

I had some problems, when trying to "stack" the 
org.apache.bcel.util.ClassLoader (use the result of a ClassLoader and 
modify the resulting batecode with a different ClassLoader).

This does not work, because ClassLoader does not override 
getResourceAsStream(). getResourceAsStream(Classname) returns the 
original bytecode, even if loadClass() returns a modified class.

The attached patch fixes this.

Also can you add hansel (http://hansel.sourceforge.net, a code coverage 
testing extension to JUnit) to the list of projects using BCEL?

thanks,
   Niklas

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
patch.txt (text/plain, 4.4 KB)
? patch.txt
Index: ClassLoader.java
===================================================================
RCS file: /home/cvspublic/jakarta-bcel/src/java/org/apache/bcel/util/ClassLoader.java,v
retrieving revision 1.6
diff -u -r1.6 ClassLoader.java
--- ClassLoader.java	13 Jun 2002 09:32:50 -0000	1.6
+++ ClassLoader.java	4 Apr 2003 09:36:53 -0000
@@ -84,6 +84,8 @@
  */
 public class ClassLoader extends java.lang.ClassLoader {
   private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe
+  private Hashtable javaClasses = new Hashtable();
+
   private String[] ignored_packages = {
     "java.", "javax.", "sun."
   };
@@ -122,48 +124,64 @@
     this.ignored_packages = new_p;
   }
   
+    private JavaClass loadSpecialClass(String class_name) throws ClassNotFoundException {
+	JavaClass clazz = null;
+	if((clazz=(JavaClass)javaClasses.get(class_name)) == null) {
+	    // Special request?
+	    if(class_name.indexOf("$$BCEL$$") >= 0) {
+		clazz = createClass(class_name);
+	    } else { 
+		// Load classes via repository
+		if ((clazz = repository.loadClass(class_name)) != null) {
+		    clazz = modifyClass(clazz);
+		} else {
+		    throw new ClassNotFoundException(class_name);
+		}
+	    }
+
+	    javaClasses.put(class_name, clazz);   
+	}
+
+	return clazz;
+    }
+
+    private boolean ignoreClass(String class_name) {
+	for(int i=0; i < ignored_packages.length; i++) {
+	    if(class_name.startsWith(ignored_packages[i])) {
+		return true;
+	    }
+	}
+
+	return false;
+    }
+
   protected Class loadClass(String class_name, boolean resolve) 
-    throws ClassNotFoundException 
-  {
+    throws ClassNotFoundException {
+
     Class cl = null;
 
-    /* First try: lookup hash table.
+    /* lookup hash table.
      */
     if((cl=(Class)classes.get(class_name)) == null) {
-      /* Second try: Load system class using system class loader. You better
+      /* Load system class using system class loader. You better
        * don't mess around with them.
        */
-      for(int i=0; i < ignored_packages.length; i++) {
-	if(class_name.startsWith(ignored_packages[i])) {
-	  cl = deferTo.loadClass(class_name);
-	  break;
-	}
-      }
-
-      if(cl == null) {
-	JavaClass clazz = null;
-
-	/* Third try: Special request?
-	 */
-	if(class_name.indexOf("$$BCEL$$") >= 0)
-	  clazz = createClass(class_name);
-	else { // Fourth try: Load classes via repository
-	  if ((clazz = repository.loadClass(class_name)) != null) {
-	    clazz = modifyClass(clazz);
+      if (ignoreClass(class_name)) {
+        cl = deferTo.loadClass(class_name);   
+      } else {
+	  JavaClass clazz = loadSpecialClass(class_name);
+	  
+	  if(clazz != null) {
+	      byte[] bytes  = clazz.getBytes();
+	      cl = defineClass(class_name, bytes, 0, bytes.length);
+	  } else {
+	      // Use default class loader
+	      cl = Class.forName(class_name);
 	  }
-	  else
-	    throw new ClassNotFoundException(class_name);
-	}
-
-	if(clazz != null) {
-	  byte[] bytes  = clazz.getBytes();
-	  cl = defineClass(class_name, bytes, 0, bytes.length);
-	} else // Fourth try: Use default class loader
-	  cl = Class.forName(class_name);
-      }
       
-      if(resolve)
-	resolveClass(cl);
+	  if(resolve)
+	      resolveClass(cl);
+      }
     }
 
     classes.put(class_name, cl);
@@ -171,6 +189,25 @@
     return cl;
   }
 
+    public InputStream getResourceAsStream(String name) {
+	if (name.endsWith(".class")) {
+	    String classname = name.substring(0, name.length() - 6).replace('/', '.');
+	
+	    if (!ignoreClass(classname)) {
+		try {
+		    JavaClass clazz = loadSpecialClass(classname);
+		    if (clazz != null) {
+			return new ByteArrayInputStream(clazz.getBytes());
+		    }
+		} catch (ClassNotFoundException cnfe) {
+		    cnfe.printStackTrace();
+		}	    
+	    } 
+	}
+
+	return deferTo.getResourceAsStream(name);
+    }
+
   /** Override this method if you want to alter a class before it gets actually
    * loaded. Does nothing by default.
    */
@@ -181,7 +218,7 @@
   /** 
    * Override this method to create you own classes on the fly. The
    * name contains the special token $$BCEL$$. Everything before that
-   * token is consddered to be a package name. You can encode you own
+   * token is considered to be a package name. You can encode you own
    * arguments into the subsequent string. You must regard however not
    * to use any "illegal" characters, i.e., characters that may not
    * appear in a Java class name too<br>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.