Search in sources :

Example 1 with ConstPool

use of javassist.bytecode.ConstPool in project play-cookbook by spinscale.

the class XmlEnhancer method enhanceThisClass.

@Override
public void enhanceThisClass(ApplicationClass applicationClass) throws Exception {
    CtClass ctClass = makeClass(applicationClass);
    if (!ctClass.subtypeOf(classPool.get("play.db.jpa.JPABase"))) {
        return;
    }
    if (!hasAnnotation(ctClass, "javax.persistence.Entity")) {
        return;
    }
    ConstPool constpool = ctClass.getClassFile().getConstPool();
    AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
    if (!hasAnnotation(ctClass, "javax.xml.bind.annotation.XmlAccessorType")) {
        Annotation annot = new Annotation("javax.xml.bind.annotation.XmlAccessorType", constpool);
        EnumMemberValue enumValue = new EnumMemberValue(constpool);
        enumValue.setType("javax.xml.bind.annotation.XmlAccessType");
        enumValue.setValue("FIELD");
        annot.addMemberValue("value", enumValue);
        attr.addAnnotation(annot);
        ctClass.getClassFile().addAttribute(attr);
    }
    if (!hasAnnotation(ctClass, "javax.xml.bind.annotation.XmlRootElement")) {
        Annotation annot = new Annotation("javax.xml.bind.annotation.XmlRootElement", constpool);
        String entityName = ctClass.getName();
        String entity = entityName.substring(entityName.lastIndexOf('.') + 1).toLowerCase();
        annot.addMemberValue("name", new StringMemberValue(entity, constpool));
        attr.addAnnotation(annot);
        ctClass.getClassFile().addAttribute(attr);
    }
    applicationClass.enhancedByteCode = ctClass.toBytecode();
    ctClass.defrost();
}
Also used : EnumMemberValue(javassist.bytecode.annotation.EnumMemberValue) CtClass(javassist.CtClass) ConstPool(javassist.bytecode.ConstPool) StringMemberValue(javassist.bytecode.annotation.StringMemberValue) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) Annotation(javassist.bytecode.annotation.Annotation)

Example 2 with ConstPool

use of javassist.bytecode.ConstPool in project hibernate-orm by hibernate.

the class BulkAccessorFactory method addGetter.

private void addGetter(ClassFile classfile, final Method[] getters) throws CannotCompileException {
    final ConstPool constPool = classfile.getConstPool();
    final int targetBeanConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
    final String desc = GET_SETTER_DESC;
    final MethodInfo getterMethodInfo = new MethodInfo(constPool, GENERATED_GETTER_NAME, desc);
    final Bytecode code = new Bytecode(constPool, 6, 4);
    /* | this | bean | args | raw bean | */
    if (getters.length >= 0) {
        // aload_1 // load bean
        code.addAload(1);
        // checkcast // cast bean
        code.addCheckcast(this.targetBean.getName());
        // astore_3 // store bean
        code.addAstore(3);
        for (int i = 0; i < getters.length; ++i) {
            if (getters[i] != null) {
                final Method getter = getters[i];
                // aload_2 // args
                code.addAload(2);
                // iconst_i // continue to aastore
                // growing stack is 1
                code.addIconst(i);
                final Class returnType = getter.getReturnType();
                int typeIndex = -1;
                if (returnType.isPrimitive()) {
                    typeIndex = FactoryHelper.typeIndex(returnType);
                    // new
                    code.addNew(FactoryHelper.wrapperTypes[typeIndex]);
                    // dup
                    code.addOpcode(Opcode.DUP);
                }
                // aload_3 // load the raw bean
                code.addAload(3);
                final String getterSignature = RuntimeSupport.makeDescriptor(getter);
                final String getterName = getter.getName();
                if (this.targetBean.isInterface()) {
                    // invokeinterface
                    code.addInvokeinterface(targetBeanConstPoolIndex, getterName, getterSignature, 1);
                } else {
                    // invokevirtual
                    code.addInvokevirtual(targetBeanConstPoolIndex, getterName, getterSignature);
                }
                if (typeIndex >= 0) {
                    // is a primitive type
                    // invokespecial
                    code.addInvokespecial(FactoryHelper.wrapperTypes[typeIndex], MethodInfo.nameInit, FactoryHelper.wrapperDesc[typeIndex]);
                }
                // aastore // args
                code.add(Opcode.AASTORE);
                code.growStack(-3);
            }
        }
    }
    // return
    code.addOpcode(Opcode.RETURN);
    getterMethodInfo.setCodeAttribute(code.toCodeAttribute());
    getterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
    classfile.addMethod(getterMethodInfo);
}
Also used : ConstPool(javassist.bytecode.ConstPool) MethodInfo(javassist.bytecode.MethodInfo) Bytecode(javassist.bytecode.Bytecode) Method(java.lang.reflect.Method)

Example 3 with ConstPool

use of javassist.bytecode.ConstPool in project hibernate-orm by hibernate.

the class BulkAccessorFactory method addSetter.

private void addSetter(ClassFile classfile, final Method[] setters) throws CannotCompileException {
    final ConstPool constPool = classfile.getConstPool();
    final int targetTypeConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
    final String desc = GET_SETTER_DESC;
    final MethodInfo setterMethodInfo = new MethodInfo(constPool, GENERATED_SETTER_NAME, desc);
    final Bytecode code = new Bytecode(constPool, 4, 6);
    StackMapTable stackmap = null;
    /* | this | bean | args | i | raw bean | exception | */
    if (setters.length > 0) {
        // required to exception table
        int start;
        int end;
        // iconst_0 // i
        code.addIconst(0);
        // istore_3 // store i
        code.addIstore(3);
        // aload_1 // load the bean
        code.addAload(1);
        // checkcast // cast the bean into a raw bean
        code.addCheckcast(this.targetBean.getName());
        // astore 4 // store the raw bean
        code.addAstore(4);
        /* current stack len = 0 */
        // start region to handling exception (BulkAccessorException)
        start = code.currentPc();
        int lastIndex = 0;
        for (int i = 0; i < setters.length; ++i) {
            if (setters[i] != null) {
                final int diff = i - lastIndex;
                if (diff > 0) {
                    // iinc 3, 1
                    code.addOpcode(Opcode.IINC);
                    code.add(3);
                    code.add(diff);
                    lastIndex = i;
                }
            }
            /* current stack len = 0 */
            // aload 4 // load the raw bean
            code.addAload(4);
            // aload_2 // load the args
            code.addAload(2);
            // iconst_i
            code.addIconst(i);
            // aaload
            code.addOpcode(Opcode.AALOAD);
            // checkcast
            final Class[] setterParamTypes = setters[i].getParameterTypes();
            final Class setterParamType = setterParamTypes[0];
            if (setterParamType.isPrimitive()) {
                // checkcast (case of primitive type)
                // invokevirtual (case of primitive type)
                this.addUnwrapper(code, setterParamType);
            } else {
                // checkcast (case of reference type)
                code.addCheckcast(setterParamType.getName());
            }
            /* current stack len = 2 */
            final String rawSetterMethodDesc = RuntimeSupport.makeDescriptor(setters[i]);
            if (!this.targetBean.isInterface()) {
                // invokevirtual
                code.addInvokevirtual(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc);
            } else {
                // invokeinterface
                final Class[] params = setters[i].getParameterTypes();
                int size;
                if (params[0].equals(Double.TYPE) || params[0].equals(Long.TYPE)) {
                    size = 3;
                } else {
                    size = 2;
                }
                code.addInvokeinterface(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc, size);
            }
        }
        // end region to handling exception (BulkAccessorException)
        end = code.currentPc();
        // return
        code.addOpcode(Opcode.RETURN);
        /* current stack len = 0 */
        // register in exception table
        final int throwableTypeIndex = constPool.addClassInfo(THROWABLE_CLASS_NAME);
        final int handlerPc = code.currentPc();
        code.addExceptionHandler(start, end, handlerPc, throwableTypeIndex);
        // astore 5 // store exception
        code.addAstore(5);
        // new // BulkAccessorException
        code.addNew(BULKEXCEPTION_CLASS_NAME);
        // dup
        code.addOpcode(Opcode.DUP);
        // aload 5 // load exception
        code.addAload(5);
        // iload_3 // i
        code.addIload(3);
        // invokespecial // BulkAccessorException.<init>
        final String consDesc = "(Ljava/lang/Throwable;I)V";
        code.addInvokespecial(BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, consDesc);
        // athrow
        code.addOpcode(Opcode.ATHROW);
        final StackMapTable.Writer writer = new StackMapTable.Writer(32);
        final int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
        final int[] localData = { constPool.getThisClassInfo(), constPool.addClassInfo("java/lang/Object"), constPool.addClassInfo("[Ljava/lang/Object;"), 0 };
        final int[] stackTags = { StackMapTable.OBJECT };
        final int[] stackData = { throwableTypeIndex };
        writer.fullFrame(handlerPc, localTags, localData, stackTags, stackData);
        stackmap = writer.toStackMapTable(constPool);
    } else {
        // return
        code.addOpcode(Opcode.RETURN);
    }
    final CodeAttribute ca = code.toCodeAttribute();
    if (stackmap != null) {
        ca.setAttribute(stackmap);
    }
    setterMethodInfo.setCodeAttribute(ca);
    setterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
    classfile.addMethod(setterMethodInfo);
}
Also used : ConstPool(javassist.bytecode.ConstPool) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) Bytecode(javassist.bytecode.Bytecode) StackMapTable(javassist.bytecode.StackMapTable)

Example 4 with ConstPool

use of javassist.bytecode.ConstPool in project hibernate-orm by hibernate.

the class PersistentAttributesEnhancer method enhanceAttributesAccess.

protected void enhanceAttributesAccess(CtClass managedCtClass, IdentityHashMap<String, PersistentAttributeAccessMethods> attributeDescriptorMap) {
    final ConstPool constPool = managedCtClass.getClassFile().getConstPool();
    final ClassPool classPool = managedCtClass.getClassPool();
    for (Object oMethod : managedCtClass.getClassFile().getMethods()) {
        final MethodInfo methodInfo = (MethodInfo) oMethod;
        final String methodName = methodInfo.getName();
        // skip methods added by enhancement and abstract methods (methods without any code)
        if (methodName.startsWith("$$_hibernate_") || methodInfo.getCodeAttribute() == null) {
            continue;
        }
        try {
            final CodeIterator itr = methodInfo.getCodeAttribute().iterator();
            while (itr.hasNext()) {
                final int index = itr.next();
                final int op = itr.byteAt(index);
                if (op != Opcode.PUTFIELD && op != Opcode.GETFIELD) {
                    continue;
                }
                // only transform access to fields of the entity being enhanced
                if (!managedCtClass.getName().equals(constPool.getFieldrefClassName(itr.u16bitAt(index + 1)))) {
                    continue;
                }
                final String fieldName = constPool.getFieldrefName(itr.u16bitAt(index + 1));
                final PersistentAttributeAccessMethods attributeMethods = attributeDescriptorMap.get(fieldName);
                // its not a field we have enhanced for interception, so skip it
                if (attributeMethods == null) {
                    continue;
                }
                //System.out.printf( "Transforming access to field [%s] from method [%s]%n", fieldName, methodName );
                log.debugf("Transforming access to field [%s] from method [%s]", fieldName, methodName);
                if (op == Opcode.GETFIELD) {
                    final int methodIndex = MethodWriter.addMethod(constPool, attributeMethods.getReader());
                    itr.writeByte(Opcode.INVOKEVIRTUAL, index);
                    itr.write16bit(methodIndex, index + 1);
                } else {
                    final int methodIndex = MethodWriter.addMethod(constPool, attributeMethods.getWriter());
                    itr.writeByte(Opcode.INVOKEVIRTUAL, index);
                    itr.write16bit(methodIndex, index + 1);
                }
            }
            methodInfo.getCodeAttribute().setAttribute(MapMaker.make(classPool, methodInfo));
        } catch (BadBytecode bb) {
            final String msg = String.format("Unable to perform field access transformation in method [%s]", methodName);
            throw new EnhancementException(msg, bb);
        }
    }
}
Also used : ConstPool(javassist.bytecode.ConstPool) CodeIterator(javassist.bytecode.CodeIterator) ClassPool(javassist.ClassPool) EnhancementException(org.hibernate.bytecode.enhance.spi.EnhancementException) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode)

Example 5 with ConstPool

use of javassist.bytecode.ConstPool in project hibernate-orm by hibernate.

the class PersistentAttributesEnhancer method extendedEnhancement.

// --- //
/**
	 * Replace access to fields of entities (for example, entity.field) with a call to the enhanced getter / setter
	 * (in this example, entity.$$_hibernate_read_field()). It's assumed that the target entity is enhanced as well.
	 *
	 * @param aCtClass Class to enhance (not an entity class).
	 */
public void extendedEnhancement(CtClass aCtClass) {
    final ConstPool constPool = aCtClass.getClassFile().getConstPool();
    final ClassPool classPool = aCtClass.getClassPool();
    for (Object oMethod : aCtClass.getClassFile().getMethods()) {
        final MethodInfo methodInfo = (MethodInfo) oMethod;
        final String methodName = methodInfo.getName();
        // skip methods added by enhancement and abstract methods (methods without any code)
        if (methodName.startsWith("$$_hibernate_") || methodInfo.getCodeAttribute() == null) {
            continue;
        }
        try {
            final CodeIterator itr = methodInfo.getCodeAttribute().iterator();
            while (itr.hasNext()) {
                int index = itr.next();
                int op = itr.byteAt(index);
                if (op != Opcode.PUTFIELD && op != Opcode.GETFIELD) {
                    continue;
                }
                String fieldName = constPool.getFieldrefName(itr.u16bitAt(index + 1));
                String fieldClassName = constPool.getClassInfo(constPool.getFieldrefClass(itr.u16bitAt(index + 1)));
                CtClass targetCtClass = classPool.getCtClass(fieldClassName);
                if (!enhancementContext.isEntityClass(targetCtClass) && !enhancementContext.isCompositeClass(targetCtClass)) {
                    continue;
                }
                if (targetCtClass == aCtClass || !enhancementContext.isPersistentField(targetCtClass.getField(fieldName)) || PersistentAttributesHelper.hasAnnotation(targetCtClass, fieldName, Id.class) || "this$0".equals(fieldName)) {
                    continue;
                }
                log.debugf("Extended enhancement: Transforming access to field [%s.%s] from method [%s#%s]", fieldClassName, fieldName, aCtClass.getName(), methodName);
                if (op == Opcode.GETFIELD) {
                    int fieldReaderMethodIndex = constPool.addMethodrefInfo(constPool.addClassInfo(fieldClassName), EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName, "()" + constPool.getFieldrefType(itr.u16bitAt(index + 1)));
                    itr.writeByte(Opcode.INVOKEVIRTUAL, index);
                    itr.write16bit(fieldReaderMethodIndex, index + 1);
                } else {
                    int fieldWriterMethodIndex = constPool.addMethodrefInfo(constPool.addClassInfo(fieldClassName), EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName, "(" + constPool.getFieldrefType(itr.u16bitAt(index + 1)) + ")V");
                    itr.writeByte(Opcode.INVOKEVIRTUAL, index);
                    itr.write16bit(fieldWriterMethodIndex, index + 1);
                }
            }
            methodInfo.getCodeAttribute().setAttribute(MapMaker.make(classPool, methodInfo));
        } catch (BadBytecode bb) {
            final String msg = String.format("Unable to perform extended enhancement in method [%s]", methodName);
            throw new EnhancementException(msg, bb);
        } catch (NotFoundException nfe) {
            final String msg = String.format("Unable to perform extended enhancement in method [%s]", methodName);
            throw new EnhancementException(msg, nfe);
        }
    }
}
Also used : ConstPool(javassist.bytecode.ConstPool) CtClass(javassist.CtClass) CodeIterator(javassist.bytecode.CodeIterator) ClassPool(javassist.ClassPool) EnhancementException(org.hibernate.bytecode.enhance.spi.EnhancementException) NotFoundException(javassist.NotFoundException) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode)

Aggregations

ConstPool (javassist.bytecode.ConstPool)8 MethodInfo (javassist.bytecode.MethodInfo)6 CtClass (javassist.CtClass)4 Bytecode (javassist.bytecode.Bytecode)4 ClassPool (javassist.ClassPool)3 BadBytecode (javassist.bytecode.BadBytecode)3 CodeIterator (javassist.bytecode.CodeIterator)3 NotFoundException (javassist.NotFoundException)2 CodeAttribute (javassist.bytecode.CodeAttribute)2 EnhancementException (org.hibernate.bytecode.enhance.spi.EnhancementException)2 Method (java.lang.reflect.Method)1 CannotCompileException (javassist.CannotCompileException)1 CtMethod (javassist.CtMethod)1 AnnotationsAttribute (javassist.bytecode.AnnotationsAttribute)1 StackMapTable (javassist.bytecode.StackMapTable)1 Annotation (javassist.bytecode.annotation.Annotation)1 EnumMemberValue (javassist.bytecode.annotation.EnumMemberValue)1 StringMemberValue (javassist.bytecode.annotation.StringMemberValue)1 CompileError (javassist.compiler.CompileError)1 Javac (javassist.compiler.Javac)1