Search in sources :

Example 26 with CtMethod

use of javassist.CtMethod in project hibernate-orm by hibernate.

the class PersistentAttributesEnhancer method handleBiDirectionalAssociation.

private void handleBiDirectionalAssociation(CtClass managedCtClass, CtField persistentField, CtMethod fieldWriter) throws NotFoundException, CannotCompileException {
    if (!PersistentAttributesHelper.isPossibleBiDirectionalAssociation(persistentField)) {
        return;
    }
    final CtClass targetEntity = PersistentAttributesHelper.getTargetEntityClass(managedCtClass, persistentField);
    if (targetEntity == null) {
        log.infof("Could not find type of bi-directional association for field [%s#%s]", managedCtClass.getName(), persistentField.getName());
        return;
    }
    final String mappedBy = PersistentAttributesHelper.getMappedBy(persistentField, targetEntity, enhancementContext);
    if (mappedBy == null || mappedBy.isEmpty()) {
        log.infof("Could not find bi-directional association for field [%s#%s]", managedCtClass.getName(), persistentField.getName());
        return;
    }
    // create a temporary getter and setter on the target entity to be able to compile our code
    final String mappedByGetterName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + mappedBy;
    final String mappedBySetterName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + mappedBy;
    CtMethod getter;
    CtMethod setter;
    boolean tmpTargetMethods = false;
    try {
        getter = targetEntity.getDeclaredMethod(mappedByGetterName);
        setter = targetEntity.getDeclaredMethod(mappedByGetterName);
    } catch (NotFoundException nfe) {
        getter = MethodWriter.addGetter(targetEntity, mappedBy, mappedByGetterName);
        setter = MethodWriter.addSetter(targetEntity, mappedBy, mappedBySetterName);
        tmpTargetMethods = true;
    }
    // code fragments to check loaded state. We don't want to trigger lazy loading in association management code
    String currentAssociationLoaded = String.format("%s.isPropertyInitialized(this.%s, \"%s\")", Hibernate.class.getName(), persistentField.getName(), mappedBy);
    String targetElementLoaded = String.format("%s.isPropertyInitialized(target, \"%s\")", Hibernate.class.getName(), mappedBy);
    String newAssociationLoaded = String.format("%s.isPropertyInitialized($1, \"%s\")", Hibernate.class.getName(), mappedBy);
    if (PersistentAttributesHelper.hasAnnotation(persistentField, OneToOne.class)) {
        // only unset when $1 != null to avoid recursion
        fieldWriter.insertBefore(String.format("  if (this.%1$s != null && %2$s && $1 != null) { this.%1$s.%3$s(null); }%n", persistentField.getName(), currentAssociationLoaded, mappedBySetterName));
        fieldWriter.insertAfter(String.format("  if ($1 != null && %s && $1.%s() != this) { $1.%s(this); }%n", newAssociationLoaded, mappedByGetterName, mappedBySetterName));
    }
    if (PersistentAttributesHelper.hasAnnotation(persistentField, OneToMany.class)) {
        boolean isMap = PersistentAttributesHelper.isAssignable(persistentField.getType(), Map.class.getName());
        String toArrayMethod = isMap ? "values().toArray()" : "toArray()";
        // only remove elements not in the new collection or else we would loose those elements
        // don't use iterator to avoid ConcurrentModException
        fieldWriter.insertBefore(String.format("  if (this.%3$s != null && %1$s) {%n" + "    Object[] array = this.%3$s.%2$s;%n" + "    for (int i = 0; i < array.length; i++) {%n" + "      %4$s target = (%4$s) array[i];%n" + "      if ($1 == null || !$1.contains(target)) { target.%5$s(null); }%n" + "    }%n" + "  }%n", currentAssociationLoaded, toArrayMethod, persistentField.getName(), targetEntity.getName(), mappedBySetterName));
        fieldWriter.insertAfter(String.format("  if ($1 != null && %1$s) {%n" + "    Object[] array = $1.%2$s;%n" + "    for (int i = 0; i < array.length; i++) {%n" + "      %4$s target = (%4$s) array[i];%n" + "      if (%3$s && target.%5$s() != this) { target.%6$s(this); }%n" + "    }%n" + "  }%n", newAssociationLoaded, toArrayMethod, targetElementLoaded, targetEntity.getName(), mappedByGetterName, mappedBySetterName));
    }
    if (PersistentAttributesHelper.hasAnnotation(persistentField, ManyToOne.class)) {
        fieldWriter.insertBefore(String.format("  if (this.%2$s != null && %1$s && this.%2$s.%3$s() != null) { this.%2$s.%3$s().remove(this); }%n", currentAssociationLoaded, persistentField.getName(), mappedByGetterName));
        // check .contains(this) to avoid double inserts (but preventing duplicates)
        fieldWriter.insertAfter(String.format("  if ($1 != null && %s) {%n" + "    java.util.Collection c = $1.%s();%n" + "    if (c != null && !c.contains(this)) { c.add(this); }%n" + "  }%n", newAssociationLoaded, mappedByGetterName));
    }
    if (PersistentAttributesHelper.hasAnnotation(persistentField, ManyToMany.class)) {
        if (PersistentAttributesHelper.isAssignable(persistentField.getType(), Map.class.getName()) || PersistentAttributesHelper.isAssignable(targetEntity.getField(mappedBy).getType(), Map.class.getName())) {
            log.infof("Bi-directional association for field [%s#%s] not managed: @ManyToMany in java.util.Map attribute not supported ", managedCtClass.getName(), persistentField.getName());
            return;
        }
        fieldWriter.insertBefore(String.format("  if (this.%2$s != null && %1$s) {%n" + "    Object[] array = this.%2$s.toArray();%n" + "    for (int i = 0; i < array.length; i++) {%n" + "      %3$s target = (%3$s) array[i];%n" + "      if ($1 == null || !$1.contains(target)) { target.%4$s().remove(this); }%n" + "    }%n" + "  }%n", currentAssociationLoaded, persistentField.getName(), targetEntity.getName(), mappedByGetterName));
        fieldWriter.insertAfter(String.format("  if ($1 != null && %s) {%n" + "    Object[] array = $1.toArray();%n" + "    for (int i = 0; i < array.length; i++) {%n" + "      %s target = (%s) array[i];%n" + "	   if (%s) {%n" + "        java.util.Collection c = target.%s();%n" + "        if (c != this && c != null) { c.add(this); }%n" + "      }%n" + "    }%n" + "  }%n", newAssociationLoaded, targetEntity.getName(), targetEntity.getName(), targetElementLoaded, mappedByGetterName));
    }
    if (tmpTargetMethods) {
        targetEntity.removeMethod(getter);
        targetEntity.removeMethod(setter);
    }
}
Also used : CtClass(javassist.CtClass) Hibernate(org.hibernate.Hibernate) NotFoundException(javassist.NotFoundException) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) CtMethod(javassist.CtMethod)

Example 27 with CtMethod

use of javassist.CtMethod in project hibernate-orm by hibernate.

the class PersistentAttributesHelper method getterOrNull.

private static CtMethod getterOrNull(CtClass containerClass, String propertyName) {
    for (CtMethod method : containerClass.getDeclaredMethods()) {
        try {
            // if the method has parameters, skip it
            if (method.isEmpty() || method.getParameterTypes().length != 0) {
                continue;
            }
        } catch (NotFoundException e) {
            continue;
        }
        final String methodName = method.getName();
        // try "get"
        if (methodName.startsWith("get")) {
            String testStdMethod = Introspector.decapitalize(methodName.substring(3));
            String testOldMethod = methodName.substring(3);
            if (testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName)) {
                return method;
            }
        }
        // if not "get", then try "is"
        if (methodName.startsWith("is")) {
            String testStdMethod = Introspector.decapitalize(methodName.substring(2));
            String testOldMethod = methodName.substring(2);
            if (testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName)) {
                return method;
            }
        }
    }
    return null;
}
Also used : NotFoundException(javassist.NotFoundException) CtMethod(javassist.CtMethod)

Example 28 with CtMethod

use of javassist.CtMethod in project yyl_example by Relucent.

the class CreateSimpleBeanTest method create.

@SuppressWarnings("unchecked")
public static Class<? extends SimpleBean> create(String className, String... fields) throws CannotCompileException, NotFoundException {
    ClassPool pool = ClassPool.getDefault();
    CtClass cc = pool.makeClass(className);
    cc.setInterfaces(new CtClass[] { pool.get(SimpleBean.class.getName()) });
    CtClass stringctClass = pool.get("java.lang.String");
    {
        for (String field : fields) {
            cc.addField(new CtField(stringctClass, field, cc));
        }
    }
    {
        CtMethod setCtMethod = new CtMethod(CtClass.voidType, "set", new CtClass[] { stringctClass, stringctClass }, cc);
        setCtMethod.setModifiers(Modifier.PUBLIC);
        StringBuilder vSetBody = new StringBuilder();
        vSetBody.append("if(null == $1){ throw new NullPointerException(\" key can not be NULL \"); }");
        for (String field : fields) {
            vSetBody.append("else if(\"").append(field).append("\".equals($1)){ $0.").append(field).append("=$2; }");
        }
        vSetBody.append("else { throw new IllegalArgumentException(\"Object does not exist in the \" + $1 + \" field\"); }");
        setCtMethod.setBody(vSetBody.toString());
        cc.addMethod(setCtMethod);
    }
    {
        CtMethod getCtMethod = new CtMethod(stringctClass, "get", new CtClass[] { stringctClass }, cc);
        getCtMethod.setModifiers(Modifier.PUBLIC);
        StringBuilder vGetBody = new StringBuilder();
        vGetBody.append("if(null == $1){ throw new NullPointerException(\" key can not be NULL \"); }");
        for (String field : fields) {
            vGetBody.append("else if(\"").append(field).append("\".equals($1)){ return $0.").append(field).append("; }");
        }
        vGetBody.append("else { throw new IllegalArgumentException(\"Object does not exist in the \" + $1 + \" field\"); }");
        getCtMethod.setBody(vGetBody.toString());
        cc.addMethod(getCtMethod);
    }
    {
        CtConstructor cons = new CtConstructor(new CtClass[] {}, cc);
        cons.setBody("{}");
        cc.addConstructor(cons);
    }
    cc.detach();
    return cc.toClass();
}
Also used : CtClass(javassist.CtClass) CtField(javassist.CtField) ClassPool(javassist.ClassPool) CtMethod(javassist.CtMethod) CtConstructor(javassist.CtConstructor)

Example 29 with CtMethod

use of javassist.CtMethod in project java-chassis by ServiceComb.

the class JavassistUtils method addEnumValuesMethod.

private static void addEnumValuesMethod(CtClass ctClass, List<String> values) throws CannotCompileException {
    StringBuilder sb = new StringBuilder();
    sb.append("public static Enum[] values(){return new Enum[]{");
    for (int idx = 0; idx < values.size(); idx++) {
        String value = values.get(idx);
        String line = String.format("new %s(\"%s\", %d),", ctClass.getName(), value, idx);
        sb.append(line);
    }
    sb.setLength(sb.length() - 1);
    sb.append("};}");
    CtMethod valuesMethod = CtMethod.make(sb.toString(), ctClass);
    ctClass.addMethod(valuesMethod);
}
Also used : CtMethod(javassist.CtMethod)

Example 30 with CtMethod

use of javassist.CtMethod in project java-chassis by ServiceComb.

the class JavassistUtils method createClass.

public static Class<?> createClass(ClassLoader classLoader, ClassConfig config) {
    if (classLoader == null) {
        classLoader = Thread.currentThread().getContextClassLoader();
    }
    appendThreadClassPath();
    CtClass ctClass = null;
    if (config.isIntf()) {
        ctClass = POOL.makeInterface(config.getClassName());
    } else {
        ctClass = POOL.makeClass(config.getClassName());
    }
    try {
        for (String intfName : config.getIntfList()) {
            ctClass.addInterface(POOL.get(intfName));
        }
        for (FieldConfig fieldConfig : config.getFieldList()) {
            CtField field = createCtField(POOL, ctClass, fieldConfig);
            ctClass.addField(field);
        }
        for (MethodConfig methodConfig : config.getMethodList()) {
            CtMethod ctMethod = CtMethod.make(methodConfig.getSource(), ctClass);
            if (methodConfig.getGenericSignature() != null) {
                ctMethod.setGenericSignature(methodConfig.getGenericSignature());
            }
            ctClass.addMethod(ctMethod);
        }
        return ctClass.toClass(classLoader, null);
    } catch (Throwable e) {
        throw new Error(e);
    }
}
Also used : CtClass(javassist.CtClass) CtField(javassist.CtField) CtMethod(javassist.CtMethod)

Aggregations

CtMethod (javassist.CtMethod)70 CtClass (javassist.CtClass)42 CannotCompileException (javassist.CannotCompileException)20 NotFoundException (javassist.NotFoundException)20 ClassPool (javassist.ClassPool)16 CtField (javassist.CtField)14 Test (org.junit.Test)12 IOException (java.io.IOException)10 InitMethod (com.googlecode.gwt.test.patchers.InitMethod)6 Method (java.lang.reflect.Method)5 CtConstructor (javassist.CtConstructor)5 EnhancementException (org.hibernate.bytecode.enhance.spi.EnhancementException)4 GwtTestPatchException (com.googlecode.gwt.test.exceptions.GwtTestPatchException)3 PinpointException (com.navercorp.pinpoint.exception.PinpointException)3 File (java.io.File)3 FileNotFoundException (java.io.FileNotFoundException)3 ArrayList (java.util.ArrayList)3 PatchMethod (com.googlecode.gwt.test.patchers.PatchMethod)2 FileFilter (java.io.FileFilter)2 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)2