summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2006-08-07 15:48:31 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2006-08-07 15:48:31 +0000
commit2405e6804619f75ef93c9a8e9ba366e595f4899d (patch)
treea5fac709b60ce7e9f161fe5b55e144e24283cdcf /src/main
parenta62c5816078737cc3a392beaa88c2c03d95ea961 (diff)
downloadjavassist-2405e6804619f75ef93c9a8e9ba366e595f4899d.tar.gz
javassist-2405e6804619f75ef93c9a8e9ba366e595f4899d.zip
fixed the bug reported as JASSIST-23.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@305 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/ClassPool.java90
-rw-r--r--src/main/javassist/CtClass.java36
-rw-r--r--src/main/javassist/Loader.java18
-rw-r--r--src/main/javassist/scopedpool/ScopedClassPool.java7
-rw-r--r--src/main/javassist/util/proxy/FactoryHelper.java54
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java15
6 files changed, 194 insertions, 26 deletions
diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java
index 1062d670..c65872c3 100644
--- a/src/main/javassist/ClassPool.java
+++ b/src/main/javassist/ClassPool.java
@@ -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);
}
/**
@@ -793,6 +818,23 @@ public class ClassPool {
/**
* 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
* any more.
*
@@ -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;
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index 51fa78c3..d7552002 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -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);
diff --git a/src/main/javassist/Loader.java b/src/main/javassist/Loader.java
index b676a63a..716fc988 100644
--- a/src/main/javassist/Loader.java
+++ b/src/main/javassist/Loader.java
@@ -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");
}
@@ -202,6 +205,16 @@ public class Loader extends ClassLoader {
}
/**
+ * 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>.
*/
public void setClassPool(ClassPool cp) {
@@ -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)
diff --git a/src/main/javassist/scopedpool/ScopedClassPool.java b/src/main/javassist/scopedpool/ScopedClassPool.java
index 4c33e634..8be4b439 100644
--- a/src/main/javassist/scopedpool/ScopedClassPool.java
+++ b/src/main/javassist/scopedpool/ScopedClassPool.java
@@ -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);
}
}
diff --git a/src/main/javassist/util/proxy/FactoryHelper.java b/src/main/javassist/util/proxy/FactoryHelper.java
index b00b9a93..21038fe9 100644
--- a/src/main/javassist/util/proxy/FactoryHelper.java
+++ b/src/main/javassist/util/proxy/FactoryHelper.java
@@ -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;
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java
index bf29e539..fdd397ad 100644
--- a/src/main/javassist/util/proxy/ProxyFactory.java
+++ b/src/main/javassist/util/proxy/ProxyFactory.java
@@ -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.
*