]> source.dussan.org Git - javassist.git/commitdiff
fixed the bug reported as JASSIST-23.
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 7 Aug 2006 15:48:31 +0000 (15:48 +0000)
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Mon, 7 Aug 2006 15:48:31 +0000 (15:48 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@305 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

.classpath
Readme.html
src/main/javassist/ClassPool.java
src/main/javassist/CtClass.java
src/main/javassist/Loader.java
src/main/javassist/scopedpool/ScopedClassPool.java
src/main/javassist/util/proxy/FactoryHelper.java
src/main/javassist/util/proxy/ProxyFactory.java

index 7b2fabb0bd4efd5e2221074fcace259d26acca71..deae2f478f71a3e4c05465613f8f8f028eedbeb2 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry excluding="javassist/util/HotSwapper.java" kind="src" path="src/main"/>
+       <classpathentry kind="src" path="src/test"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="output" path="build/classes"/>
 </classpath>
index f650a2152e12068cb55397b41673c7a5f33e8195..c791af92555f0bbf694a0956abfa81180a4e97c9 100644 (file)
@@ -283,6 +283,9 @@ see javassist.Dump.
 
 <p>-version 3.3
 <ul>
+    <li>CtClass#toClass() and ClassPool#toClass() were modified to accept a
+    <code>ProtectionDomain</code>
+    (<a href="http://jira.jboss.com/jira/browse/JASSIST-23">JASSIST-23</a>).
     <li>CtClass#getAvailableAnnotations() etc. have been implemented.
     <li>A bug related to a way of dealing with a bridge method was fixed
     (<a href="http://jira.jboss.com/jira/browse/HIBERNATE-37">HIBERNATE-37</a>).
@@ -683,7 +686,7 @@ Howard Lewis Ship, Richard Jones, Marjan Sterjev,
 Bruce McDonald, Mark Brennan, Vlad Skarzhevskyy,
 Brett Randall, Tsuyoshi Murakami, Nathan Meyers, Yoshiyuki Usui
 Yutaka Sunaga, Arjan van der Meer, Bruce Eckel, Guillaume Pothier,
-Kumar Matcha, Andreas Salathe,
+Kumar Matcha, Andreas Salathe, Renat Zubairov,
 and all other contributors for their contributions.
 
 <p><br>
index 1062d670e66e3491d11c57b3189cac95d037bf30..c65872c3167cc9ed8a062cd1c2d01731ff4ee1b2 100644 (file)
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
+import java.security.ProtectionDomain;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.ArrayList;
@@ -61,6 +62,24 @@ import javassist.bytecode.Descriptor;
  * @see javassist.ClassPath
  */
 public class ClassPool {
+    // used by toClass().
+    private static java.lang.reflect.Method defineClass1, defineClass2;
+
+    static {
+        try {
+            Class cl = Class.forName("java.lang.ClassLoader");
+            defineClass1 = cl.getDeclaredMethod("defineClass",
+                        new Class[] { String.class, byte[].class,
+                                      int.class, int.class });
+
+            defineClass2 = cl.getDeclaredMethod("defineClass",
+                        new Class[] { String.class, byte[].class,
+                              int.class, int.class, ProtectionDomain.class });
+        }
+        catch (Exception e) {
+            throw new RuntimeException("cannot initialize ClassPool");
+        }
+    }
 
     /**
      * Determines the search order.
@@ -752,21 +771,27 @@ public class ClassPool {
      * Once this method is called, further modifications are not
      * allowed any more.
      * To load the class, this method uses the context class loader
-     * of the current thread.  If the program is running on some application
-     * server, the context class loader might be inappropriate to load the
-     * class.
+     * of the current thread.  It is obtained by calling
+     * <code>getClassLoader()</code>.  
      * 
-     * <p>This can be changed by subclassing the pool and changing
+     * <p>This behavior can be changed by subclassing the pool and changing
      * the <code>getClassLoader()</code> method.
+     * If the program is running on some application
+     * server, the context class loader might be inappropriate to load the
+     * class.
      *
      * <p>This method is provided for convenience.  If you need more
      * complex functionality, you should write your own class loader.
      *
-     * @see #toClass(CtClass, java.lang.ClassLoader)
+     * <p><b>Warining:</b> A Class object returned by this method may not
+     * work with a security manager or a signed jar file because a
+     * protection domain is not specified.
+     *
+     * @see #toClass(CtClass, java.lang.ClassLoader, ProtectionDomain)
      * @see #getClassLoader()
      */
     public Class toClass(CtClass clazz) throws CannotCompileException {
-        return toClass(clazz, getClassLoader()); 
+        return toClass(clazz, getClassLoader(), null); 
     }
 
     /**
@@ -791,6 +816,23 @@ public class ClassPool {
         return Thread.currentThread().getContextClassLoader();
     }
 
+    /**
+     * Converts the class to a <code>java.lang.Class</code> object.
+     * Do not override this method any more at a subclass because
+     * <code>toClass(CtClass)</code> never calls this method.
+     *
+     * <p><b>Warining:</b> A Class object returned by this method may not
+     * work with a security manager or a signed jar file because a
+     * protection domain is not specified.
+     * 
+     * @deprecated      Replaced by {@link #toClass(CtClass,ClassLoader,ProtectionDomain)}
+     */
+    public final Class toClass(CtClass ct, ClassLoader loader)
+        throws CannotCompileException
+    {
+        return toClass(ct, loader, null);
+    }
+
     /**
      * Converts the class to a <code>java.lang.Class</code> object.
      * Once this method is called, further modifications are not allowed
@@ -802,24 +844,44 @@ public class ClassPool {
      * on the class loader is invoked through the reflection API,
      * the caller must have permissions to do that.
      *
+     * <p>An easy way to obtain <code>ProtectionDomain</code> object is
+     * to call <code>getProtectionDomain()</code>
+     * in <code>java.lang.Class</code>.  It returns the domain that the
+     * class belongs to.
+     *
      * <p>This method is provided for convenience.  If you need more
      * complex functionality, you should write your own class loader.
      *
      * @param loader        the class loader used to load this class.
+     *                      For example, the loader returned by
+     *                      <code>getClassLoader()</code> can be used
+     *                      for this parameter.
+     * @param domain        the protection domain for the class.
+     *                      If it is null, the default domain created
+     *                      by <code>java.lang.ClassLoader</code> is used.
+     *
+     * @see #getContextClassLoader()
+     * @since 3.3
      */
-    public Class toClass(CtClass ct, ClassLoader loader)
+    public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain)
         throws CannotCompileException
     {
         try {
             byte[] b = ct.toBytecode();
-            Class cl = Class.forName("java.lang.ClassLoader");
-            java.lang.reflect.Method method =
-                cl.getDeclaredMethod("defineClass",
-                                new Class[] { String.class, byte[].class,
-                                              int.class, int.class });
+            java.lang.reflect.Method method;
+            Object[] args;
+            if (domain == null) {
+                method = defineClass1;
+                args = new Object[] { ct.getName(), b, new Integer(0),
+                                      new Integer(b.length)};
+            }
+            else {
+                method = defineClass2;
+                args = new Object[] { ct.getName(), b, new Integer(0),
+                    new Integer(b.length), domain};
+            }
+                
             method.setAccessible(true);
-            Object[] args = new Object[] { ct.getName(), b, new Integer(0),
-                                           new Integer(b.length)};
             Class clazz = (Class)method.invoke(loader, args);
             method.setAccessible(false);
             return clazz;
index 51fa78c3922f1bc868801fa6c5923cb52e71085a..d755200269a955421ed54cfb05ad28b6823b42fc 100644 (file)
@@ -23,6 +23,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
+import java.security.ProtectionDomain;
 import java.util.Collection;
 import javassist.bytecode.ClassFile;
 import javassist.bytecode.Descriptor;
@@ -1025,6 +1026,10 @@ public abstract class CtClass {
      * <p>Note: this method calls <code>toClass()</code>
      * in <code>ClassPool</code>.
      *
+     * <p><b>Warining:</b> A Class object returned by this method may not
+     * work with a security manager or a signed jar file because a
+     * protection domain is not specified.
+     *
      * @see #toClass(java.lang.ClassLoader)
      * @see ClassPool#toClass(CtClass)
      */
@@ -1043,6 +1048,11 @@ public abstract class CtClass {
      * on the class loader is invoked through the reflection API,
      * the caller must have permissions to do that.
      *
+     * <p>An easy way to obtain <code>ProtectionDomain</code> object is
+     * to call <code>getProtectionDomain()</code>
+     * in <code>java.lang.Class</code>.  It returns the domain that
+     * the class belongs to.
+     *
      * <p>This method is provided for convenience.  If you need more
      * complex functionality, you should write your own class loader.
      *
@@ -1050,9 +1060,33 @@ public abstract class CtClass {
      * in <code>ClassPool</code>.
      *
      * @param loader        the class loader used to load this class.
+     *                      If it is null, the class loader returned by
+     *                      {@link ClassPool#getClassLoader()} is used.
+     * @param domain        the protection domain that the class belongs to.
+     *                      If it is null, the default domain created
+     *                      by <code>java.lang.ClassLoader</code> is used.
      * @see ClassPool#toClass(CtClass,java.lang.ClassLoader)
      */
-    public Class toClass(ClassLoader loader)
+    public Class toClass(ClassLoader loader, ProtectionDomain domain)
+        throws CannotCompileException
+    {
+        ClassPool cp = getClassPool();
+        if (loader == null)
+            loader = cp.getClassLoader();
+
+        return cp.toClass(this, loader, domain);
+    }
+
+    /**
+     * Converts this class to a <code>java.lang.Class</code> object.
+     *
+     * <p><b>Warining:</b> A Class object returned by this method may not
+     * work with a security manager or a signed jar file because a
+     * protection domain is not specified.
+     *
+     * @deprecated      Replaced by {@link #toClass(ClassLoader,ProtectionDomain)}
+     */
+    public final Class toClass(ClassLoader loader)
         throws CannotCompileException
     {
         return getClassPool().toClass(this, loader);
index b676a63a0423ab7350375fadf18dbc1ebb4ad71c..716fc98816201ef79bbfa3a259a14d3f4f170d47 100644 (file)
@@ -18,6 +18,7 @@ package javassist;
 import java.io.*;
 import java.util.Hashtable;
 import java.util.Vector;
+import java.security.ProtectionDomain;
 
 /**
  * The class loader for Javassist.
@@ -136,6 +137,7 @@ public class Loader extends ClassLoader {
     private Vector notDefinedPackages; // must be atomic.
     private ClassPool source;
     private Translator translator;
+    private ProtectionDomain domain; 
 
     /**
      * Specifies the algorithm of class loading.
@@ -183,6 +185,7 @@ public class Loader extends ClassLoader {
         notDefinedPackages = new Vector();
         source = cp;
         translator = null;
+        domain = null;
         delegateLoadingOf("javassist.Loader");
     }
 
@@ -201,6 +204,16 @@ public class Loader extends ClassLoader {
             notDefinedHere.put(classname, this);
     }
 
+    /**
+     * Sets the protection domain for the classes handled by this class
+     * loader.  Without registering an appropriate protection domain,
+     * the program loaded by this loader will not work with a security
+     * manager or a signed jar file.
+     */
+    public void setDomain(ProtectionDomain d) {
+        domain = d;
+    }
+
     /**
      * Sets the soruce <code>ClassPool</code>.
      */
@@ -362,7 +375,10 @@ public class Loader extends ClassLoader {
                 }
         }
 
-        return defineClass(name, classfile, 0, classfile.length);
+        if (domain == null)
+            return defineClass(name, classfile, 0, classfile.length);
+        else
+            return defineClass(name, classfile, 0, classfile.length, domain);
     }
 
     protected Class loadClassByDelegation(String name)
index 4c33e6343ea196d48d41b1dcb8b4cb8e740869cd..8be4b439f3b96f27c856cef8c1e35d9d8532606c 100644 (file)
@@ -16,6 +16,7 @@
 package javassist.scopedpool;
 
 import java.lang.ref.WeakReference;
+import java.security.ProtectionDomain;
 import java.util.Iterator;
 import java.util.Map;
 import javassist.CannotCompileException;
@@ -30,7 +31,7 @@ import javassist.NotFoundException;
  * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
  * @author <a href="adrian@jboss.com">Adrian Brock</a>
  * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
- * @version $Revision: 1.3 $
+ * @version $Revision: 1.4 $
  */
 public class ScopedClassPool extends ClassPool {
     protected ScopedClassPoolRepository repository;
@@ -261,7 +262,7 @@ public class ScopedClassPool extends ClassPool {
      * @throws CannotCompileException
      *             for any error
      */
-    public Class toClass(CtClass ct, ClassLoader loader)
+    public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain)
             throws CannotCompileException {
         // We need to pass up the classloader stored in this pool, as the
         // default implementation uses the Thread context cl.
@@ -276,6 +277,6 @@ public class ScopedClassPool extends ClassPool {
         // org.apache.jsp. For classes belonging to org.apache.jsp,
         // JasperLoader does NOT delegate to its parent if it cannot find them.
         lockInCache(ct);
-        return super.toClass(ct, getClassLoader0());
+        return super.toClass(ct, getClassLoader0(), domain);
     }
 }
index b00b9a93529bb4e7e8b899b2934f4fae0e2c9c6d..21038fe94add46ed73b677e4baa54180a4d5099b 100644 (file)
@@ -21,8 +21,10 @@ import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.security.ProtectionDomain;
 
 import javassist.CannotCompileException;
+import javassist.CtClass;
 import javassist.bytecode.ClassFile;
 
 /**
@@ -32,6 +34,24 @@ import javassist.bytecode.ClassFile;
  * @see ProxyFactory
  */
 public class FactoryHelper {
+    private static java.lang.reflect.Method defineClass1, defineClass2;
+
+    static {
+        try {
+            Class cl = Class.forName("java.lang.ClassLoader");
+            defineClass1 = cl.getDeclaredMethod("defineClass",
+                        new Class[] { String.class, byte[].class,
+                                      int.class, int.class });
+
+            defineClass2 = cl.getDeclaredMethod("defineClass",
+                        new Class[] { String.class, byte[].class,
+                              int.class, int.class, ProtectionDomain.class });
+        }
+        catch (Exception e) {
+            throw new RuntimeException("cannot initialize");
+        }
+    }
+
     /**
      * Returns an index for accessing arrays in this class.
      *
@@ -101,19 +121,41 @@ public class FactoryHelper {
 
     /**
      * Loads a class file by a given class loader.
+     * This method uses a default protection domain for the class
+     * but it may not work with a security manager or a sigend jar file.
+     *
+     * @see #toClass(CtClass,ClassLoader,ProtectionDomain)
      */
     public static Class toClass(ClassFile cf, ClassLoader loader)
+        throws CannotCompileException
+    {
+        return toClass(cf, loader, null);
+    }
+
+    /**
+     * Loads a class file by a given class loader.
+     *
+     * @param domain        if it is null, a default domain is used.
+     */
+    public static Class toClass(ClassFile cf, ClassLoader loader, ProtectionDomain domain)
             throws CannotCompileException
     {
         try {
             byte[] b = toBytecode(cf);
-            Class cl = Class.forName("java.lang.ClassLoader");
-            java.lang.reflect.Method method = cl.getDeclaredMethod(
-                    "defineClass", new Class[] { String.class, byte[].class,
-                    Integer.TYPE, Integer.TYPE });
+            java.lang.reflect.Method method;
+            Object[] args;
+            if (domain == null) {
+                method = defineClass1;
+                args = new Object[] { cf.getName(), b, new Integer(0),
+                        new Integer(b.length) };
+            }
+            else {
+                method = defineClass2;
+                args = new Object[] { cf.getName(), b, new Integer(0),
+                        new Integer(b.length), domain };
+            }
+
             method.setAccessible(true);
-            Object[] args = new Object[] { cf.getName(), b, new Integer(0),
-                    new Integer(b.length) };
             Class clazz = (Class)method.invoke(loader, args);
             method.setAccessible(false);
             return clazz;
index bf29e5392e087c7c7090327aa0e234c25dfd5ca4..fdd397ad3737585101bb24a76b2b7136e2471eb3 100644 (file)
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Member;
 import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -166,7 +167,7 @@ public class ProxyFactory {
                 if (writeDirectory != null)
                     FactoryHelper.writeFile(cf, writeDirectory);
 
-                thisClass = FactoryHelper.toClass(cf, cl);
+                thisClass = FactoryHelper.toClass(cf, cl, getDomain());
                 setHandler();
             }
             catch (CannotCompileException e) {
@@ -194,6 +195,18 @@ public class ProxyFactory {
         return loader;
     }
 
+    protected ProtectionDomain getDomain() {
+        Class clazz;
+        if (superClass != null && !superClass.getName().equals("java.lang.Object"))
+            clazz = superClass;
+        else if (interfaces != null && interfaces.length > 0)
+            clazz = interfaces[0];
+        else
+            clazz = this.getClass();
+
+        return clazz.getProtectionDomain();
+    }
+
     /**
      * Creates a proxy class and returns an instance of that class.
      *