Browse Source

fixed the bug reported as JASSIST-23.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@305 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 18 years ago
parent
commit
2405e68046

+ 1
- 0
.classpath View 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>

+ 4
- 1
Readme.html View 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>

+ 76
- 14
src/main/javassist/ClassPool.java View 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;

+ 35
- 1
src/main/javassist/CtClass.java View 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);

+ 17
- 1
src/main/javassist/Loader.java View 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)

+ 4
- 3
src/main/javassist/scopedpool/ScopedClassPool.java View 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);
}
}

+ 48
- 6
src/main/javassist/util/proxy/FactoryHelper.java View 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;

+ 14
- 1
src/main/javassist/util/proxy/ProxyFactory.java View 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.
*

Loading…
Cancel
Save