Search in sources :

Example 1 with EnhancementException

use of org.hibernate.bytecode.enhance.spi.EnhancementException in project hibernate-orm by hibernate.

the class FieldWriter method addWithModifiers.

private static void addWithModifiers(CtClass target, CtClass type, String name, int modifiers, Class<?>... annotations) {
    try {
        final CtField f = new CtField(type, name, target);
        f.setModifiers(f.getModifiers() | modifiers);
        addAnnotations(f.getFieldInfo(), annotations);
        target.addField(f);
    } catch (CannotCompileException cce) {
        final String msg = String.format("Could not enhance class [%s] to add field [%s]", target.getName(), name);
        throw new EnhancementException(msg, cce);
    }
}
Also used : CtField(javassist.CtField) EnhancementException(org.hibernate.bytecode.enhance.spi.EnhancementException) CannotCompileException(javassist.CannotCompileException)

Example 2 with EnhancementException

use of org.hibernate.bytecode.enhance.spi.EnhancementException in project hibernate-orm by hibernate.

the class MethodWriter method addSetter.

public static CtMethod addSetter(CtClass target, String field, String name) {
    CtField actualField = null;
    try {
        actualField = target.getField(field);
        log.debugf("Writing setter method [%s] into [%s] for field [%s]", name, target.getName(), field);
        CtMethod method = CtNewMethod.setter(name, actualField);
        target.addMethod(method);
        return method;
    } catch (CannotCompileException cce) {
        try {
            // Fall back to create a getter from delegation.
            CtMethod method = CtNewMethod.delegator(CtNewMethod.setter(name, actualField), target);
            target.addMethod(method);
            return method;
        } catch (CannotCompileException ignored) {
            String msg = String.format("Could not enhance class [%s] to add method [%s] for field [%s]", target.getName(), name, field);
            throw new EnhancementException(msg, cce);
        }
    } catch (NotFoundException nfe) {
        String msg = String.format("Could not enhance class [%s] to add method [%s] for field [%s]", target.getName(), name, field);
        throw new EnhancementException(msg, nfe);
    }
}
Also used : CtField(javassist.CtField) EnhancementException(org.hibernate.bytecode.enhance.spi.EnhancementException) NotFoundException(javassist.NotFoundException) CannotCompileException(javassist.CannotCompileException) CtMethod(javassist.CtMethod)

Example 3 with EnhancementException

use of org.hibernate.bytecode.enhance.spi.EnhancementException 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 4 with EnhancementException

use of org.hibernate.bytecode.enhance.spi.EnhancementException 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)

Example 5 with EnhancementException

use of org.hibernate.bytecode.enhance.spi.EnhancementException in project hibernate-orm by hibernate.

the class EnhancerImpl method loadCtClassFromClass.

protected CtClass loadCtClassFromClass(Class<?> aClass) {
    String resourceName = aClass.getName().replace('.', '/') + ".class";
    InputStream resourceAsStream = aClass.getClassLoader().getResourceAsStream(resourceName);
    if (resourceAsStream == null) {
        throw new UncheckedIOException(new FileNotFoundException("Not found: " + resourceName));
    }
    try {
        return classPool.makeClass(resourceAsStream);
    } catch (IOException e) {
        throw new EnhancementException("Could not prepare Javassist ClassPool", e);
    } finally {
        try {
            resourceAsStream.close();
        } catch (IOException ioe) {
            log.debugf("An error occurs closing InputStream for class [%s]", aClass.getName());
        }
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) FileNotFoundException(java.io.FileNotFoundException) EnhancementException(org.hibernate.bytecode.enhance.spi.EnhancementException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException)

Aggregations

EnhancementException (org.hibernate.bytecode.enhance.spi.EnhancementException)8 CannotCompileException (javassist.CannotCompileException)5 NotFoundException (javassist.NotFoundException)5 CtMethod (javassist.CtMethod)4 CtField (javassist.CtField)3 ClassPool (javassist.ClassPool)2 BadBytecode (javassist.bytecode.BadBytecode)2 CodeIterator (javassist.bytecode.CodeIterator)2 ConstPool (javassist.bytecode.ConstPool)2 MethodInfo (javassist.bytecode.MethodInfo)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 UncheckedIOException (java.io.UncheckedIOException)1 CtClass (javassist.CtClass)1