diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-07-26 08:55:35 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-07-26 08:55:35 +0000 |
commit | 7c1450fd7d23d45faf7036f9467c820a91d99202 (patch) | |
tree | b1fa2d6a6f4c94480f7c9d9fdd7fd2819f6b1954 /src/main | |
parent | aa92b8250ecf9bb0698a0844123b67a5f2ac5279 (diff) | |
download | javassist-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.java | 2 | ||||
-rw-r--r-- | src/main/javassist/ClassPool.java | 81 | ||||
-rw-r--r-- | src/main/javassist/CtClass.java | 88 | ||||
-rw-r--r-- | src/main/javassist/reflect/CannotReflectException.java | 34 | ||||
-rw-r--r-- | src/main/javassist/reflect/Reflection.java | 21 |
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); } |