[jboss-cvs] JBossAS SVN: r104720 - in projects/jboss-reflect/trunk: src/main/java/org/jboss/reflect/plugins/javassist/bytecode and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed May 12 07:01:34 EDT 2010
Author: kabir.khan at jboss.com
Date: 2010-05-12 07:01:32 -0400 (Wed, 12 May 2010)
New Revision: 104720
Added:
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ClassFileWriterContext.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ErrorCheckingMemberFactory.java
Modified:
projects/jboss-reflect/trunk/pom.xml
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistBehaviorFactory.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistConstructorFactory.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistFieldFactory.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMemberFactory.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMethodFactory.java
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/SecurityActions.java
Log:
[JBREFLECT-122] Make JavassistMemberFactory use the new javassist.bytecode.ClassFileWriter API when creating classes
Modified: projects/jboss-reflect/trunk/pom.xml
===================================================================
--- projects/jboss-reflect/trunk/pom.xml 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/pom.xml 2010-05-12 11:01:32 UTC (rev 104720)
@@ -21,7 +21,7 @@
<version.jboss.common.core>2.2.17.GA</version.jboss.common.core>
<version.jboss.logging.spi>2.2.0.CR1</version.jboss.logging.spi>
<version.jboss.logging.log4j>2.2.0.CR1</version.jboss.logging.log4j>
- <version.javassist>3.12.0.GA</version.javassist>
+ <version.javassist>3.12.1-SNAPSHOT</version.javassist>
<version.org.jboss.test>1.1.5.GA</version.org.jboss.test>
<version.junit>4.8.1</version.junit>
<version.jboss.profiler.jvmti>1.0.0.CR5</version.jboss.profiler.jvmti>
Added: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ClassFileWriterContext.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ClassFileWriterContext.java (rev 0)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ClassFileWriterContext.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -0,0 +1,415 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.reflect.plugins.javassist.bytecode;
+
+import java.lang.reflect.InvocationTargetException;
+import java.security.ProtectionDomain;
+
+import javassist.CtClass;
+import javassist.Modifier;
+import javassist.bytecode.Bytecode;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.ClassFileWriter;
+import javassist.bytecode.Descriptor;
+import javassist.bytecode.MethodInfo;
+import javassist.bytecode.Opcode;
+import javassist.bytecode.ClassFileWriter.ConstPoolWriter;
+import javassist.bytecode.ClassFileWriter.MethodWriter;
+
+/**
+ * Wrapper around the {@link ClassFileWriter} with some utility methods
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+class ClassFileWriterContext<T>
+{
+ private static final java.lang.reflect.Method defineClass1, defineClass2;
+
+ static {
+ try {
+ Class<?> cl = Class.forName("java.lang.ClassLoader");
+ defineClass1 = SecurityActions.getDeclaredMethod(
+ cl,
+ "defineClass",
+ new Class[] { String.class, byte[].class,
+ int.class, int.class });
+
+ defineClass2 = SecurityActions.getDeclaredMethod(
+ cl,
+ "defineClass",
+ new Class[] { String.class, byte[].class,
+ int.class, int.class, ProtectionDomain.class });
+ }
+ catch (Exception e) {
+ throw new RuntimeException("cannot initialize");
+ }
+
+ SecurityActions.setAccessible(defineClass1);
+ SecurityActions.setAccessible(defineClass2);
+ }
+
+ /** The class of the interface we are implementing */
+ final Class<T> type;
+
+ /** The name of the class we are creating */
+ final String name;
+
+ /** The underlying class file writer */
+ final ClassFileWriter fileWriter;
+
+ /** The underlying class pool writer */
+ final ConstPoolWriter poolWriter;
+
+ /** This class's name index in the const pool */
+ final int thisClass;
+
+ /** This class's superclass name index in the const pool */
+ final int superClass;
+
+ /** The interfaces */
+ final int[] interfaces;
+
+ /** The method writer for the methods */
+ final MethodWriter mw;
+
+ /** The created bytes */
+ byte[] bytes;
+
+ int stackDepth;
+
+ int maxStackDepth;
+
+ ClassFileWriterContext(String name, String superClassName, Class<T> type, String[] interfaceNames)
+ {
+ this.name = name;
+ this.type = type;
+
+ //FIXME Once we get rid of the old ClassFile stuff we should make the real names look like this
+ //to start with
+ name = ClassFileWriterContext.jvmClassName(name);
+ superClassName = ClassFileWriterContext.jvmClassName(superClassName);
+ for (int i = 0 ; i < interfaceNames.length ; i++)
+ interfaceNames[i] = ClassFileWriterContext.jvmClassName(interfaceNames[i]);
+
+ fileWriter = new ClassFileWriter(ClassFile.JAVA_4, 0);
+ poolWriter = fileWriter.getConstPool();
+ thisClass = poolWriter.addClassInfo(name);
+ superClass = poolWriter.addClassInfo(superClassName);
+ interfaces = poolWriter.addClassInfo(interfaceNames);
+
+ //Add default constructor
+ mw = fileWriter.getMethodWriter();
+ mw.begin(Modifier.PUBLIC, MethodInfo.nameInit, "()V", null, null);
+ mw.add(Opcode.ALOAD_0);
+ mw.add(Opcode.INVOKESPECIAL);
+ int signature = poolWriter.addNameAndTypeInfo(MethodInfo.nameInit, "()V");
+ mw.add16(poolWriter.addMethodrefInfo(superClass, signature));
+ mw.add(Opcode.RETURN);
+ mw.codeEnd(1, 1);
+ mw.end(null, null);
+ }
+
+ String getSimpleType()
+ {
+ return type.getSimpleName();
+ }
+
+ String getName()
+ {
+ return name;
+ }
+
+ void beginMethod(int accessFlags, String name, String descriptor, String[] exceptions)
+ {
+ mw.begin(Modifier.PUBLIC, name, descriptor, exceptions, null);
+ }
+
+ void endMethod(int maxLocals)
+ {
+ mw.codeEnd(maxStackDepth, maxLocals);
+ mw.end(null, null);
+ }
+
+ void addInvokeStatic(String targetClass, String methodName, String descriptor)
+ {
+ mw.addInvoke(Opcode.INVOKESTATIC, targetClass, methodName, descriptor);
+
+ //Stolen from Bytecode.addInvokestatic()
+ growStack(Descriptor.dataSize(descriptor));
+ }
+
+ void addInvokeVirtual(String targetClass, String methodName, String descriptor)
+ {
+ mw.addInvoke(Opcode.INVOKEVIRTUAL, targetClass, methodName, descriptor);
+
+ //Stolen from Bytecode.addInvokevirtual()
+ growStack(Descriptor.dataSize(descriptor) - 1);
+ }
+
+ void addInvokeInterface(String targetClass, String methodName, String descriptor, int count)
+ {
+ mw.addInvoke(Opcode.INVOKEINTERFACE, targetClass, methodName, descriptor);
+ mw.add(count);
+ mw.add(0);
+
+ //Stolen from Bytecode.addInvokeinterface()
+ growStack(Descriptor.dataSize(descriptor) - 1);
+ }
+
+ void addInvokeSpecial(String targetClass, String methodName, String descriptor)
+ {
+ mw.addInvoke(Opcode.INVOKESPECIAL, targetClass, methodName, descriptor);
+
+ //Stolen from Bytecode.addInvokespecial()
+ growStack(Descriptor.dataSize(descriptor) - 1);
+ }
+
+ void addGetField(String className, String fieldName, String type)
+ {
+ mw.add(Opcode.GETFIELD);
+ addFieldRefInfo(className, fieldName, type);
+
+ //Stolen from Bytecode.addGetfield()
+ growStack(Descriptor.dataSize(type) - 1);
+ }
+
+ void addGetStatic(String className, String fieldName, String type)
+ {
+ mw.add(Opcode.GETSTATIC);
+ addFieldRefInfo(className, fieldName, type);
+
+ //Stolen from Bytecode.addGetstatic()
+ growStack(Descriptor.dataSize(type));
+ }
+
+ void addPutField(String className, String fieldName, String type)
+ {
+ mw.add(Opcode.PUTFIELD);
+ addFieldRefInfo(className, fieldName, type);
+
+ //Stolen from Bytecode.addPutfield()
+ growStack(1 - Descriptor.dataSize(type));
+ }
+
+ void addPutStatic(String className, String fieldName, String type)
+ {
+ mw.add(Opcode.PUTSTATIC);
+ addFieldRefInfo(className, fieldName, type);
+
+ //Stolen from Bytecode.addPutStatic()
+ growStack(-Descriptor.dataSize(type));
+ }
+
+ void addAReturn()
+ {
+ mw.add(Opcode.ARETURN);
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(-1);
+ }
+
+ void addAConstNull()
+ {
+ mw.add(Opcode.ACONST_NULL);
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(1);
+ }
+
+ void addAALoad()
+ {
+ mw.add(Opcode.AALOAD);
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(-1);
+ }
+
+ /**
+ * Adds the right bytecode to call ALOAD depending on the
+ * number of the parameter
+ *
+ * @param i the number of the parameter
+ * @see Bytecode#addAload(int)
+ */
+ void addAload(int i)
+ {
+ if (i < 4)
+ mw.add(Opcode.ALOAD_0 + i);
+ else if (i < 0x100)
+ {
+ mw.add(Opcode.ALOAD); // aload
+ mw.add(i);
+ }
+ else
+ {
+ mw.add(Opcode.WIDE);
+ mw.add(Opcode.ALOAD);
+ addIndex(i);
+ }
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(1);
+ }
+
+ /**
+ * Adds the right bytecode to load a constant depending on the
+ * size of the constant
+ *
+ * @param i the number
+ * @see Bytecode#addIconst(int);
+ */
+ void addIconst(int i)
+ {
+ if (i < 6 && -2 < i)
+ mw.add(Opcode.ICONST_0 + i); // iconst_<i> -1..5
+ else if (i <= 127 && -128 <= i) {
+ mw.add(Opcode.BIPUSH); // bipush
+ mw.add(i);
+ }
+ else if (i <= 32767 && -32768 <= i)
+ {
+ mw.add(Opcode.SIPUSH); // sipush
+ mw.add(i >> 8);
+ mw.add(i);
+ }
+ else
+ {
+ int ref = poolWriter.addIntegerInfo(i);
+
+ if (i > 0xFF)
+ {
+ mw.add(Opcode.LDC_W);
+ mw.add(i >> 8);
+ mw.add(i);
+ }
+ else
+ {
+ mw.add(Opcode.LDC);
+ mw.add(ref);
+ }
+ }
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(1);
+ }
+
+ void addNew(String className)
+ {
+ mw.add(Opcode.NEW);
+ addIndex(addClassInfo(className));
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(1);
+ }
+
+ void addDup()
+ {
+ mw.add(Opcode.DUP);
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ growStack(1);
+ }
+
+ void addCheckcast(String clazz)
+ {
+ mw.add(Opcode.CHECKCAST);
+ int i = poolWriter.addClassInfo(clazz);
+ addIndex(i);
+
+ //From Opcode.STACK_GROW[] (see test in main())
+ //No change to stack
+ }
+
+ byte[] getBytes()
+ {
+ if (bytes == null)
+ bytes = fileWriter.end(Modifier.PUBLIC, thisClass, superClass, interfaces, null);
+ return bytes;
+ }
+
+ Class<T> toClass(ClassLoader loader, ProtectionDomain domain) throws InvocationTargetException, IllegalAccessException
+ {
+ byte[] bytes = getBytes();
+ if (domain == null)
+ return (Class<T>) SecurityActions.invoke(defineClass1, loader, name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length));
+ else
+ return (Class<T>) SecurityActions.invoke(defineClass2, loader, name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length), domain);
+ }
+
+ private void addIndex(int i)
+ {
+ mw.add(i >> 8);
+ mw.add(i);
+ }
+
+ private void addFieldRefInfo(String className, String fieldName, String type)
+ {
+ addIndex(poolWriter.addFieldrefInfo(poolWriter.addClassInfo(className), poolWriter.addNameAndTypeInfo(fieldName, type)));
+ }
+
+ private int addClassInfo(String className)
+ {
+ return poolWriter.addClassInfo(className.replace('.', '/'));
+ }
+
+ private void growStack(int i)
+ {
+ stackDepth += i;
+ if (stackDepth > maxStackDepth)
+ maxStackDepth = stackDepth;
+ }
+
+ static String jvmClassName(CtClass clazz)
+ {
+ return ClassFileWriterContext.jvmClassName(clazz.getName());
+ }
+
+ static String jvmClassName(String name)
+ {
+ return name.replace('.', '/');
+ }
+
+ public static void main (String[] args)
+ {
+ System.out.println(" Opcode.INVOKESTATIC \t" + Opcode.STACK_GROW[ Opcode.INVOKESTATIC ]);
+ System.out.println(" Opcode.INVOKEVIRTUAL \t" + Opcode.STACK_GROW[ Opcode.INVOKEVIRTUAL ]);
+ System.out.println(" Opcode.INVOKEINTERFACE\t" + Opcode.STACK_GROW[ Opcode.INVOKEINTERFACE ]);
+ System.out.println(" Opcode.INVOKESPECIAL \t" + Opcode.STACK_GROW[ Opcode.INVOKESPECIAL ]);
+ System.out.println(" Opcode.GETFIELD \t" + Opcode.STACK_GROW[ Opcode.GETFIELD ]);
+ System.out.println(" Opcode.GETSTATIC \t" + Opcode.STACK_GROW[ Opcode.GETSTATIC ]);
+ System.out.println(" Opcode.PUTFIELD \t" + Opcode.STACK_GROW[ Opcode.PUTFIELD ]);
+ System.out.println(" Opcode.PUTSTATIC \t" + Opcode.STACK_GROW[ Opcode.PUTSTATIC ]);
+ System.out.println(" Opcode.ARETURN \t" + Opcode.STACK_GROW[ Opcode.ARETURN ]);
+ System.out.println(" Opcode.ACONST_NULL \t" + Opcode.STACK_GROW[ Opcode.ACONST_NULL ]);
+ System.out.println(" Opcode.AALOAD \t" + Opcode.STACK_GROW[ Opcode.AALOAD ]);
+ System.out.println(" Opcode.ALOAD_1 \t" + Opcode.STACK_GROW[ Opcode.ALOAD_1 ]);
+ System.out.println(" Opcode.ALOAD \t" + Opcode.STACK_GROW[ Opcode.ALOAD ]);
+ System.out.println(" Opcode.WIDE \t" + Opcode.STACK_GROW[ Opcode.WIDE ]);
+ System.out.println(" Opcode.NEW \t" + Opcode.STACK_GROW[ Opcode.NEW ]);
+ System.out.println(" Opcode.DUP \t" + Opcode.STACK_GROW[ Opcode.DUP ]);
+ System.out.println(" Opcode.CHECKCAST \t" + Opcode.STACK_GROW[ Opcode.CHECKCAST ]);
+ System.out.println(" Opcode.ICONST_1) \t" + Opcode.STACK_GROW[ Opcode.ICONST_1 ]);
+ System.out.println(" Opcode.BIPUSH) \t" + Opcode.STACK_GROW[ Opcode.BIPUSH ]);
+ System.out.println(" Opcode.SIPUSH) \t" + Opcode.STACK_GROW[ Opcode.SIPUSH ]);
+ System.out.println(" Opcode.LDC_W) \t" + Opcode.STACK_GROW[ Opcode.LDC_W ]);
+ System.out.println(" Opcode.LDC) \t" + Opcode.STACK_GROW[ Opcode.LDC ]);
+ }
+ }
Added: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ErrorCheckingMemberFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ErrorCheckingMemberFactory.java (rev 0)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/ErrorCheckingMemberFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -0,0 +1,340 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.reflect.plugins.javassist.bytecode;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMember;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+
+import org.jboss.reflect.plugins.javassist.JavassistConstructor;
+import org.jboss.reflect.plugins.javassist.JavassistField;
+import org.jboss.reflect.plugins.javassist.JavassistMethod;
+import org.jboss.reflect.plugins.javassist.JavassistUtil;
+import org.jboss.util.Strings;
+
+/**
+ * Class to wrap the generated JavassistMethod, -Constructor and -Field
+ * implementations with another implementation that checks the parameters
+ * if something went wrong when invoking
+ *
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+class ErrorCheckingMemberFactory
+{
+ /**
+ * Wraps the generated JavassistMethod in an implementation that checks the
+ * parameters
+ *
+ * @param m The wrapped method
+ * @param method the target method for information about the parameters
+ * @return the error checking wrapper
+ */
+ static JavassistMethod wrapInErrorChecker(JavassistMethod m, CtMethod method)
+ {
+ if (m == null || method == null)
+ throw new IllegalArgumentException("Null method");
+
+ int numParameters = 0;
+ try
+ {
+ numParameters = method.getParameterTypes().length;
+ }
+ catch(NotFoundException e)
+ {
+ throw new IllegalArgumentException("Could not load the parameters for " + method);
+ }
+
+ return new ErrorCheckingJavassistMethod(m, method, numParameters);
+ }
+
+ /**
+ * Wraps the generated JavassistConstructor in an implementation that checks the
+ * parameters
+ *
+ * @param c The wrapped constructor
+ * @param constructor the target constructor for information about the parameters
+ * @return the error checking wrapper
+ */
+ static JavassistConstructor wrapInErrorChecker(JavassistConstructor c, CtConstructor constructor)
+ {
+ if (c == null || constructor == null)
+ throw new IllegalArgumentException("Null constructor");
+
+ int numParameters = 0;
+ try
+ {
+ numParameters = constructor.getParameterTypes().length;
+ }
+ catch(NotFoundException e)
+ {
+ throw new IllegalArgumentException("Could not load the parameters for " + constructor);
+ }
+
+ return new ErrorCheckingJavassistConstructor(c, constructor, numParameters);
+ }
+
+ /**
+ * Wraps the generated JavassistField in an implementation that checks the
+ * parameters
+ *
+ * @param f The wrapped field
+ * @param field the target field for information about the parameters
+ * @return the error checking wrapper
+ */
+ static JavassistField wrapInErrorChecker(JavassistField f, CtField field)
+ {
+ if (f == null)
+ throw new IllegalArgumentException("Null field");
+
+ return new ErrorCheckingJavassistField(f, field);
+ }
+
+ private static boolean checkNumberOfParameters(Object[] args, int numParameters)
+ {
+ if (args == null && numParameters > 0)
+ return false;
+ if (args != null && args.length != numParameters)
+ return false;
+ return true;
+ }
+
+ private static boolean isStatic(CtMember member)
+ {
+ return Modifier.isStatic(member.getModifiers());
+ }
+
+ private static void handleWrongParameters(String context, String target, Class<?>[] expected, Object[] args)
+ {
+ List<String> actual = new ArrayList<String>();
+ if (args != null)
+ {
+ for (Object argument : args)
+ {
+ if (argument == null)
+ actual.add(null);
+ else
+ actual.add(argument.getClass().getName());
+ }
+ }
+ throw new IllegalArgumentException("Wrong arguments. " + context + " for target " + target + " expected=" + expected + " actual=" + actual);
+
+ }
+
+ private static void handleWrongTarget(Object target, Class<?> expected, String name)
+ {
+ throw new IllegalArgumentException("Wrong target for " + name + " " + target.getClass().getName() + " is not a " + expected.getName());
+ }
+
+ private static void handleNullTarget(AccessibleObject ao)
+ {
+ throw new IllegalArgumentException("Null target calling non-static " + ao);
+ }
+
+ private static class ErrorCheckingJavassistMethod extends ErrorCheckingMemberFactory implements JavassistMethod
+ {
+ private final JavassistMethod delegate;
+ private final CtMethod ctMethod;
+ private final int numParameters;
+
+ private ErrorCheckingJavassistMethod(JavassistMethod delegate, CtMethod ctMethod, int numParameters)
+ {
+ this.delegate = delegate;
+ this.ctMethod = ctMethod;
+ this.numParameters = numParameters;
+ }
+
+ public Object invoke(Object target, Object[] args) throws Throwable
+ {
+ if (!checkNumberOfParameters(args, numParameters))
+ throw new IllegalArgumentException("Wrong number of parameters for " + ctMethod.getDeclaringClass() + "." + ctMethod.getName() + ctMethod.getSignature());
+
+ try
+ {
+ return delegate.invoke(target, args);
+ }
+ catch(ClassCastException e)
+ {
+ Method method = JavassistUtil.ctMethodToMethod(ctMethod);
+ if (!isStatic(ctMethod))
+ {
+ if (!method.getDeclaringClass().isAssignableFrom(target.getClass()))
+ handleWrongTarget(target, method.getDeclaringClass(), method.getName());
+ }
+
+ Class<?>[] params = method.getParameterTypes();
+ for (int i = 0 ; i < args.length ; i++)
+ {
+ if (!params[i].isAssignableFrom(args[i].getClass()))
+ handleWrongParameters(method.getName(), Strings.defaultToString(target), method.getParameterTypes(), args);
+ }
+
+ throw e;
+ }
+ catch(NullPointerException e)
+ {
+ Method method = JavassistUtil.ctMethodToMethod(ctMethod);
+ if (!isStatic(ctMethod) && target == null)
+ handleNullTarget(method);
+
+ CtClass[] parameters = ctMethod.getParameterTypes();
+ for (int i = 0 ; i < parameters.length ; i++)
+ {
+ if (parameters[i].isPrimitive() && args[i] == null)
+ handleWrongParameters(method.getName(), Strings.defaultToString(target), method.getParameterTypes(), args);
+ }
+
+ throw e;
+ }
+ }
+
+ }
+
+ private static class ErrorCheckingJavassistConstructor extends ErrorCheckingMemberFactory implements JavassistConstructor
+ {
+ private final JavassistConstructor delegate;
+ private final CtConstructor ctConstructor;
+ private final int numParameters;
+
+ private ErrorCheckingJavassistConstructor(JavassistConstructor delegate, CtConstructor ctConstructor, int numParameters)
+ {
+ this.delegate = delegate;
+ this.ctConstructor = ctConstructor;
+ this.numParameters = numParameters;
+ }
+
+ public Object newInstance(Object[] args) throws Throwable
+ {
+ if (!checkNumberOfParameters(args, numParameters))
+ throw new IllegalArgumentException("Wrong number of parameters for " + ctConstructor.getDeclaringClass() + "." + ctConstructor.getName() + ctConstructor.getSignature());
+
+ try
+ {
+ return delegate.newInstance(args);
+ }
+ catch(ClassCastException e)
+ {
+ Constructor<?> constructor = JavassistUtil.ctConstructorToConstructor(ctConstructor);
+ Class<?>[] params = constructor.getParameterTypes();
+ for (int i = 0 ; i < args.length ; i++)
+ {
+ if (!params[i].isAssignableFrom(args[i].getClass()))
+ handleWrongParameters("new", Strings.defaultToString(ctConstructor.getDeclaringClass().getName()), constructor.getParameterTypes(), args);
+ }
+
+ throw e;
+ }
+ catch(NullPointerException e)
+ {
+ CtClass[] parameters = ctConstructor.getParameterTypes();
+ for (int i = 0 ; i < parameters.length ; i++)
+ {
+ if (parameters[i].isPrimitive() && args[i] == null)
+ {
+ Constructor<?> constructor = JavassistUtil.ctConstructorToConstructor(ctConstructor);
+ handleWrongParameters("new", Strings.defaultToString(ctConstructor.getDeclaringClass().getName()), constructor.getParameterTypes(), args);
+ }
+ }
+
+ throw e;
+ }
+ }
+ }
+
+ private static class ErrorCheckingJavassistField extends ErrorCheckingMemberFactory implements JavassistField
+ {
+ private final JavassistField delegate;
+ private final CtField ctField;
+
+ private ErrorCheckingJavassistField(JavassistField delegate, CtField ctField)
+ {
+ this.delegate = delegate;
+ this.ctField = ctField;
+ }
+
+ public Object get(Object target) throws Throwable
+ {
+ try
+ {
+ return delegate.get(target);
+ }
+ catch (ClassCastException e)
+ {
+ Field field = JavassistUtil.ctFieldToField(ctField);
+
+ if (!isStatic(ctField) && !field.getDeclaringClass().isAssignableFrom(target.getClass()))
+ handleWrongTarget(target, field.getDeclaringClass(), field.getName());
+
+ throw e;
+ }
+ catch(NullPointerException e)
+ {
+ Field field = JavassistUtil.ctFieldToField(ctField);
+ if (!isStatic(ctField) && target == null)
+ handleNullTarget(field);
+ throw e;
+ }
+ }
+
+ public void set(Object target, Object value) throws Throwable
+ {
+ try
+ {
+ delegate.set(target, value);
+ }
+ catch (ClassCastException e)
+ {
+ Field field = JavassistUtil.ctFieldToField(ctField);
+ Class<?> type = field.getType();
+
+ if (!isStatic(ctField) && !field.getDeclaringClass().isAssignableFrom(target.getClass()))
+ handleWrongTarget(target, field.getDeclaringClass(), field.getName());
+
+ if (!type.isAssignableFrom(value.getClass()))
+ throw new IllegalArgumentException("Wrong arguments. Setting " + field.getName() + " for target " + target + " expected=" + field.getType() + " actual=" + value.getClass());
+ }
+ catch(NullPointerException e)
+ {
+ Field field = JavassistUtil.ctFieldToField(ctField);
+ if (!isStatic(ctField) && target == null)
+ handleNullTarget(field);
+ if (ctField.getType().isPrimitive() && value == null)
+ throw new IllegalArgumentException("Null value setting non-static field. " + field);
+ throw e;
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistBehaviorFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistBehaviorFactory.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistBehaviorFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -24,8 +24,6 @@
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.NotFoundException;
-import javassist.bytecode.Bytecode;
-import javassist.bytecode.Opcode;
import org.jboss.reflect.plugins.javassist.JavassistConstructor;
import org.jboss.reflect.plugins.javassist.JavassistMethod;
@@ -85,19 +83,21 @@
* Adds the byte code to push the parameters for a method/constructor
* on to the stack
*
- * @param code the byte code of the method we are generating
+ * @param cfwc the byte code of the method we are generating
* @param params the target parameter types
+ * @param the index of the parameter array
*/
- void addParameters(Bytecode code, CtClass[] params, int parameterIndex)
+ void addParameters(ClassFileWriterContext<?> cfwc, CtClass[] params, int parameterIndex)
{
for (int i = 0 ; i < params.length ; i++)
{
- code.addAload(parameterIndex);
- code.addIconst(i);
- code.addOpcode(Opcode.AALOAD);
+ cfwc.addAload(parameterIndex);
+ cfwc.addIconst(i);
+ cfwc.addAALoad();
+
if (!params[i].getName().equals(OBJECT_NAME))
{
- castAndUnbox(code, params[i]);
+ castAndUnbox(cfwc, params[i]);
}
}
}
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistConstructorFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistConstructorFactory.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistConstructorFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -25,12 +25,7 @@
import javassist.CtConstructor;
import javassist.Modifier;
-import javassist.bytecode.Bytecode;
-import javassist.bytecode.CodeAttribute;
-import javassist.bytecode.ConstPool;
import javassist.bytecode.MethodInfo;
-import javassist.bytecode.Opcode;
-import javassist.bytecode.StackMapTable;
import javassist.util.proxy.RuntimeSupport;
import org.jboss.reflect.plugins.javassist.JavassistConstructor;
@@ -51,11 +46,13 @@
private static final String[] interfaceNames = new String[] {JavassistConstructor.class.getName()};
/** The methods from the interface that are being implemented */
- private static final Method[] methods;
+ private static final Method[] methods = new Method[1];
+ /** The descriptors for the methods */
+ private static final String[] methodDescriptors = new String[1];
+
static
{
- methods = new Method[1];
try
{
methods[0] = SecurityActions.getDeclaredMethod(JavassistConstructor.class, "newInstance", Object[].class);
@@ -64,6 +61,7 @@
{
throw new RuntimeException(e);
}
+ methodDescriptors[0] = RuntimeSupport.makeDescriptor(methods[0]);
}
/** The constructor we are targeting */
@@ -85,51 +83,43 @@
this.ctConstructor = ctConstructor;
}
+ @Override
String getGeneratedClassName()
{
return className;
}
-
+ @Override
String[] getInterfaceNames()
{
return interfaceNames;
}
@Override
- MethodInfo implementMethod(int index, ConstPool cp)
+ boolean implementMethod(int index, ClassFileWriterContext<?> cfwc)
{
if (index >= methods.length)
- return null;
+ return false;
Method method = methods[index];
- String desc = RuntimeSupport.makeDescriptor(method);
- MethodInfo minfo = new MethodInfo(cp, method.getName(), desc);
- minfo.setAccessFlags(Modifier.PUBLIC);
- setThrows(minfo, cp, method.getExceptionTypes());
- Bytecode code = new Bytecode(cp, 0, 0);
-
- int pc = code.currentPc();
-
- code.addNew(ctConstructor.getDeclaringClass().getName());
- code.addOpcode(Opcode.DUP);
+ cfwc.beginMethod(Modifier.PUBLIC, method.getName(), methodDescriptors[index], THROWABLE_EXCEPTIONS);
- addParameters(code, getParameterTypes(), 1);
+ cfwc.addNew(ClassFileWriterContext.jvmClassName(ctConstructor.getDeclaringClass()));
+ cfwc.addDup();
- code.addInvokespecial(ctConstructor.getDeclaringClass(), "<init>", ctConstructor.getSignature());
- code.addOpcode(Opcode.ARETURN);
+ addParameters(cfwc, getParameterTypes(), 1);
+ cfwc.addInvokeSpecial(ClassFileWriterContext.jvmClassName(ctConstructor.getDeclaringClass()), MethodInfo.nameInit, ctConstructor.getSignature());
+ cfwc.addAReturn();
+
//We need 3 local variable slots.
//One for 'this', one for the target reference and one for the argument array.
- //These are all object references and so take one slot each
- code.setMaxLocals(3);
- CodeAttribute ca = code.toCodeAttribute();
- minfo.setCodeAttribute(ca);
-
- StackMapTable.Writer writer = new StackMapTable.Writer(32);
- writer.sameFrame(pc);
- ca.setAttribute(writer.toStackMapTable(cp));
- return minfo;
+ //These are all object references and so take one slot each
+
+ //TODO the max stack
+ cfwc.endMethod(3);
+
+ return true;
}
}
\ No newline at end of file
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistFieldFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistFieldFactory.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistFieldFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -27,12 +27,6 @@
import javassist.CtField;
import javassist.Modifier;
import javassist.NotFoundException;
-import javassist.bytecode.Bytecode;
-import javassist.bytecode.CodeAttribute;
-import javassist.bytecode.ConstPool;
-import javassist.bytecode.MethodInfo;
-import javassist.bytecode.Opcode;
-import javassist.bytecode.StackMapTable;
import javassist.util.proxy.RuntimeSupport;
import org.jboss.reflect.plugins.javassist.JavassistField;
@@ -54,7 +48,10 @@
/** The methods from the interface that are being implemented */
protected static final Method[] methods;
-
+
+ /** The descriptors for the methods */
+ private static final String[] methodDescriptors = new String[2];
+
static
{
interfaceNames = new String[] {JavassistField.class.getName()};
@@ -68,6 +65,9 @@
{
throw new RuntimeException(e);
}
+
+ methodDescriptors[0] = RuntimeSupport.makeDescriptor(methods[0]);
+ methodDescriptors[1] = RuntimeSupport.makeDescriptor(methods[1]);
}
/** The field we are targeting */
@@ -132,28 +132,25 @@
}
@Override
- MethodInfo implementMethod(int index, ConstPool cp)
+ boolean implementMethod(int index, ClassFileWriterContext<?> cfwc)
{
if (index >= methods.length)
- return null;
+ return false;
- String desc = RuntimeSupport.makeDescriptor(methods[index]);
- MethodInfo minfo = new MethodInfo(cp, methods[index].getName(), desc);
- minfo.setAccessFlags(Modifier.PUBLIC);
- setThrows(minfo, cp, methods[index].getExceptionTypes());
- Bytecode code = new Bytecode(cp, 0, 0);
-
- int pc = code.currentPc();
+ Method method = methods[index];
+
+ cfwc.beginMethod(Modifier.PUBLIC, method.getName(), methodDescriptors[index], THROWABLE_EXCEPTIONS);
+
boolean isStatic = Modifier.isStatic(ctField.getModifiers());
int maxLocals = 0;
if (index == 0)
{
//We need 2 local variable slots.
- //One for 'this' and one for the target reference
+ //One for 'this' and one for the argument array
//These are all object references and so take one slot each
maxLocals = 2;
- makeGetMethod(code, methods[index], cp, isStatic);
+ makeGetMethod(cfwc, isStatic);
}
else
{
@@ -161,59 +158,55 @@
//One for 'this', one for the target reference and one for the argument array.
//These are all object references and so take one slot each
maxLocals = 3;
- makeSetMethod(code, methods[index], cp, isStatic);
+ makeSetMethod(cfwc, isStatic);
}
-
- code.setMaxLocals(maxLocals);
- CodeAttribute ca = code.toCodeAttribute();
- minfo.setCodeAttribute(ca);
- StackMapTable.Writer writer = new StackMapTable.Writer(32);
- writer.sameFrame(pc);
- ca.setAttribute(writer.toStackMapTable(cp));
- return minfo;
+ cfwc.endMethod(maxLocals);
+
+ return true;
}
+
- private void makeGetMethod(Bytecode code, Method method, ConstPool cp, boolean isStatic)
+ private void makeGetMethod(ClassFileWriterContext<?> cfwc, boolean isStatic)
{
if (isStatic)
{
- code.addGetstatic(ctField.getDeclaringClass().getName(), ctField.getName(), ctField.getSignature());
+ cfwc.addGetStatic(ClassFileWriterContext.jvmClassName(ctField.getDeclaringClass()), ctField.getName(), ctField.getSignature());
}
else
{
+ String targetClassName = ClassFileWriterContext.jvmClassName(ctField.getDeclaringClass());
//push and cast the target object
- code.addAload(1);
- code.addCheckcast(ctField.getDeclaringClass());
- code.addGetfield(ctField.getDeclaringClass(), ctField.getName(), ctField.getSignature());
+ cfwc.addAload(1);
+ cfwc.addCheckcast(targetClassName);
+ cfwc.addGetField(targetClassName, ctField.getName(), ctField.getSignature());
}
- boxReturnValue(code, getFieldType());
- code.addOpcode(Opcode.ARETURN);
-
+ boxReturnValue(cfwc, getFieldType());
+ cfwc.addAReturn();
}
- private void makeSetMethod(Bytecode code, Method method, ConstPool cp, boolean isStatic)
+ private void makeSetMethod(ClassFileWriterContext<?> cfwc, boolean isStatic)
{
if (!isStatic)
{
//push and cast the target object
- code.addAload(1);
- code.addCheckcast(ctField.getDeclaringClass());
+ cfwc.addAload(1);
+ cfwc.addCheckcast(ClassFileWriterContext.jvmClassName(ctField.getDeclaringClass()));
}
//push and cast the value
- code.addAload(2);
- castAndUnbox(code, getFieldType());
+ cfwc.addAload(2);
+ castAndUnbox(cfwc, getFieldType());
if (isStatic)
{
- code.addPutstatic(ctField.getDeclaringClass().getName(), ctField.getName(), ctField.getSignature());
+ cfwc.addPutStatic(ClassFileWriterContext.jvmClassName(ctField.getDeclaringClass()), ctField.getName(), ctField.getSignature());
}
else
{
- code.addPutfield(ctField.getDeclaringClass(), ctField.getName(), ctField.getSignature());
+ cfwc.addPutField(ClassFileWriterContext.jvmClassName(ctField.getDeclaringClass()), ctField.getName(), ctField.getSignature());
}
- code.addOpcode(Opcode.RETURN);
+ cfwc.addAReturn();
}
}
\ No newline at end of file
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMemberFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMemberFactory.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMemberFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -21,50 +21,30 @@
*/
package org.jboss.reflect.plugins.javassist.bytecode;
-import java.io.DataOutputStream;
+import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
+import java.security.ProtectionDomain;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
-import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
-import javassist.CtMember;
import javassist.CtMethod;
-import javassist.Modifier;
-import javassist.NotFoundException;
-import javassist.bytecode.AccessFlag;
-import javassist.bytecode.Bytecode;
-import javassist.bytecode.ClassFile;
-import javassist.bytecode.CodeAttribute;
-import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
import javassist.bytecode.DuplicateMemberException;
-import javassist.bytecode.ExceptionsAttribute;
-import javassist.bytecode.MethodInfo;
-import javassist.bytecode.Opcode;
-import javassist.bytecode.StackMapTable;
-import javassist.util.proxy.FactoryHelper;
import javassist.util.proxy.RuntimeSupport;
import org.jboss.reflect.plugins.javassist.JavassistConstructor;
import org.jboss.reflect.plugins.javassist.JavassistField;
import org.jboss.reflect.plugins.javassist.JavassistMethod;
-import org.jboss.reflect.plugins.javassist.JavassistUtil;
-import org.jboss.util.Strings;
import org.jboss.util.UnreachableStatementException;
/**
@@ -80,38 +60,33 @@
*/
public abstract class JavassistMemberFactory
{
+ /** Object class name */
protected static final String OBJECT_NAME = Object.class.getName();
- protected static final String ILLEGAL_ARGUMENT_EXCEPTION_NAME = IllegalArgumentException.class.getName();
+ /** The jvm class name of Short */
+ private static final String SHORT_NAME = ClassFileWriterContext.jvmClassName(Short.class.getName());
- private static final String SHORT_NAME = Short.class.getName();
+ /** The jvm class name of Long */
+ private static final String LONG_NAME = ClassFileWriterContext.jvmClassName(Long.class.getName());
- private static final String LONG_NAME = Long.class.getName();
+ /** The jvm class name of Integer */
+ private static final String INTEGER_NAME = ClassFileWriterContext.jvmClassName(Integer.class.getName());
- private static final String INTEGER_NAME = Integer.class.getName();
+ /** The jvm class name of Float */
+ private static final String FLOAT_NAME = ClassFileWriterContext.jvmClassName(Float.class.getName());
- private static final String FLOAT_NAME = Float.class.getName();
+ /** The jvm class name of Double */
+ private static final String DOUBLE_NAME = ClassFileWriterContext.jvmClassName(Double.class.getName());
- private static final String DOUBLE_NAME = Double.class.getName();
+ /** The jvm class name of Character */
+ private static final String CHARACTER_NAME = ClassFileWriterContext.jvmClassName(Character.class.getName());
- private static final String CHARACTER_NAME = Character.class.getName();
+ /** The jvm class name of Byte */
+ protected static final String BYTE_NAME = ClassFileWriterContext.jvmClassName(Byte.class.getName());
- protected static final String BYTE_NAME = Byte.class.getName();
+ /** The jvm class name of Boolean */
+ protected static final String BOOLEAN_NAME = ClassFileWriterContext.jvmClassName(Boolean.class.getName());
- protected static final String BOOLEAN_NAME = Boolean.class.getName();
-
- /** Descriptor for new IllegalArgumentException(String) */
- protected static final String ILLEGAL_ARGUMENT_EXCEPTION_CONSTRUCTOR_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class<?>[] {String.class}, Void.TYPE);
-
- /** Descriptor for StringBuilder.toString() */
- protected static final String STRINGBUILDER_TOSTRING_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class<?>[0], String.class);
-
- /** Descriptor for StringBuilder.append(Object) */
- protected static final String STRINGBUILDER_APPEND_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class<?>[] {Object.class}, StringBuilder.class);
-
- /** Descriptor for new StringBuilder(String) */
- protected static final String STRINGBUILDER_CONSTRUCTOR_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class[]{String.class}, Void.TYPE);
-
/** Descriptor for Boolean.booleanValue() */
private final static String BOOLEAN_VALUE_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class[0], Boolean.TYPE);
@@ -159,6 +134,9 @@
/** Descriptor for Short.valueOf */
private final static String SHORT_VALUE_OF_DESCRIPTOR = RuntimeSupport.makeDescriptor(new Class[] {Short.TYPE}, Short.class);
+
+ /** Array of exceptions containing jvm name of Throwable */
+ protected final static String[] THROWABLE_EXCEPTIONS = new String[] {"java/lang/Throwable"};
/** The method class counter */
protected static final AtomicInteger counter = new AtomicInteger(0);
@@ -227,7 +205,7 @@
{
JavassistMemberFactory factory = new JavassistMethodFactory(superClass, ctMethod, debug);
Class<JavassistMethod> member = factory.makeClass(JavassistMethod.class, ctMethod.getDeclaringClass());
- return wrapInErrorChecker(factory.instantiate(member), ctMethod);
+ return ErrorCheckingMemberFactory.wrapInErrorChecker(factory.instantiate(member), ctMethod);
}
/**
@@ -243,7 +221,7 @@
{
JavassistMemberFactory factory = new JavassistConstructorFactory(superClass, ctConstructor, debug);
Class<JavassistConstructor> member = factory.makeClass(JavassistConstructor.class, ctConstructor.getDeclaringClass());
- return wrapInErrorChecker(factory.instantiate(member), ctConstructor);
+ return ErrorCheckingMemberFactory.wrapInErrorChecker(factory.instantiate(member), ctConstructor);
}
/**
@@ -259,7 +237,7 @@
{
JavassistMemberFactory factory = new JavassistFieldFactory(superClass, ctField, debug);
Class<JavassistField> member = factory.makeClass(JavassistField.class, ctField.getDeclaringClass());
- return wrapInErrorChecker(factory.instantiate(member), ctField);
+ return ErrorCheckingMemberFactory.wrapInErrorChecker(factory.instantiate(member), ctField);
}
/**
@@ -291,20 +269,21 @@
protected <T> Class<T> makeClass(Class<T> expected, CtClass target)
{
//Create a new public class
- final ClassFile cf = new ClassFile(false, getGeneratedClassName(), superClass.getName());
- cf.setAccessFlags(AccessFlag.PUBLIC);
- cf.setInterfaces(getInterfaceNames());
+ String name = getGeneratedClassName();
+ final ClassFileWriterContext<T> cfwc = new ClassFileWriterContext<T>(name, superClass.getName(), expected, getInterfaceNames());
try
{
- //Add the constructors from the super class
- makeConstructors(cf);
-
//implement the methods from the interfaces
- implementMethods(cf);
-
+ implementMethods(cfwc);
+
+
if (debug)
- debugWriteFile(cf);
+ {
+ debugWriteFile(cfwc);
+ }
+
+
}
catch(Exception e)
{
@@ -316,51 +295,51 @@
if (cl == null)
cl = SecurityActions.getContextClassLoader();
- return toClass(expected, target, cf, cl);
+ return toClass(cfwc, target, cl, null);
}
- private <T> Class<T> toClass(final Class<T> expected, final CtClass target, final ClassFile cf, final ClassLoader cl)
+ /**
+ * Create a class from the class file writer context
+ *
+ * @param cfwc the class file writer context
+ * @param target the target class
+ * @param cl the classloader
+ * @param domain the protection domain
+ * @return the class
+ *
+ */
+ private <T> Class<T> toClass(ClassFileWriterContext<T> cfwc, final CtClass target, ClassLoader cl, ProtectionDomain domain)
{
final ClassLoader actualLoader = PARENT_LOADER_HANDLER.getActualLoader(cl);
Throwable t = null;
+
try
{
- if (System.getSecurityManager() == null)
- return FactoryHelper.toClass(cf, actualLoader);
- else
- return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<T>>()
- {
- public Class<T> run() throws Exception
- {
- return FactoryHelper.toClass(cf, actualLoader);
- }
- });
+ return cfwc.toClass(actualLoader, domain);
}
- catch(CannotCompileException e)
+ catch (InvocationTargetException e)
{
t = e;
}
- catch (PrivilegedActionException e)
+ catch (IllegalAccessException e)
{
- t = e.getCause();
+ t = e;
}
- throw new RuntimeException("Error creating " + expected.getSimpleName() + " for " + target.getName() + " with classloader " + actualLoader + "(" + cl + ")", t);
+ throw new RuntimeException("Error creating " + cfwc.getSimpleType() + " for " + target.getName() + " with classloader " + actualLoader + "(" + cl + ")", t);
}
/**
* Implements the methods of the interface
*
- * @param cf the class file of the class we are creating
+ * @param cfcw the class file of the class we are creating
*/
- void implementMethods(ClassFile cf) throws DuplicateMemberException
+ void implementMethods(ClassFileWriterContext<?> cfcw) throws DuplicateMemberException
{
int i = 0;
while (true)
{
- MethodInfo minfo = implementMethod(i++, cf.getConstPool());
- if (minfo == null)
+ if (!implementMethod(i++, cfcw))
break;
- cf.addMethod(minfo);
}
}
@@ -382,10 +361,10 @@
* Create the method
*
* @param index the current index (starting at 0)
- * @param cp the constant pool
- * @return the created method, or null if there was no method with that index
+ * @param cfwc the class file writer context
+ * @return true, or false if there was no method with that index
*/
- abstract MethodInfo implementMethod(int index, ConstPool cp);
+ abstract boolean implementMethod(int index, ClassFileWriterContext<?> cfwc);
/**
* Get the names of the interfaces to implement
@@ -428,149 +407,49 @@
}
/**
- * Adds the constructors from the super class to the and delegates to them
- * via super calls
- *
- * @param cf the class file of the class we are creating
- * @throws CannotCompileException if any of the constructors could not be added
- */
- private void makeConstructors(ClassFile cf) throws CannotCompileException
- {
- Constructor<?>[] cons = SecurityActions.getDeclaredConstructors(superClass);
- for (int i = 0; i < cons.length; i++)
- {
- Constructor<?> c = cons[i];
- int mod = c.getModifiers();
- if (!Modifier.isFinal(mod) && !Modifier.isPrivate(mod))
- {
- MethodInfo m = makeConstructor(c, cf.getConstPool());
- cf.addMethod(m);
- }
- }
- }
-
- /**
- * Add a particular constructor from the super class and delegate to it via a
- * super call
- *
- * @param cons the constructor we are implementing
- * @param cp the constant pool of the class we are generating
- * @return the method info for the created constructor
- */
- private MethodInfo makeConstructor(Constructor<?> cons, ConstPool cp)
- {
- String desc = RuntimeSupport.makeDescriptor(cons.getParameterTypes(), Void.TYPE);
- MethodInfo minfo = new MethodInfo(cp, "<init>", desc);
- minfo.setAccessFlags(Modifier.PUBLIC);
- setThrows(minfo, cp, cons.getExceptionTypes());
- Bytecode code = new Bytecode(cp, 0, 0);
-
- int pc = code.currentPc();
-
- code.addAload(0);
- int s = addLoadParameters(code, cons.getParameterTypes(), 1);
- code.addInvokespecial(superClass.getName(), "<init>", desc);
- code.addOpcode(Opcode.RETURN);
- code.setMaxLocals(s + 1);
- CodeAttribute ca = code.toCodeAttribute();
- minfo.setCodeAttribute(ca);
-
- StackMapTable.Writer writer = new StackMapTable.Writer(32);
- writer.sameFrame(pc);
- ca.setAttribute(writer.toStackMapTable(cp));
- return minfo;
- }
-
- /**
- * Adds a throws clause to a method info
- *
- * @param minfo the method info being created
- * @param cp the constant pool of the class file the minfo will be added to
- * @param exceptions the exceptions to be added to the throws clause
- */
- void setThrows(MethodInfo minfo, ConstPool cp, Class<?>[] exceptions)
- {
- if (exceptions.length == 0)
- return;
-
- String[] list = new String[exceptions.length];
- for (int i = 0; i < exceptions.length; i++)
- list[i] = exceptions[i].getName();
-
- ExceptionsAttribute ea = new ExceptionsAttribute(cp);
- ea.setExceptions(list);
- minfo.setExceptionsAttribute(ea);
- }
-
- /**
* Writes the class file bytes to the local file system so they can be inspected
* with javap or another decompiler.
*
- * @param cf the class file
+ * @param cfwc the class file writer context
* @throws IOException if an error occurred writing the file
*/
- void debugWriteFile(ClassFile cf) throws IOException
+ void debugWriteFile(final ClassFileWriterContext<?> cfwc) throws IOException
{
- FileOutputStream fout = new FileOutputStream(cf.getName() + ".class");
- DataOutputStream out = new DataOutputStream(fout);
- try
+ try
{
- cf.write(out);
- }
- finally {
- out.close();
- }
- }
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+ {
- /**
- * Adds instructions to load all the parameters for a method/constructor
- *
- * @param code the byte code of the method/constructor being constructed
- * @param params the types of the parameters of the method/constructor
- * @param offset the offset
- * @return the stack size
- */
- int addLoadParameters(Bytecode code, Class<?>[] params, int offset)
- {
- int stacksize = 0;
- int n = params.length;
- for (int i = 0; i < n; ++i)
- stacksize += addLoad(code, stacksize + offset, params[i]);
-
- return stacksize;
- }
-
- /**
- * Adds the instruction to load a particular parameter for a method constructor
- *
- * @param code the byte code of the method/constructor being constructed
- * @param index the index of the parameter
- * @param type the type of the parameter
- * @return the stack size required for loading the parameter
- */
- int addLoad(Bytecode code, int index, Class<?> type)
- {
- if (type.isPrimitive())
+ public Object run() throws Exception
+ {
+ FileOutputStream fout = new FileOutputStream(cfwc.getName() + ".class");
+ BufferedOutputStream out = new BufferedOutputStream(fout);
+ try
+ {
+ out.write(cfwc.getBytes());
+ }
+ finally
+ {
+ try
+ {
+ out.close();
+ }
+ catch (Exception ignore)
+ {
+ }
+ }
+ return null;
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
{
- if (type == Long.TYPE)
- {
- code.addLload(index);
- return 2;
- }
- else if (type == Float.TYPE)
- code.addFload(index);
- else if (type == Double.TYPE)
- {
- code.addDload(index);
- return 2;
- }
- else
- code.addIload(index);
+ if (e.getCause() instanceof IOException)
+ throw (IOException)e.getCause();
+ if (e.getCause() instanceof RuntimeException)
+ throw (RuntimeException)e.getCause();
+ throw new RuntimeException(e.getCause());
}
- else
- code.addAload(index);
-
- return 1;
}
/**
@@ -609,138 +488,114 @@
return type.getName();
}
- String getArrayType(CtClass type)
- {
- StringBuilder buf = new StringBuilder();
-
- //int dims = 0;
- while (type.isArray())
- {
- buf.append("L");
- try
- {
- type = type.getComponentType();
- }
- catch(NotFoundException e)
- {
- throw new RuntimeException(e);
- }
- }
- buf.append(type.getName());
- buf.append(";");
-
- return buf.toString();
- }
-
/**
* Casts the value currently on the stack to the target type, and if a primitive
* unboxes it. The byte code instructions to do this are added to the
- * <code>code</code> parameter.
+ * <code>cfwc</code> parameter.
*
- * @param code the byte code of the method/constructor we are creating
+ * @param cfcw the class file writer context of the method/constructor we are creating
* @param type the target type we want to cast to
*/
- void castAndUnbox(Bytecode code, CtClass type)
+ void castAndUnbox(ClassFileWriterContext<?> cfwc, CtClass type)
{
if (type.getName().equals(OBJECT_NAME))
return;
- code.addCheckcast(getBoxedType(type));
+ cfwc.addCheckcast(ClassFileWriterContext.jvmClassName(getBoxedType(type)));
if (type.isPrimitive())
{
if (CtClass.booleanType.equals(type))
{
- code.addInvokevirtual(BOOLEAN_NAME, "booleanValue", BOOLEAN_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(BOOLEAN_NAME, "booleanValue", BOOLEAN_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.byteType.equals(type))
{
- code.addInvokevirtual(BYTE_NAME, "byteValue", BYTE_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(BYTE_NAME, "byteValue", BYTE_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.charType.equals(type))
{
- code.addInvokevirtual(CHARACTER_NAME, "charValue", CHAR_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(CHARACTER_NAME, "charValue", CHAR_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.doubleType.equals(type))
{
- code.addInvokevirtual(DOUBLE_NAME, "doubleValue", DOUBLE_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(DOUBLE_NAME, "doubleValue", DOUBLE_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.floatType.equals(type))
{
- code.addInvokevirtual(FLOAT_NAME, "floatValue", FLOAT_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(FLOAT_NAME, "floatValue", FLOAT_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.intType.equals(type))
{
- code.addInvokevirtual(INTEGER_NAME, "intValue", INTEGER_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(INTEGER_NAME, "intValue", INTEGER_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.longType.equals(type))
{
- code.addInvokevirtual(LONG_NAME, "longValue", LONG_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(LONG_NAME, "longValue", LONG_VALUE_DESCRIPTOR);
return;
}
else if (CtClass.shortType.equals(type))
{
- code.addInvokevirtual(SHORT_NAME, "shortValue", SHORT_VALUE_DESCRIPTOR);
+ cfwc.addInvokeVirtual(SHORT_NAME, "shortValue", SHORT_VALUE_DESCRIPTOR);
return;
}
throw new UnreachableStatementException();
}
-
}
/**
- * Adds the byte code instructions to the <code>code</code> paramter to box the value currently on the stack to the target type.
+ * Adds the byte code instructions to the <code>cfcw</code> paramter to box the value currently on the stack to the target type.
*
- * @param code the byte code of the method/constructor we are currently creating
+ * @param cfcw the class file writer context of the method/constructor we are creating
* @param type the type we want to cast to
*/
- void boxReturnValue(Bytecode code, CtClass type)
+ void boxReturnValue(ClassFileWriterContext<?> cfwc, CtClass type)
{
if (type.isPrimitive())
{
if (CtClass.booleanType.equals(type))
{
- code.addInvokestatic(BOOLEAN_NAME, "valueOf", BOOLEAN_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(BOOLEAN_NAME, "valueOf", BOOLEAN_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.byteType.equals(type))
{
- code.addInvokestatic(BYTE_NAME, "valueOf", BYTE_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(BYTE_NAME, "valueOf", BYTE_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.charType.equals(type))
{
- code.addInvokestatic(CHARACTER_NAME, "valueOf", CHARACTER_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(CHARACTER_NAME, "valueOf", CHARACTER_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.doubleType.equals(type))
{
- code.addInvokestatic(DOUBLE_NAME, "valueOf", DOUBLE_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(DOUBLE_NAME, "valueOf", DOUBLE_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.floatType.equals(type))
{
- code.addInvokestatic(FLOAT_NAME, "valueOf", FLOAT_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(FLOAT_NAME, "valueOf", FLOAT_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.intType.equals(type))
{
- code.addInvokestatic(INTEGER_NAME, "valueOf", INTEGER_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(INTEGER_NAME, "valueOf", INTEGER_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.longType.equals(type))
{
- code.addInvokestatic(LONG_NAME, "valueOf", LONG_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(LONG_NAME, "valueOf", LONG_VALUE_OF_DESCRIPTOR);
return;
}
else if (CtClass.shortType.equals(type))
{
- code.addInvokestatic(SHORT_NAME, "valueOf", SHORT_VALUE_OF_DESCRIPTOR);
+ cfwc.addInvokeStatic(SHORT_NAME, "valueOf", SHORT_VALUE_OF_DESCRIPTOR);
return;
}
throw new UnreachableStatementException();
@@ -748,293 +603,11 @@
}
/**
- * Wraps the generated JavassistMethod in an implementation that checks the
- * parameters
+ * In AS the JavassistMethod, -Constructor and -Field classloaders are not deployed in
+ * the system classpath. When generating an accessor for something from the system classpath
+ * we need to make sure it happens at the level that can see the implemented interfaces
*
- * @param m The wrapped method
- * @param method the target method for information about the parameters
- * @return the error checking wrapper
*/
- private static JavassistMethod wrapInErrorChecker(JavassistMethod m, CtMethod method)
- {
- if (m == null || method == null)
- throw new IllegalArgumentException("Null method");
-
- int numParameters = 0;
- try
- {
- numParameters = method.getParameterTypes().length;
- }
- catch(NotFoundException e)
- {
- throw new IllegalArgumentException("Could not load the parameters for " + method);
- }
-
- return new ErrorCheckingJavassistMethod(m, method, numParameters);
- }
-
- /**
- * Wraps the generated JavassistConstructor in an implementation that checks the
- * parameters
- *
- * @param c The wrapped constructor
- * @param constructor the target constructor for information about the parameters
- * @return the error checking wrapper
- */
- private static JavassistConstructor wrapInErrorChecker(JavassistConstructor c, CtConstructor constructor)
- {
- if (c == null || constructor == null)
- throw new IllegalArgumentException("Null constructor");
-
- int numParameters = 0;
- try
- {
- numParameters = constructor.getParameterTypes().length;
- }
- catch(NotFoundException e)
- {
- throw new IllegalArgumentException("Could not load the parameters for " + constructor);
- }
-
- return new ErrorCheckingJavassistConstructor(c, constructor, numParameters);
- }
-
- /**
- * Wraps the generated JavassistField in an implementation that checks the
- * parameters
- *
- * @param f The wrapped field
- * @param field the target field for information about the parameters
- * @return the error checking wrapper
- */
- private static JavassistField wrapInErrorChecker(JavassistField f, CtField field)
- {
- if (f == null)
- throw new IllegalArgumentException("Null field");
-
- return new ErrorCheckingJavassistField(f, field);
- }
-
- private static class ErrorChecker
- {
- protected boolean checkNumberOfParameters(Object[] args, int numParameters)
- {
- if (args == null && numParameters > 0)
- return false;
- if (args != null && args.length != numParameters)
- return false;
- return true;
- }
-
- protected boolean isStatic(CtMember member)
- {
- return Modifier.isStatic(member.getModifiers());
- }
-
- protected void handleWrongParameters(String context, String target, Class<?>[] expected, Object[] args)
- {
- List<String> actual = new ArrayList<String>();
- if (args != null)
- {
- for (Object argument : args)
- {
- if (argument == null)
- actual.add(null);
- else
- actual.add(argument.getClass().getName());
- }
- }
- throw new IllegalArgumentException("Wrong arguments. " + context + " for target " + target + " expected=" + expected + " actual=" + actual);
-
- }
-
- protected void handleWrongTarget(Object target, Class<?> expected, String name)
- {
- throw new IllegalArgumentException("Wrong target for " + name + " " + target.getClass().getName() + " is not a " + expected.getName());
- }
-
- protected void handleNullTarget(AccessibleObject ao)
- {
- throw new IllegalArgumentException("Null target calling non-static " + ao);
- }
-
- }
-
- private static class ErrorCheckingJavassistMethod extends ErrorChecker implements JavassistMethod
- {
- private final JavassistMethod delegate;
- private final CtMethod ctMethod;
- private final int numParameters;
-
- private ErrorCheckingJavassistMethod(JavassistMethod delegate, CtMethod ctMethod, int numParameters)
- {
- this.delegate = delegate;
- this.ctMethod = ctMethod;
- this.numParameters = numParameters;
- }
-
- public Object invoke(Object target, Object[] args) throws Throwable
- {
- if (!checkNumberOfParameters(args, numParameters))
- throw new IllegalArgumentException("Wrong number of parameters for " + ctMethod.getDeclaringClass() + "." + ctMethod.getName() + ctMethod.getSignature());
-
- try
- {
- return delegate.invoke(target, args);
- }
- catch(ClassCastException e)
- {
- Method method = JavassistUtil.ctMethodToMethod(ctMethod);
- if (!isStatic(ctMethod))
- {
- if (!method.getDeclaringClass().isAssignableFrom(target.getClass()))
- handleWrongTarget(target, method.getDeclaringClass(), method.getName());
- }
-
- Class<?>[] params = method.getParameterTypes();
- for (int i = 0 ; i < args.length ; i++)
- {
- if (!params[i].isAssignableFrom(args[i].getClass()))
- handleWrongParameters(method.getName(), Strings.defaultToString(target), method.getParameterTypes(), args);
- }
-
- throw e;
- }
- catch(NullPointerException e)
- {
- Method method = JavassistUtil.ctMethodToMethod(ctMethod);
- if (!isStatic(ctMethod) && target == null)
- handleNullTarget(method);
-
- CtClass[] parameters = ctMethod.getParameterTypes();
- for (int i = 0 ; i < parameters.length ; i++)
- {
- if (parameters[i].isPrimitive() && args[i] == null)
- handleWrongParameters(method.getName(), Strings.defaultToString(target), method.getParameterTypes(), args);
- }
-
- throw e;
- }
- }
-
- }
-
- private static class ErrorCheckingJavassistConstructor extends ErrorChecker implements JavassistConstructor
- {
- private final JavassistConstructor delegate;
- private final CtConstructor ctConstructor;
- private final int numParameters;
-
- private ErrorCheckingJavassistConstructor(JavassistConstructor delegate, CtConstructor ctConstructor, int numParameters)
- {
- this.delegate = delegate;
- this.ctConstructor = ctConstructor;
- this.numParameters = numParameters;
- }
-
- public Object newInstance(Object[] args) throws Throwable
- {
- if (!checkNumberOfParameters(args, numParameters))
- throw new IllegalArgumentException("Wrong number of parameters for " + ctConstructor.getDeclaringClass() + "." + ctConstructor.getName() + ctConstructor.getSignature());
-
- try
- {
- return delegate.newInstance(args);
- }
- catch(ClassCastException e)
- {
- Constructor<?> constructor = JavassistUtil.ctConstructorToConstructor(ctConstructor);
- Class<?>[] params = constructor.getParameterTypes();
- for (int i = 0 ; i < args.length ; i++)
- {
- if (!params[i].isAssignableFrom(args[i].getClass()))
- handleWrongParameters("new", Strings.defaultToString(ctConstructor.getDeclaringClass().getName()), constructor.getParameterTypes(), args);
- }
-
- throw e;
- }
- catch(NullPointerException e)
- {
- CtClass[] parameters = ctConstructor.getParameterTypes();
- for (int i = 0 ; i < parameters.length ; i++)
- {
- if (parameters[i].isPrimitive() && args[i] == null)
- {
- Constructor<?> constructor = JavassistUtil.ctConstructorToConstructor(ctConstructor);
- handleWrongParameters("new", Strings.defaultToString(ctConstructor.getDeclaringClass().getName()), constructor.getParameterTypes(), args);
- }
- }
-
- throw e;
- }
- }
- }
-
- private static class ErrorCheckingJavassistField extends ErrorChecker implements JavassistField
- {
- private final JavassistField delegate;
- private final CtField ctField;
-
- private ErrorCheckingJavassistField(JavassistField delegate, CtField ctField)
- {
- this.delegate = delegate;
- this.ctField = ctField;
- }
-
- public Object get(Object target) throws Throwable
- {
- try
- {
- return delegate.get(target);
- }
- catch (ClassCastException e)
- {
- Field field = JavassistUtil.ctFieldToField(ctField);
-
- if (!isStatic(ctField) && !field.getDeclaringClass().isAssignableFrom(target.getClass()))
- handleWrongTarget(target, field.getDeclaringClass(), field.getName());
-
- throw e;
- }
- catch(NullPointerException e)
- {
- Field field = JavassistUtil.ctFieldToField(ctField);
- if (!isStatic(ctField) && target == null)
- handleNullTarget(field);
- throw e;
- }
- }
-
- public void set(Object target, Object value) throws Throwable
- {
- try
- {
- delegate.set(target, value);
- }
- catch (ClassCastException e)
- {
- Field field = JavassistUtil.ctFieldToField(ctField);
- Class<?> type = field.getType();
-
- if (!isStatic(ctField) && !field.getDeclaringClass().isAssignableFrom(target.getClass()))
- handleWrongTarget(target, field.getDeclaringClass(), field.getName());
-
- if (!type.isAssignableFrom(value.getClass()))
- throw new IllegalArgumentException("Wrong arguments. Setting " + field.getName() + " for target " + target + " expected=" + field.getType() + " actual=" + value.getClass());
- }
- catch(NullPointerException e)
- {
- Field field = JavassistUtil.ctFieldToField(ctField);
- if (!isStatic(ctField) && target == null)
- handleNullTarget(field);
- if (ctField.getType().isPrimitive() && value == null)
- throw new IllegalArgumentException("Null value setting non-static field. " + field);
- throw e;
- }
- }
- }
-
-
private static class ParentLoaderHandler
{
final ClassLoader reflectLoader;
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMethodFactory.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMethodFactory.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/JavassistMethodFactory.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -27,12 +27,6 @@
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
-import javassist.bytecode.Bytecode;
-import javassist.bytecode.CodeAttribute;
-import javassist.bytecode.ConstPool;
-import javassist.bytecode.MethodInfo;
-import javassist.bytecode.Opcode;
-import javassist.bytecode.StackMapTable;
import javassist.util.proxy.RuntimeSupport;
import org.jboss.reflect.plugins.javassist.JavassistMethod;
@@ -55,6 +49,9 @@
/** The methods from the interface that are being implemented */
private static final Method[] methods;
+ /** The descriptors for the methods */
+ private static final String[] methodDescriptors = new String[1];
+
static
{
interfaceNames = new String[] {JavassistMethod.class.getName()};
@@ -66,7 +63,8 @@
catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
- }
+ }
+ methodDescriptors[0] = RuntimeSupport.makeDescriptor(methods[0]);
}
/** The method we are targeting */
@@ -118,63 +116,55 @@
}
@Override
- MethodInfo implementMethod(int index, ConstPool cp)
+ boolean implementMethod(int index, ClassFileWriterContext<?> cfwc)
{
if (index >= methods.length)
- return null;
+ return false;
Method method = methods[index];
- String desc = RuntimeSupport.makeDescriptor(method);
- MethodInfo minfo = new MethodInfo(cp, method.getName(), desc);
- minfo.setAccessFlags(Modifier.PUBLIC);
- setThrows(minfo, cp, method.getExceptionTypes());
- Bytecode code = new Bytecode(cp, 0, 0);
-
- int pc = code.currentPc();
-
-
+ cfwc.beginMethod(Modifier.PUBLIC, method.getName(), methodDescriptors[index], THROWABLE_EXCEPTIONS);
+
boolean isStatic = Modifier.isStatic(ctBehavior.getModifiers());
-
+
+ String targetClassName = ClassFileWriterContext.jvmClassName(ctMethod.getDeclaringClass());
if (!isStatic)
{
//push and cast the target object
- code.addAload(1);
- code.addCheckcast(ctMethod.getDeclaringClass());
+ cfwc.addAload(1);
+ cfwc.addCheckcast(targetClassName);
}
- addParameters(code, getParameterTypes(), 2);
-
+ addParameters(cfwc, getParameterTypes(), 2);
+
if (isStatic)
- code.addInvokestatic(ctMethod.getDeclaringClass(), ctMethod.getName(), ctMethod.getSignature());
+ cfwc.addInvokeStatic(targetClassName, ctMethod.getName(), ctMethod.getSignature());
else if (ctMethod.getDeclaringClass().isInterface())
- code.addInvokeinterface(ctMethod.getDeclaringClass(), ctMethod.getName(), ctMethod.getSignature(), countParameterStackSize(0, getParameterTypes()));
+ {
+ cfwc.addInvokeInterface(targetClassName, ctMethod.getName(), ctMethod.getSignature(), countParameterStackSize(0, getParameterTypes()));
+ }
else
- code.addInvokevirtual(ctMethod.getDeclaringClass(), ctMethod.getName(), ctMethod.getSignature());
+ cfwc.addInvokeVirtual(targetClassName, ctMethod.getName(), ctMethod.getSignature());
if (getReturnType() == CtClass.voidType)
- {
- //return null;
- code.addOpcode(Opcode.ACONST_NULL);
- code.addOpcode(Opcode.ARETURN);
+ {
+ //return null
+ cfwc.addAConstNull();
+ cfwc.addAReturn();
}
else
{
- boxReturnValue(code, getReturnType());
- code.addOpcode(Opcode.ARETURN);
+ boxReturnValue(cfwc, getReturnType());
+ cfwc.addAReturn();
}
//We need 3 local variable slots.
//One for 'this', one for the target reference and one for the argument array.
//These are all object references and so take one slot each
- code.setMaxLocals(3);
-
- CodeAttribute ca = code.toCodeAttribute();
- minfo.setCodeAttribute(ca);
- StackMapTable.Writer writer = new StackMapTable.Writer(32);
- writer.sameFrame(pc);
- ca.setAttribute(writer.toStackMapTable(cp));
- return minfo;
+ //TODO the max stack
+ cfwc.endMethod(3);
+
+ return true;
}
}
\ No newline at end of file
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/SecurityActions.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/SecurityActions.java 2010-05-12 10:45:48 UTC (rev 104719)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/bytecode/SecurityActions.java 2010-05-12 11:01:32 UTC (rev 104720)
@@ -21,7 +21,9 @@
*/
package org.jboss.reflect.plugins.javassist.bytecode;
+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -111,4 +113,47 @@
}
}
}
+
+ static void setAccessible(final AccessibleObject member)
+ {
+ if (System.getSecurityManager() == null)
+ member.setAccessible(true);
+ else
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
+ {
+ public Object run()
+ {
+ member.setAccessible(true);
+ return null;
+ }
+ });
+ }
+
+ static Object invoke(final Method method, final Object target, final Object...args) throws IllegalAccessException, InvocationTargetException
+ {
+ if (System.getSecurityManager() == null)
+ return method.invoke(target, args);
+
+ try
+ {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws Exception
+ {
+ return method.invoke(target, args);
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ if (e.getCause() instanceof RuntimeException)
+ throw (RuntimeException)e.getCause();
+ if (e.getCause() instanceof IllegalAccessException)
+ throw (IllegalAccessException)e.getCause();
+ if (e.getCause() instanceof InvocationTargetException)
+ throw (InvocationTargetException)e.getCause();
+
+ throw new RuntimeException(e.getCause());
+ }
+ }
}
More information about the jboss-cvs-commits
mailing list