aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-07-26 08:55:35 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-07-26 08:55:35 +0000
commit7c1450fd7d23d45faf7036f9467c820a91d99202 (patch)
treeb1fa2d6a6f4c94480f7c9d9fdd7fd2819f6b1954 /src/main
parentaa92b8250ecf9bb0698a0844123b67a5f2ac5279 (diff)
downloadjavassist-7c1450fd7d23d45faf7036f9467c820a91d99202.tar.gz
javassist-7c1450fd7d23d45faf7036f9467c820a91d99202.zip
Changed the implementation of CtClass#toClass() and fixed [Bugs item #993105] Reflection#makeReflective could reject some reflections
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@116 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/CannotCompileException.java2
-rw-r--r--src/main/javassist/ClassPool.java81
-rw-r--r--src/main/javassist/CtClass.java88
-rw-r--r--src/main/javassist/reflect/CannotReflectException.java34
-rw-r--r--src/main/javassist/reflect/Reflection.java21
5 files changed, 103 insertions, 123 deletions
diff --git a/src/main/javassist/CannotCompileException.java b/src/main/javassist/CannotCompileException.java
index dfc5f79f..0a575577 100644
--- a/src/main/javassist/CannotCompileException.java
+++ b/src/main/javassist/CannotCompileException.java
@@ -41,7 +41,7 @@ public class CannotCompileException extends Exception {
/**
* Constructs a CannotCompileException with an <code>Exception</code>.
*/
- public CannotCompileException(Exception e) {
+ public CannotCompileException(Throwable e) {
super("by " + e.toString());
message = null;
}
diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java
index ce64c847..6ddcf31d 100644
--- a/src/main/javassist/ClassPool.java
+++ b/src/main/javassist/ClassPool.java
@@ -219,87 +219,6 @@ public class ClassPool {
return (Object[])cflow.get(name);
}
- /**
- * A simple class loader used by <code>toClass()</code>
- * in <code>CtClass</code>.
- * This class loader is provided for convenience. If you need more
- * complex functionality, you should write your own class loader.
- *
- * @see CtClass#forName(String)
- * @see CtClass#toClass()
- * @see ClassPool#toClass(CtClass)
- * @see ClassPool#forName(String)
- */
- public static class SimpleLoader extends ClassLoader {
- /**
- * Loads a class.
- *
- * @param name the fully qualified class name.
- * @param classfile the class file.
- * @throws ClassFormatError if the class file is wrong.
- */
- public Class loadClass(String name, byte[] classfile)
- throws ClassFormatError
- {
- Class c = defineClass(name, classfile, 0, classfile.length);
- resolveClass(c);
- return c;
- }
- };
-
- private static SimpleLoader classLoader = null;
-
- /**
- * Returns a <code>java.lang.Class</code> object that has been loaded
- * by <code>toClass()</code> in <code>CtClass</code>
- * or <code>ClassPool</code>. Such an object cannot be
- * obtained by <code>java.lang.Class.forName()</code> because it has
- * been loaded by an internal class loader of Javassist.
- *
- * @param name the fully-qualified class name.
- * @see #toClass(CtClass)
- */
- public Class forName(String name) throws ClassNotFoundException {
- if (classLoader == null)
- classLoader = new SimpleLoader();
-
- return classLoader.loadClass(name);
- }
-
- /**
- * Loads the class represented by a <code>CtClass</code> object.
- * <code>toClass()</code> in <code>CtClass</code> calls this method
- * to load a class.
- *
- * <p>This method can be overridden to change the class loader.
- * In the default implementation,
- * the class loader is a <code>SimpleLoader</code>.
- * If this method is overridden, <code>forName()</code> must be also
- * overridden for extending the behavior.
- *
- * @param cc the loaded <code>CtClass</code>.
- * @return the <code>java.lang.Class</code> object representing
- * the loaded class.
- * @see #forName(String)
- */
- public Class toClass(CtClass cc)
- throws NotFoundException, CannotCompileException, IOException
- {
- if (cc.getClassPool() != this)
- throw new CannotCompileException(
- "not contained in this class pool: " + cc.getName());
-
- try {
- if (classLoader == null)
- classLoader = new SimpleLoader();
-
- return classLoader.loadClass(cc.getName(), cc.toBytecode());
- }
- catch (ClassFormatError e) {
- throw new CannotCompileException(e, cc.getName());
- }
- }
-
/**
* Reads a class file and constructs a <code>CtClass</code>
* object with a new name.
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index bf5a28ee..0ef8491d 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -843,57 +843,65 @@ public abstract class CtClass {
/**
* Converts this class to a <code>java.lang.Class</code> object.
* Once this method is called, further modifications are not
- * possible any more.
+ * 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.
*
* <p>This method is provided for convenience. If you need more
* complex functionality, you should write your own class loader.
*
- * <p>To load a class file, this method uses an internal class loader,
- * which is an instance of <code>ClassPool.SimpleLoader</code>.
- * Thus, that class file is not loaded by the system class loader,
- * which should have loaded this <code>CtClass</code> class.
- * The internal class loader
- * loads only the classes explicitly specified by this method
- * <code>toClass()</code>. The other classes are loaded
- * by the parent class loader (usually the sytem class loader)
- * by delegation.
- *
- * <p>For example,
- *
- * <ul><pre>class Line { Point p1, p2; }</pre></ul>
- *
- * <p>If the class <code>Line</code> is loaded by the internal class
- * loader and the class <code>Point</code> has not been loaded yet,
- * then the class <code>Point</code> that the class <code>Line</code>
- * refers to is loaded by the parent class loader. There is no
- * chance of modifying the definition of <code>Point</code> with
- * Javassist.
- *
- * <p>The internal class loader is shared among all the instances
- * of <code>ClassPool</code>.
- *
- * @return the <code>Class</code> object representing the loaded class.
- * @see CtClass#forName(String)
- * @see ClassPool.SimpleLoader
- * @see Loader
+ * @see #toClass(java.lang.ClassLoader)
*/
public Class toClass()
- throws NotFoundException, IOException, CannotCompileException
+ throws CannotCompileException
{
- return getClassPool().toClass(this);
+ return toClass(Thread.currentThread().getContextClassLoader());
}
/**
- * Returns a <code>java.lang.Class</code> object that has been loaded
- * by <code>toClass()</code>. Such an object cannot be
- * obtained by <code>java.lang.Class.forName()</code> because it has
- * been loaded by an internal class loader of Javassist.
+ * Converts this class to a <code>java.lang.Class</code> object.
+ * Once this method is called, further modifications are not allowed
+ * any more.
+ *
+ * <p>The class file represented by this <code>CtClass</code> is
+ * loaded by the given class loader to construct a
+ * <code>java.lang.Class</code> object. Since a private method
+ * on the class loader is invoked through the reflection API,
+ * the caller must have permissions to do that.
*
- * @see CtClass#toClass()
- * @see ClassPool.SimpleLoader
+ * <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.
*/
- public Class forName(String name) throws ClassNotFoundException {
- return getClassPool().forName(name);
+ public Class toClass(ClassLoader loader)
+ throws CannotCompileException
+ {
+ try {
+ byte[] b = 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 });
+ method.setAccessible(true);
+ Object[] args = new Object[] { getName(), b, new Integer(0),
+ new Integer(b.length)};
+ Class clazz = (Class)method.invoke(loader, args);
+ method.setAccessible(false);
+ return clazz;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (java.lang.reflect.InvocationTargetException e) {
+ throw new CannotCompileException(e.getTargetException());
+ }
+ catch (Exception e) {
+ throw new CannotCompileException(e);
+ }
}
/**
@@ -921,7 +929,7 @@ public abstract class CtClass {
* @return the contents of the class file.
*/
public byte[] toBytecode()
- throws NotFoundException, IOException, CannotCompileException
+ throws IOException, CannotCompileException
{
ByteArrayOutputStream barray = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(barray);
diff --git a/src/main/javassist/reflect/CannotReflectException.java b/src/main/javassist/reflect/CannotReflectException.java
new file mode 100644
index 00000000..3147e08e
--- /dev/null
+++ b/src/main/javassist/reflect/CannotReflectException.java
@@ -0,0 +1,34 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.reflect;
+
+import javassist.CannotCompileException;
+
+/**
+ * Thrown by <code>makeReflective()</code> in <code>Reflection</code>
+ * when there is an attempt to reflect
+ * a class that is either an interface or a subclass of
+ * either ClassMetaobject or Metaobject.
+ *
+ * @author Brett Randall
+ * @see javassist.reflect.Reflection#makeReflective(CtClass,CtClass,CtClass)
+ * @see javassist.CannotCompileException
+ */
+public class CannotReflectException extends CannotCompileException {
+ public CannotReflectException(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/main/javassist/reflect/Reflection.java b/src/main/javassist/reflect/Reflection.java
index 1405d9b3..9cb14425 100644
--- a/src/main/javassist/reflect/Reflection.java
+++ b/src/main/javassist/reflect/Reflection.java
@@ -66,6 +66,10 @@ public class Reflection implements Translator {
static final String readPrefix = "_r_";
static final String writePrefix = "_w_";
+ static final String metaobjectClassName = "javassist.reflect.Metaobject";
+ static final String classMetaobjectClassName
+ = "javassist.reflect.ClassMetaobject";
+
protected CtMethod trapMethod, trapStaticMethod;
protected CtMethod trapRead, trapWrite;
protected CtClass[] readParam;
@@ -189,8 +193,23 @@ public class Reflection implements Translator {
*/
public boolean makeReflective(CtClass clazz,
CtClass metaobject, CtClass metaclass)
- throws CannotCompileException, NotFoundException
+ throws CannotCompileException, CannotReflectException,
+ NotFoundException
{
+ if (clazz.isInterface())
+ throw new CannotReflectException(
+ "Cannot reflect an interface: " + clazz.getName());
+
+ if (clazz.subclassOf(classPool.get(classMetaobjectClassName)))
+ throw new CannotReflectException(
+ "Cannot reflect a subclass of ClassMetaobject: "
+ + clazz.getName());
+
+ if (clazz.subclassOf(classPool.get(metaobjectClassName)))
+ throw new CannotReflectException(
+ "Cannot reflect a subclass of Metaobject: "
+ + clazz.getName());
+
registerReflectiveClass(clazz);
return modifyClassfile(clazz, metaobject, metaclass);
}