private void boxType(MethodVisitor methodVisitor, Class<?> primitiveType) { Class<?> boxedType = BOXED_TYPES.get(primitiveType); methodVisitor.visitMethodInsn( INVOKESTATIC, Type.getInternalName(boxedType), "valueOf", "(" + Type.getDescriptor(primitiveType) + ")" + Type.getDescriptor(boxedType), false); }
/** * Adds a number or string constant to the constant pool of the class being build. Does nothing if * the constant pool already contains a similar item. * * @param cst the value of the constant to be added to the constant pool. This parameter must be * an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String} or * a {@link Type}. * @return a new or already existing constant item with the given value. */ Item newConstItem(final Object cst) { if (cst instanceof Integer) { int val = ((Integer) cst).intValue(); return newInteger(val); } else if (cst instanceof Byte) { int val = ((Byte) cst).intValue(); return newInteger(val); } else if (cst instanceof Character) { int val = ((Character) cst).charValue(); return newInteger(val); } else if (cst instanceof Short) { int val = ((Short) cst).intValue(); return newInteger(val); } else if (cst instanceof Boolean) { int val = ((Boolean) cst).booleanValue() ? 1 : 0; return newInteger(val); } else if (cst instanceof Float) { float val = ((Float) cst).floatValue(); return newFloat(val); } else if (cst instanceof Long) { long val = ((Long) cst).longValue(); return newLong(val); } else if (cst instanceof Double) { double val = ((Double) cst).doubleValue(); return newDouble(val); } else if (cst instanceof String) { return newString((String) cst); } else if (cst instanceof Type) { Type t = (Type) cst; return newClassItem(t.getSort() == Type.OBJECT ? t.getInternalName() : t.getDescriptor()); } else { throw new IllegalArgumentException("value " + cst); } }
protected void injectGetByIndex( ClassWriter classWriter, String targetClassName, List<Field> fields) { MethodVisitor methodVisitor = classWriter.visitMethod( ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())}); Boxer boxer = new Boxer(methodVisitor); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ILOAD, 2); int maxStack = 6; Label[] labels = new Label[fields.size()]; Label errorLabel = new Label(); for (int i = 0; i < fields.size(); i++) { labels[i] = new Label(); } methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels); if (!fields.isEmpty()) { maxStack--; for (int i = 0; i < fields.size(); i++) { Field field = fields.get(i); Class<?> type = field.getType(); String fieldDescriptor = Type.getDescriptor(type); methodVisitor.visitLabel(labels[i]); if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null); else methodVisitor.visitFrame(F_SAME, 0, null, 0, null); if (isPublic(field)) { methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitTypeInsn(CHECKCAST, targetClassName); methodVisitor.visitFieldInsn(GETFIELD, targetClassName, field.getName(), fieldDescriptor); boxer.box(Type.getType(type)); } else { injectReflectiveGetter(methodVisitor); } methodVisitor.visitInsn(ARETURN); } methodVisitor.visitLabel(errorLabel); methodVisitor.visitFrame(F_SAME, 0, null, 0, null); } injectException(methodVisitor, IllegalAccessException.class); methodVisitor.visitMaxs(maxStack, 3); methodVisitor.visitEnd(); }
private FieldVisitor declareStaticField(ClassVisitor visitor, String name, Class<?> fieldClass) { return visitor.visitField( ACC_PRIVATE | ACC_FINAL | ACC_STATIC | ACC_SYNTHETIC, name, Type.getDescriptor(fieldClass), null, null); }
private void assignTypeConverterField(MethodVisitor constructorVisitor, Type generatedType) { putThisOnStack(constructorVisitor); putSecondMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), TYPE_CONVERTER_FIELD_NAME, TYPE_CONVERTER_TYPE.getDescriptor()); }
private void assignStateField(MethodVisitor constructorVisitor, Type generatedType) { putThisOnStack(constructorVisitor); putFirstMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), STATE_FIELD_NAME, MODEL_ELEMENT_STATE_TYPE.getDescriptor()); }
private static void generateLocalVariableTable( @NotNull MethodVisitor mv, @NotNull JvmMethodSignature jvmMethodSignature, @NotNull FunctionDescriptor functionDescriptor, @Nullable Type thisType, @NotNull Label methodBegin, @NotNull Label methodEnd, @NotNull OwnerKind ownerKind) { Iterator<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator(); List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters(); int shift = 0; boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor); if (!isStatic) { // add this if (thisType != null) { mv.visitLocalVariable( "this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift); } else { // TODO: provide thisType for callable reference } shift++; } for (int i = 0; i < params.size(); i++) { JvmMethodParameterSignature param = params.get(i); JvmMethodParameterKind kind = param.getKind(); String parameterName; if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = valueParameters.next(); parameterName = parameter.getName().asString(); } else { String lowercaseKind = kind.name().toLowerCase(); parameterName = needIndexForVar(kind) ? "$" + lowercaseKind + "$" + i : "$" + lowercaseKind; } Type type = param.getAsmType(); mv.visitLocalVariable( parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift); shift += type.getSize(); } }
private void assignDelegateField( MethodVisitor constructorVisitor, Type generatedType, Type delegateType) { putThisOnStack(constructorVisitor); putThirdMethodArgumentOnStack(constructorVisitor); constructorVisitor.visitFieldInsn( PUTFIELD, generatedType.getInternalName(), DELEGATE_FIELD_NAME, delegateType.getDescriptor()); }
private void writeManagedTypeStaticField( Type generatedType, Class<?> managedTypeClass, MethodVisitor constructorVisitor) { constructorVisitor.visitLdcInsn(Type.getType(managedTypeClass)); constructorVisitor.visitMethodInsn( INVOKESTATIC, MODELTYPE_INTERNAL_NAME, "of", MODELTYPE_OF_METHOD_DESCRIPTOR, false); constructorVisitor.visitFieldInsn( PUTSTATIC, generatedType.getInternalName(), MANAGED_TYPE_FIELD_NAME, Type.getDescriptor(ModelType.class)); }
/** Generate a call to the delegate object. */ protected MethodVisitor makeDelegateCall( final String name, final String desc, final String signature, final String[] exceptions, final int accessFlags) { MethodVisitor mv = super.visitMethod(accessFlags, name, desc, signature, exceptions); mv.visitVarInsn(ALOAD, 0); // load this mv.visitFieldInsn( GETFIELD, proxyName, DELEGATE_OBJECT_FIELD, BytecodeHelper.getTypeDescription(delegateClass)); // load delegate // using InvokerHelper to allow potential intercepted calls int size; mv.visitLdcInsn(name); // method name Type[] args = Type.getArgumentTypes(desc); BytecodeHelper.pushConstant(mv, args.length); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); size = 3; int idx = 1; for (int i = 0; i < args.length; i++) { Type arg = args[i]; mv.visitInsn(DUP); BytecodeHelper.pushConstant(mv, i); // primitive types must be boxed if (isPrimitive(arg)) { mv.visitIntInsn(getLoadInsn(arg), idx); String wrappedType = getWrappedClassDescriptor(arg); mv.visitMethodInsn( INVOKESTATIC, wrappedType, "valueOf", "(" + arg.getDescriptor() + ")L" + wrappedType + ";"); } else { mv.visitVarInsn(ALOAD, idx); // load argument i } size = Math.max(6, 5 + registerLen(arg)); idx += registerLen(arg); mv.visitInsn(AASTORE); // store value into array } mv.visitMethodInsn( INVOKESTATIC, "org/codehaus/groovy/runtime/InvokerHelper", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;"); unwrapResult(mv, desc); mv.visitMaxs(size, registerLen(args) + 1); return EMPTY_VISITOR; }
private MethodVisitor createConstructor( final int access, final String name, final String desc, final String signature, final String[] exceptions) { Type[] args = Type.getArgumentTypes(desc); StringBuilder newDesc = new StringBuilder("("); for (Type arg : args) { newDesc.append(arg.getDescriptor()); } newDesc.append("Ljava/util/Map;"); // the closure map if (generateDelegateField) { newDesc.append(BytecodeHelper.getTypeDescription(delegateClass)); } newDesc.append(")V"); MethodVisitor mv = super.visitMethod(access, name, newDesc.toString(), signature, exceptions); mv.visitCode(); initializeDelegateClosure(mv, args.length); if (generateDelegateField) { initializeDelegateObject(mv, args.length + 1); } mv.visitVarInsn(ALOAD, 0); int idx = 1; for (Type arg : args) { if (isPrimitive(arg)) { mv.visitIntInsn(getLoadInsn(arg), idx); } else { mv.visitVarInsn(ALOAD, idx); // load argument i } idx += registerLen(arg); } mv.visitMethodInsn( INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass), "<init>", desc); mv.visitInsn(RETURN); int max = idx + 1 + (generateDelegateField ? 1 : 0); mv.visitMaxs(max, max); mv.visitEnd(); return EMPTY_VISITOR; }
protected MethodVisitor makeDelegateToClosureCall( final String name, final String desc, final String signature, final String[] exceptions, final int accessFlags) { MethodVisitor mv = super.visitMethod(accessFlags, name, desc, signature, exceptions); // TraceMethodVisitor tmv = new TraceMethodVisitor(mv); // mv = tmv; mv.visitCode(); int stackSize = 0; // method body should be: // this.$delegate$closure$methodName.call(new Object[] { method arguments }) Type[] args = Type.getArgumentTypes(desc); int arrayStore = args.length + 1; BytecodeHelper.pushConstant(mv, args.length); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); // stack size = 1 stackSize = 1; int idx = 1; for (int i = 0; i < args.length; i++) { Type arg = args[i]; mv.visitInsn(DUP); // stack size = 2 BytecodeHelper.pushConstant(mv, i); // array index, stack size = 3 stackSize = 3; // primitive types must be boxed if (isPrimitive(arg)) { mv.visitIntInsn(getLoadInsn(arg), idx); String wrappedType = getWrappedClassDescriptor(arg); mv.visitMethodInsn( INVOKESTATIC, wrappedType, "valueOf", "(" + arg.getDescriptor() + ")L" + wrappedType + ";"); } else { mv.visitVarInsn(ALOAD, idx); // load argument i } idx += registerLen(arg); stackSize = Math.max(4, 3 + registerLen(arg)); mv.visitInsn(AASTORE); // store value into array } mv.visitVarInsn(ASTORE, arrayStore); // store array int arrayIndex = arrayStore; mv.visitVarInsn(ALOAD, 0); // load this mv.visitFieldInsn( GETFIELD, proxyName, CLOSURES_MAP_FIELD, "Ljava/util/Map;"); // load closure map mv.visitLdcInsn(name); // load method name mv.visitMethodInsn( INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); arrayStore++; mv.visitVarInsn(ASTORE, arrayStore); // if null, test if wildcard exists Label notNull = new Label(); mv.visitIntInsn(ALOAD, arrayStore); mv.visitJumpInsn(IFNONNULL, notNull); mv.visitVarInsn(ALOAD, 0); // load this mv.visitFieldInsn( GETFIELD, proxyName, CLOSURES_MAP_FIELD, "Ljava/util/Map;"); // load closure map mv.visitLdcInsn("*"); // load wildcard mv.visitMethodInsn( INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); mv.visitVarInsn(ASTORE, arrayStore); mv.visitLabel(notNull); mv.visitVarInsn(ALOAD, arrayStore); mv.visitMethodInsn( INVOKESTATIC, BytecodeHelper.getClassInternalName(this.getClass()), "ensureClosure", "(Ljava/lang/Object;)Lgroovy/lang/Closure;"); mv.visitVarInsn(ALOAD, arrayIndex); // load argument array stackSize++; mv.visitMethodInsn( INVOKEVIRTUAL, "groovy/lang/Closure", "call", "([Ljava/lang/Object;)Ljava/lang/Object;"); // call closure unwrapResult(mv, desc); mv.visitMaxs(stackSize, arrayStore + 1); mv.visitEnd(); // System.out.println("tmv.getText() = " + tmv.getText()); return EMPTY_VISITOR; }
private void putFieldValueOnStack( MethodVisitor methodVisitor, Type generatedType, String name, Type fieldType) { putThisOnStack(methodVisitor); methodVisitor.visitFieldInsn( GETFIELD, generatedType.getInternalName(), name, fieldType.getDescriptor()); }
private void declareField(ClassVisitor visitor, String name, Class<?> fieldClass) { visitor.visitField( ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, name, Type.getDescriptor(fieldClass), null, null); }
public void accept(ClassVisitor cv) { cv.visitField(access, name, type.getDescriptor(), null /*generics*/, null /*value*/); }
private void putStaticFieldValueOnStack( MethodVisitor methodVisitor, Type generatedType, String name, Type fieldType) { methodVisitor.visitFieldInsn( GETSTATIC, generatedType.getInternalName(), name, fieldType.getDescriptor()); }
public byte[] buildClass(ClassDefinition core) throws IOException, IntrospectionException, SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { Class coreKlazz = core.getDefinedClass(); String coreName = coreKlazz.getName(); String wrapperName = coreName + "Wrapper"; ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); FieldVisitor fv; MethodVisitor mv; cw.visit( V1_5, ACC_PUBLIC + ACC_SUPER, BuildUtils.getInternalType(wrapperName), BuildUtils.getTypeDescriptor(coreName) + "Lorg/drools/factmodel/traits/CoreWrapper<" + BuildUtils.getTypeDescriptor(coreName) + ">;", BuildUtils.getInternalType(coreName), new String[] { Type.getInternalName(CoreWrapper.class), Type.getInternalName(Externalizable.class) }); { fv = cw.visitField(ACC_PRIVATE, "core", BuildUtils.getTypeDescriptor(coreName), null, null); fv.visitEnd(); } { fv = cw.visitField( ACC_PRIVATE, TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class), "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;", null); fv.visitEnd(); } { fv = cw.visitField( ACC_PRIVATE, TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class), "Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;", null); fv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, BuildUtils.getInternalType(coreName), "<init>", "()V"); // mv.visitVarInsn( ALOAD, 0 ); // mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) ); // mv.visitInsn( DUP ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ), // "<init>", "()V" ); // mv.visitFieldInsn( PUTFIELD, // BuildUtils.getInternalType( wrapperName ), // TraitableBean.MAP_FIELD_NAME, // Type.getDescriptor( Map.class ) ); // mv.visitVarInsn( ALOAD, 0 ); // mv.visitTypeInsn( NEW, Type.getInternalName( VetoableTypedMap.class ) ); // mv.visitInsn( DUP ); // mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) ); // mv.visitInsn( DUP ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ), // "<init>", "()V" ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( VetoableTypedMap.class // ), "<init>", "(" + Type.getDescriptor( Map.class ) + ")V" ); // mv.visitFieldInsn( PUTFIELD, // BuildUtils.getInternalType( wrapperName ), // TraitableBean.TRAITSET_FIELD_NAME, // Type.getDescriptor( Map.class ) ); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } if (coreKlazz == null || needsMethod(coreKlazz, "getCore")) { { mv = cw.visitMethod( ACC_PUBLIC, "getCore", "()" + Type.getDescriptor(Object.class), "()" + BuildUtils.getTypeDescriptor(coreName), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getDynamicProperties")) { { mv = cw.visitMethod( ACC_PUBLIC, "getDynamicProperties", "()" + Type.getDescriptor(Map.class), "()Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); mv = cw.visitMethod( ACC_PUBLIC, "setDynamicProperties", "(" + Type.getDescriptor(Map.class) + ")V", "(Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;)V", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTraitMap")) { { mv = cw.visitMethod( ACC_PUBLIC, "getTraitMap", "()" + Type.getDescriptor(Map.class), "()Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); Label l0 = new Label(); mv.visitJumpInsn(IFNONNULL, l0); mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class)); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, Type.getInternalName(HashMap.class)); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(HashMap.class), "<init>", "()V"); mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName(VetoableTypedMap.class), "<init>", "(" + Type.getDescriptor(Map.class) + ")V"); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "setTraitMap", Map.class)) { { mv = cw.visitMethod(ACC_PUBLIC, "setTraitMap", "(Ljava/util/Map;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class)); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName(VetoableTypedMap.class), "<init>", "(" + Type.getDescriptor(Map.class) + ")V"); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "addTrait", String.class, Thing.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "addTrait", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "putSafe", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")" + Type.getDescriptor(Thing.class)); mv.visitInsn(POP); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "getTrait", "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "get", "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "hasTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "hasTrait", "(" + Type.getDescriptor(String.class) + ")Z", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "containsKey", "(" + Type.getDescriptor(Object.class) + ")Z"); mv.visitInsn(IRETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "removeTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "removeTrait", "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "remove", "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTraits")) { { mv = cw.visitMethod( ACC_PUBLIC, "getTraits", "()" + Type.getDescriptor(Collection.class), "()Ljava/util/Collection<Ljava/lang/String;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "keySet", "()" + Type.getDescriptor(Set.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } { mv = cw.visitMethod( ACC_PUBLIC, "writeExternal", "(" + Type.getDescriptor(ObjectOutput.class) + ")V", null, new String[] {Type.getInternalName(IOException.class)}); mv.visitCode(); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getCore", "()" + Type.getDescriptor(Object.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "readExternal", "(" + Type.getDescriptor(ObjectInput.class) + ")V", null, new String[] { Type.getInternalName(IOException.class), Type.getInternalName(ClassNotFoundException.class) }); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "init", "(" + BuildUtils.getTypeDescriptor(coreName) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } Method[] ms = coreKlazz.getMethods(); for (Method method : ms) { if (Modifier.isFinal(method.getModifiers())) { continue; } String signature = TraitFactory.buildSignature(method); { mv = cw.visitMethod(ACC_PUBLIC, method.getName(), signature, null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); int j = 1; for (Class arg : method.getParameterTypes()) { mv.visitVarInsn(BuildUtils.varType(arg.getName()), j++); } mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(coreName), method.getName(), signature); mv.visitInsn(BuildUtils.returnType(method.getReturnType().getName())); int stack = TraitFactory.getStackSize(method); mv.visitMaxs(0, 0); mv.visitEnd(); } } { mv = cw.visitMethod( ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "init", "(" + Type.getDescriptor(Object.class) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName)); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "init", "(" + BuildUtils.getTypeDescriptor(coreName) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "denyTrait", "(" + Type.getDescriptor(Class.class) + ")V", null, new String[] {Type.getInternalName(LogicalTypeInconsistencyException.class)}); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "addToVetoable", "(" + Type.getDescriptor(Class.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "allowTrait", "(" + Type.getDescriptor(Class.class) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "removeFromVetoable", "(" + Type.getDescriptor(Class.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); }
private static boolean isStringType(Type type) { return type.getSort() == Type.OBJECT && type.getDescriptor().equals(JAVA_LANG_STRING); }