public void addSetMethod(MetaBeanProperty property) throws Exception { MetaMethod setter = property.getSetter(); Type paramType = Type.getType(setter.getParameterTypes()[0].getTheClass()); Type returnType = Type.getType(setter.getReturnType()); String setterDescriptor = Type.getMethodDescriptor(returnType, new Type[] {paramType}); // GENERATE public void <propName>(<type> v) { <setter>(v) } String setMethodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {paramType}); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, property.getName(), setMethodDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE <setter>(v) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitVarInsn(paramType.getOpcode(Opcodes.ILOAD), 1); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), setter.getName(), setterDescriptor); // END methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
private void addGetter(String methodName, String methodDescriptor, MethodCodeBody body) throws Exception { MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, methodName, methodDescriptor, null, new String[0]); methodVisitor.visitCode(); body.add(methodVisitor); methodVisitor.visitInsn(Opcodes.ARETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
private void addSetter(Method method, MethodCodeBody body) throws Exception { String methodDescriptor = Type.getMethodDescriptor(method); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, method.getName(), methodDescriptor, null, new String[0]); methodVisitor.visitCode(); body.add(methodVisitor); methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
public void addSetter(MetaBeanProperty property) throws Exception { MetaMethod setter = property.getSetter(); // GENERATE public <return-type> <setter>(<type> v) { <return-type> v = super.<setter>(v); // <prop>Set = true; return v; } Type paramType = Type.getType(setter.getParameterTypes()[0].getTheClass()); Type returnType = Type.getType(setter.getReturnType()); String setterDescriptor = Type.getMethodDescriptor(returnType, new Type[] {paramType}); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, setter.getName(), setterDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE super.<setter>(v) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitVarInsn(paramType.getOpcode(Opcodes.ILOAD), 1); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, superclassType.getInternalName(), setter.getName(), setterDescriptor); // END // GENERATE <prop>Set = true methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitLdcInsn(true); methodVisitor.visitFieldInsn( Opcodes.PUTFIELD, generatedType.getInternalName(), String.format("%sSet", property.getName()), Type.BOOLEAN_TYPE.getDescriptor()); // END methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
public void addActionMethod(MetaMethod method) throws Exception { Type actionImplType = Type.getType(ClosureBackedAction.class); Type closureType = Type.getType(Closure.class); String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {closureType}); // GENERATE public void <method>(Closure v) { <method>(new ClosureBackedAction(v)); } MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, method.getName(), methodDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE <method>(new ClosureBackedAction(v)); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); // GENERATE new ClosureBackedAction(v); methodVisitor.visitTypeInsn(Opcodes.NEW, actionImplType.getInternalName()); methodVisitor.visitInsn(Opcodes.DUP); methodVisitor.visitVarInsn(Opcodes.ALOAD, 1); String constuctorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {closureType}); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, actionImplType.getInternalName(), "<init>", constuctorDescriptor); methodDescriptor = Type.getMethodDescriptor( Type.getType(method.getReturnType()), new Type[] {Type.getType(method.getParameterTypes()[0].getTheClass())}); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), method.getName(), methodDescriptor); methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
public void addConstructor(Constructor<?> constructor) throws Exception { List<Type> paramTypes = new ArrayList<Type>(); for (Class<?> paramType : constructor.getParameterTypes()) { paramTypes.add(Type.getType(paramType)); } String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, paramTypes.toArray(new Type[paramTypes.size()])); String signature = signature(constructor); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, "<init>", methodDescriptor, signature, new String[0]); methodVisitor.visitCode(); // this.super(p0 .. pn) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); for (int i = 0; i < constructor.getParameterTypes().length; i++) { methodVisitor.visitVarInsn( Type.getType(constructor.getParameterTypes()[i]).getOpcode(Opcodes.ILOAD), i + 1); } methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, superclassType.getInternalName(), "<init>", methodDescriptor); if (initDynamicObjectHelper != null) { initDynamicObjectHelper.add(methodVisitor); } if (initConventionAwareHelper != null) { initConventionAwareHelper.add(methodVisitor); } if (initMetaClass != null) { initMetaClass.add(methodVisitor); } methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
private void addConventionGetter(String getterName, String flagName, MetaBeanProperty property) throws Exception { // GENERATE public <type> <getter>() { return // (<type>)getConventionMapping().getConventionValue(super.<getter>(), '<prop>', <prop>Set); } MetaMethod getter = property.getGetter(); Type returnType = Type.getType(getter.getReturnType()); String methodDescriptor = Type.getMethodDescriptor(returnType, new Type[0]); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, getterName, methodDescriptor, null, new String[0]); methodVisitor.visitCode(); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, conventionAwareType.getInternalName(), "getConventionMapping", Type.getMethodDescriptor(conventionMappingType, new Type[0])); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitMethodInsn( Opcodes.INVOKESPECIAL, superclassType.getInternalName(), getterName, methodDescriptor); Type boxedType = null; if (getter.getReturnType().isPrimitive()) { // Box value boxedType = Type.getType(JavaReflectionUtil.getWrapperTypeForPrimitiveType(getter.getReturnType())); String valueOfMethodDescriptor = Type.getMethodDescriptor(boxedType, new Type[] {returnType}); methodVisitor.visitMethodInsn( Opcodes.INVOKESTATIC, boxedType.getInternalName(), "valueOf", valueOfMethodDescriptor); } methodVisitor.visitLdcInsn(property.getName()); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitFieldInsn( Opcodes.GETFIELD, generatedType.getInternalName(), flagName, Type.BOOLEAN_TYPE.getDescriptor()); String getConventionValueDesc = Type.getMethodDescriptor( ConventionMapping.class.getMethod( "getConventionValue", Object.class, String.class, Boolean.TYPE)); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, conventionMappingType.getInternalName(), "getConventionValue", getConventionValueDesc); if (getter.getReturnType().isPrimitive()) { // Unbox value methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, boxedType.getInternalName()); String valueMethodDescriptor = Type.getMethodDescriptor(returnType, new Type[0]); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, boxedType.getInternalName(), getter.getReturnType().getName() + "Value", valueMethodDescriptor); } else { // Cast to return type methodVisitor.visitTypeInsn( Opcodes.CHECKCAST, getter.getReturnType().isArray() ? "[" + returnType.getElementType().getDescriptor() : returnType.getInternalName()); } methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); }
public void addDynamicMethods() throws Exception { // GENERATE public Object getProperty(String name) { return // getAsDynamicObject().getProperty(name); } addGetter( GroovyObject.class.getDeclaredMethod("getProperty", String.class), new MethodCodeBody() { public void add(MethodVisitor methodVisitor) throws Exception { // GENERATE getAsDynamicObject().getProperty(name); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); String getAsDynamicObjectDesc = Type.getMethodDescriptor( DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject")); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getAsDynamicObject", getAsDynamicObjectDesc); methodVisitor.visitVarInsn(Opcodes.ALOAD, 1); String getPropertyDesc = Type.getMethodDescriptor( DynamicObject.class.getDeclaredMethod("getProperty", String.class)); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, dynamicObjectType.getInternalName(), "getProperty", getPropertyDesc); // END } }); // GENERATE public boolean hasProperty(String name) { return // getAsDynamicObject().hasProperty(name) } String methodDescriptor = Type.getMethodDescriptor( Type.getType(Boolean.TYPE), new Type[] {Type.getType(String.class)}); MethodVisitor methodVisitor = visitor.visitMethod( Opcodes.ACC_PUBLIC, "hasProperty", methodDescriptor, null, new String[0]); methodVisitor.visitCode(); // GENERATE getAsDynamicObject().hasProperty(name); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); String getAsDynamicObjectDesc = Type.getMethodDescriptor( DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject")); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getAsDynamicObject", getAsDynamicObjectDesc); methodVisitor.visitVarInsn(Opcodes.ALOAD, 1); String getPropertyDesc = Type.getMethodDescriptor( DynamicObject.class.getDeclaredMethod("hasProperty", String.class)); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, dynamicObjectType.getInternalName(), "hasProperty", getPropertyDesc); // END methodVisitor.visitInsn(Opcodes.IRETURN); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd(); // GENERATE public void setProperty(String name, Object value) { // getAsDynamicObject().setProperty(name, value); } addSetter( GroovyObject.class.getDeclaredMethod("setProperty", String.class, Object.class), new MethodCodeBody() { public void add(MethodVisitor methodVisitor) throws Exception { // GENERATE getAsDynamicObject().setProperty(name, value) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); String getAsDynamicObjectDesc = Type.getMethodDescriptor( DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject")); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getAsDynamicObject", getAsDynamicObjectDesc); methodVisitor.visitVarInsn(Opcodes.ALOAD, 1); methodVisitor.visitVarInsn(Opcodes.ALOAD, 2); String setPropertyDesc = Type.getMethodDescriptor( DynamicObject.class.getDeclaredMethod( "setProperty", String.class, Object.class)); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, dynamicObjectType.getInternalName(), "setProperty", setPropertyDesc); // END } }); // GENERATE public Object invokeMethod(String name, Object params) { return // getAsDynamicObject().invokeMethod(name, (Object[])params); } addGetter( GroovyObject.class.getDeclaredMethod("invokeMethod", String.class, Object.class), new MethodCodeBody() { public void add(MethodVisitor methodVisitor) throws Exception { String invokeMethodDesc = Type.getMethodDescriptor( Type.getType(Object.class), new Type[] {Type.getType(String.class), Type.getType(Object[].class)}); String objArrayDesc = Type.getType(Object[].class).getDescriptor(); // GENERATE getAsDynamicObject().invokeMethod(name, (args instanceof Object[]) ? args // : new Object[] { args }) methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); String getAsDynamicObjectDesc = Type.getMethodDescriptor( DynamicObjectAware.class.getDeclaredMethod("getAsDynamicObject")); methodVisitor.visitMethodInsn( Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getAsDynamicObject", getAsDynamicObjectDesc); methodVisitor.visitVarInsn(Opcodes.ALOAD, 1); // GENERATE (args instanceof Object[]) ? args : new Object[] { args } methodVisitor.visitVarInsn(Opcodes.ALOAD, 2); methodVisitor.visitTypeInsn(Opcodes.INSTANCEOF, objArrayDesc); Label end = new Label(); Label notArray = new Label(); methodVisitor.visitJumpInsn(Opcodes.IFEQ, notArray); // Generate args // methodVisitor.visitInsn(Opcodes.ACONST_NULL); methodVisitor.visitVarInsn(Opcodes.ALOAD, 2); methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, objArrayDesc); methodVisitor.visitJumpInsn(Opcodes.GOTO, end); // Generate new Object[] { args } methodVisitor.visitLabel(notArray); methodVisitor.visitInsn(Opcodes.ICONST_1); methodVisitor.visitTypeInsn( Opcodes.ANEWARRAY, Type.getType(Object.class).getInternalName()); methodVisitor.visitInsn(Opcodes.DUP); methodVisitor.visitInsn(Opcodes.ICONST_0); methodVisitor.visitVarInsn(Opcodes.ALOAD, 2); methodVisitor.visitInsn(Opcodes.AASTORE); methodVisitor.visitLabel(end); methodVisitor.visitMethodInsn( Opcodes.INVOKEINTERFACE, dynamicObjectType.getInternalName(), "invokeMethod", invokeMethodDesc); } }); }