public void testJIRA256() throws Exception {
    // CtClass ec = sloader.get("test5.Entity");

    CtClass cc = sloader.makeClass("test5.JIRA256");
    ClassFile ccFile = cc.getClassFile();
    ConstPool constpool = ccFile.getConstPool();

    AnnotationsAttribute attr =
        new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
    javassist.bytecode.annotation.Annotation entityAnno =
        new javassist.bytecode.annotation.Annotation("test5.Entity", constpool);
    // = new javassist.bytecode.annotation.Annotation(constpool, ec);

    entityAnno.addMemberValue(
        "value", new javassist.bytecode.annotation.ArrayMemberValue(constpool));
    attr.addAnnotation(entityAnno);
    ccFile.addAttribute(attr);

    cc.writeFile();
    Object o = make(cc.getName());
    assertTrue(o.getClass().getName().equals("test5.JIRA256"));

    java.lang.annotation.Annotation[] annotations = o.getClass().getDeclaredAnnotations();
    assertEquals(1, annotations.length);
  }
Beispiel #2
0
  private void addOutputArg(List<String> args, Object object) {
    if (!(object instanceof String))
      throw new IllegalArgumentException("Only a single output file can be specified");

    String value = (String) object;
    args.add("-o");
    if (value.endsWith(".vcf")) {
      args.add(value);
      try {
        ConstPool constPool = annotatedWalker.getClassFile().getConstPool();
        AnnotationsAttribute att =
            new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
        Annotation ann = new Annotation(Output.class.getName(), constPool);
        att.addAnnotation(ann);

        CtClass writerClass = pool.get(VCFWriter.class.getName());
        CtField field = new CtField(writerClass, "out", annotatedWalker);
        field.setModifiers(Modifier.PUBLIC);
        field.getFieldInfo().addAttribute(att);
        annotatedWalker.addField(field);
      } catch (NotFoundException e) {
        throw new RuntimeException(e);
      } catch (CannotCompileException e) {
        throw new RuntimeException(e);
      }
    } else throw new IllegalArgumentException("Only VCF files are supported as output files");
  }
  private void autoInjectProperty(ModelClass modelClass) {

    // 连接数据库,自动获取所有信息,然后添加属性
    CtClass ctClass = modelClass.originClass;
    String entitySimpleName = ctClass.getSimpleName();
    List<String> skipFields = modelClass.notMappingColumns();

    try {
      DBType dbType = ServiceFramwork.injector.getInstance(DBType.class);
      DBInfo dbInfo = ServiceFramwork.injector.getInstance(DBInfo.class);

      Map<String, String> columns = dbInfo.tableColumns.get(entitySimpleName);
      if (columns == null) return;
      for (String columnName : columns.keySet()) {
        String fieldName = columnName;
        String fieldType = columns.get(columnName);
        if (skipFields.contains(fieldName)) continue;
        if (fieldName.equals("discriminator")) continue;

        // 对定义过的属性略过
        boolean pass = true;
        try {
          ctClass.getField(fieldName);
        } catch (Exception e) {
          pass = false;
        }
        if (pass) continue;

        ConstPool constPool = ctClass.getClassFile().getConstPool();
        AnnotationsAttribute attr =
            new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
        CtField ctField =
            CtField.make(
                " private " + dbType.typeToJava(fieldType).v2() + " " + fieldName + " ;", ctClass);

        Tuple<Class, Map> tuple = dbType.dateType(fieldType, constPool);
        if (tuple != null) {
          createAnnotation(attr, tuple.v1(), tuple.v2());
        }

        if (fieldName.equals("id")) {
          createAnnotation(attr, javax.persistence.Id.class, map());
          createAnnotation(attr, javax.persistence.GeneratedValue.class, map());
        } else {
          createAnnotation(
              attr, Column.class, map("nullable", new BooleanMemberValue(true, constPool)));
        }

        if (attr.getAnnotations().length > 0) {
          ctField.getFieldInfo().addAttribute(attr);
        }

        ctClass.addField(ctField);
      }

    } catch (Exception e) {
      e.printStackTrace();
    }
    ctClass.defrost();
  }
  public void first(Set<String> classNames) throws NotFoundException, ClassNotFoundException {
    // 扫描注册
    ClassPool classPool = ClassPool.getDefault();
    String tempClassName = null;
    Class register = Register.class;
    CtClass clazz;
    Object isRegister;
    Iterator<String> it = classNames.iterator();
    while (it.hasNext()) {
      tempClassName = it.next();
      clazz = classPool.get(tempClassName);
      isRegister = clazz.getAnnotation(register);

      AnnotationsAttribute a =
          (AnnotationsAttribute)
              clazz.getClassFile2().getAttribute(AnnotationsAttribute.visibleTag);
      Annotation[] as = a.getAnnotations();
      for (Annotation an : as) {
        //				System.out.println(String.format("MemberNames:%s ", an.getMemberNames()));
        Set anSet = an.getMemberNames();
        Iterator anit = anSet.iterator();
        while (anit.hasNext()) {
          System.out.println("type:" + anit.next().getClass());
        }
        //			AnnotationsAttribute a = (AnnotationsAttribute)
        // clazz.getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
        //				for()
      }
      System.err.println(a);
      System.err.println(a);
      //			System.err.println(a.getName());

      if (null != isRegister) System.out.println(isRegister);
    }
  }
Beispiel #5
0
  private static void inheritAnnotations(final CtClass theClass, final CtMethod theMethod)
      throws NotFoundException {
    if (hasMethod(theClass, theMethod)) {
      CtMethod aOtherMethod = theClass.getMethod(theMethod.getName(), theMethod.getSignature());
      // method we're probably overriding or implementing in the case of an abstract method.

      AnnotationsAttribute annotationsAttribute =
          (AnnotationsAttribute)
              aOtherMethod.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag);

      if (annotationsAttribute != null) {
        ConstPool cp = theClass.getClassFile().getConstPool();
        AnnotationsAttribute attr = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag);

        for (Object obj : annotationsAttribute.getAnnotations()) {

          Annotation a = (Annotation) obj;

          Annotation theAnnotation = new Annotation(a.getTypeName(), cp);

          if (a.getMemberNames() != null) {
            for (Object aName : a.getMemberNames()) {
              theAnnotation.addMemberValue(aName.toString(), a.getMemberValue(aName.toString()));
            }
          }

          attr.setAnnotation(theAnnotation);
        }
        theMethod.getMethodInfo().addAttribute(attr);
      }
    }
  }
Beispiel #6
0
  private void addVCFArg(List<String> args, Object object) {
    List<String> vcfs = new ArrayList<String>();
    if (object instanceof String) {
      vcfs.addAll(Arrays.asList(((String) object).split(",")));
    } else if (object instanceof List) {
      vcfs.add((String) object);
    }

    int count = 1;
    for (String vcf : vcfs) {
      args.add("--vcf" + count);
      args.add(vcf);
      try {
        ConstPool constPool = annotatedWalker.getClassFile().getConstPool();
        AnnotationsAttribute att =
            new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
        Annotation ann = new Annotation(Input.class.getName(), constPool);

        MemberValue fullName = new StringMemberValue("vcf" + count, constPool);
        ann.addMemberValue("fullName", fullName);
        att.addAnnotation(ann);

        RodBinding<VariantContext> dummy =
            new RodBinding<VariantContext>(VariantContext.class, "vcf", vcf, "VCF", null);
        CtClass rodClass = pool.get(dummy.getClass().getName());

        // If there are multiple vcfs, we number each one - vcf1, vcf2, ...
        // if there is only one, we just call it "vcf"
        CtField field =
            new CtField(rodClass, vcfs.size() > 1 ? "vcf" + count : "vcf", annotatedWalker);
        field.setModifiers(Modifier.PUBLIC);
        field.getFieldInfo().addAttribute(att);

        SignatureAttribute sig =
            new SignatureAttribute(
                constPool,
                "Lorg/broadinstitute/sting/commandline/RodBinding<Lorg/broadinstitute/sting/utils/variantcontext/VariantContext;>;;");
        field.getFieldInfo().addAttribute(sig);

        annotatedWalker.addField(field);

        if (config.containsKey("out")) {
          VCFHeaderInitializer vcfInit = new VCFHeaderInitializer(this);
          this.injections.get("initializers").add(vcfInit);
        }
      } catch (CannotCompileException e) {
        throw new RuntimeException(e);

      } catch (NotFoundException e) {
        throw new RuntimeException(e);
      }
      ++count;
    }
  }
  /**
   * Retrieve the String value of an annotation which is not available at runtime.
   *
   * @param clazz The annotated class
   * @param annotation The annotation which is not visible at runtime
   * @param name The name of the String property of the annotation to retrieve
   * @return The String value of the annotation or null if the annotation or its property is not
   *     present
   */
  public static String getInvisibleAnnotationStringValue(
      Class<?> clazz, Class<? extends Annotation> annotation, String name) {
    CtClass ctClass = GwtClassPool.getCtClass(clazz);
    ctClass.defrost();

    AnnotationsAttribute attr =
        (AnnotationsAttribute)
            ctClass.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
    if (attr == null) {
      return null;
    }
    javassist.bytecode.annotation.Annotation an = attr.getAnnotation(annotation.getName());

    ctClass.freeze();

    return an != null ? ((StringMemberValue) an.getMemberValue(name)).getValue() : null;
  }
  public void testRemoveAnnotatino() throws Exception {
    CtClass cc = sloader.get("test5.RemoveAnnotation");
    AnnotationsAttribute aa =
        (AnnotationsAttribute) cc.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
    assertTrue(aa.removeAnnotation("test5.RemoveAnno1"));
    AttributeInfo ai = cc.getClassFile().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai.getName(), AnnotationsAttribute.invisibleTag);

    CtMethod foo = cc.getDeclaredMethod("foo");
    AnnotationsAttribute aa2 =
        (AnnotationsAttribute) foo.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
    assertTrue(aa2.removeAnnotation("test5.RemoveAnno1"));

    CtMethod bar = cc.getDeclaredMethod("bar");
    AnnotationsAttribute aa3 =
        (AnnotationsAttribute) bar.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
    assertFalse(aa3.removeAnnotation("test5.RemoveAnno1"));
    assertTrue(aa3.removeAnnotation("test5.RemoveAnno2"));
    AttributeInfo ai2 = bar.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai2.getName(), AnnotationsAttribute.invisibleTag);

    CtMethod run = cc.getDeclaredMethod("run");
    AttributeInfo ai3 = run.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertNull(ai3);

    CtField baz = cc.getDeclaredField("baz");
    AttributeInfo ai4 = baz.getFieldInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai4.getName(), AnnotationsAttribute.invisibleTag);

    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(3, invoke(obj, "run"));
  }
 protected void checkAnnotations(String clazz, String member, AnnotationsAttribute aa, int line) {
   if (aa != null) {
     for (Map.Entry<String, Boolean> entry : annotations.entrySet()) {
       String annotation = entry.getKey();
       Annotation ann = aa.getAnnotation(annotation);
       if (ann != null) {
         checkAnnotation(clazz, member, line, entry.getValue(), annotation, ann);
       }
     }
   }
 }
  protected void buildClassLevelAnnotations(
      ClassFile classFile, ClassFile templateClassFile, ConstPool constantPool)
      throws NotFoundException {
    List<?> templateAttributes = templateClassFile.getAttributes();
    Iterator<?> templateItr = templateAttributes.iterator();
    Annotation templateEntityListeners = null;
    while (templateItr.hasNext()) {
      Object object = templateItr.next();
      if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) {
        AnnotationsAttribute attr = (AnnotationsAttribute) object;
        Annotation[] items = attr.getAnnotations();
        for (Annotation annotation : items) {
          String typeName = annotation.getTypeName();
          if (typeName.equals(EntityListeners.class.getName())) {
            templateEntityListeners = annotation;
          }
        }
      }
    }

    if (templateEntityListeners != null) {
      AnnotationsAttribute annotationsAttribute =
          new AnnotationsAttribute(constantPool, AnnotationsAttribute.visibleTag);
      List<?> attributes = classFile.getAttributes();
      Iterator<?> itr = attributes.iterator();
      Annotation existingEntityListeners = null;
      while (itr.hasNext()) {
        Object object = itr.next();
        if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) {
          AnnotationsAttribute attr = (AnnotationsAttribute) object;
          Annotation[] items = attr.getAnnotations();
          for (Annotation annotation : items) {
            String typeName = annotation.getTypeName();
            if (typeName.equals(EntityListeners.class.getName())) {
              logger.debug(
                  "Stripping out previous EntityListeners annotation at the class level - will merge into new EntityListeners");
              existingEntityListeners = annotation;
              continue;
            }
            annotationsAttribute.addAnnotation(annotation);
          }
          itr.remove();
        }
      }

      Annotation entityListeners =
          getEntityListeners(constantPool, existingEntityListeners, templateEntityListeners);
      annotationsAttribute.addAnnotation(entityListeners);

      classFile.addAttribute(annotationsAttribute);
    }
  }
  @Override
  public byte[] transform(
      ClassLoader loader,
      String className,
      Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain,
      byte[] classfileBuffer)
      throws IllegalClassFormatException {
    // Be careful with Apache library usage in this class (e.g. ArrayUtils). Usage will likely cause
    // a ClassCircularityError
    // under JRebel. Favor not including outside libraries and unnecessary classes.
    CtClass clazz = null;
    try {
      boolean mySkipOverlaps = skipOverlaps;
      boolean myRenameMethodOverlaps = renameMethodOverlaps;
      String convertedClassName = className.replace('/', '.');
      ClassPool classPool = null;
      String xformKey = convertedClassName;
      String[] xformVals = null;
      Boolean[] xformSkipOverlaps = null;
      Boolean[] xformRenameMethodOverlaps = null;
      if (!xformTemplates.isEmpty()) {
        if (xformTemplates.containsKey(xformKey)) {
          xformVals = xformTemplates.get(xformKey).split(",");
          classPool = ClassPool.getDefault();
          clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false);
        }
      } else {
        if (annotationTransformedClasses.contains(convertedClassName)) {
          logger.warn(
              convertedClassName
                  + " has already been transformed by a previous instance of DirectCopyTransfomer. "
                  + "Skipping this annotation based transformation. Generally, annotation-based transformation is handled "
                  + "by bean id blAnnotationDirectCopyClassTransformer with template tokens being added to "
                  + "blDirectCopyTransformTokenMap via EarlyStageMergeBeanPostProcessor.");
        }
        boolean isValidPattern = true;
        List<DirectCopyIgnorePattern> matchedPatterns = new ArrayList<DirectCopyIgnorePattern>();
        for (DirectCopyIgnorePattern pattern : ignorePatterns) {
          boolean isPatternMatch = false;
          for (String patternString : pattern.getPatterns()) {
            isPatternMatch = convertedClassName.matches(patternString);
            if (isPatternMatch) {
              break;
            }
          }
          if (isPatternMatch) {
            matchedPatterns.add(pattern);
          }
          isValidPattern = !(isPatternMatch && pattern.getTemplateTokenPatterns() == null);
          if (!isValidPattern) {
            return null;
          }
        }
        if (isValidPattern) {
          classPool = ClassPool.getDefault();
          clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false);
          List<?> attributes = clazz.getClassFile().getAttributes();
          Iterator<?> itr = attributes.iterator();
          List<String> templates = new ArrayList<String>();
          List<Boolean> skips = new ArrayList<Boolean>();
          List<Boolean> renames = new ArrayList<Boolean>();
          check:
          {
            while (itr.hasNext()) {
              Object object = itr.next();
              if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) {
                AnnotationsAttribute attr = (AnnotationsAttribute) object;
                Annotation[] items = attr.getAnnotations();
                for (Annotation annotation : items) {
                  String typeName = annotation.getTypeName();
                  if (typeName.equals(DirectCopyTransform.class.getName())) {
                    ArrayMemberValue arrayMember =
                        (ArrayMemberValue) annotation.getMemberValue("value");
                    for (MemberValue arrayMemberValue : arrayMember.getValue()) {
                      AnnotationMemberValue member = (AnnotationMemberValue) arrayMemberValue;
                      Annotation memberAnnot = member.getValue();
                      ArrayMemberValue annot =
                          (ArrayMemberValue) memberAnnot.getMemberValue("templateTokens");
                      for (MemberValue memberValue : annot.getValue()) {
                        String val = ((StringMemberValue) memberValue).getValue();
                        if (val != null && templateTokens.containsKey(val)) {
                          templateCheck:
                          {
                            for (DirectCopyIgnorePattern matchedPattern : matchedPatterns) {
                              for (String ignoreToken : matchedPattern.getTemplateTokenPatterns()) {
                                if (val.matches(ignoreToken)) {
                                  break templateCheck;
                                }
                              }
                            }
                            templates.add(templateTokens.get(val));
                          }
                        }
                      }
                      BooleanMemberValue skipAnnot =
                          (BooleanMemberValue) memberAnnot.getMemberValue("skipOverlaps");
                      if (skipAnnot != null) {
                        skips.add(skipAnnot.getValue());
                      } else {
                        skips.add(mySkipOverlaps);
                      }
                      BooleanMemberValue renameAnnot =
                          (BooleanMemberValue) memberAnnot.getMemberValue("renameMethodOverlaps");
                      if (renameAnnot != null) {
                        renames.add(renameAnnot.getValue());
                      } else {
                        renames.add(myRenameMethodOverlaps);
                      }
                    }
                    xformVals = templates.toArray(new String[templates.size()]);
                    xformSkipOverlaps = skips.toArray(new Boolean[skips.size()]);
                    xformRenameMethodOverlaps = renames.toArray(new Boolean[renames.size()]);
                    break check;
                  }
                }
              }
            }
          }
        }
      }
      if (xformVals != null && xformVals.length > 0) {
        logger.lifecycle(
            LifeCycleEvent.START,
            String.format(
                "Transform - Copying into [%s] from [%s]",
                xformKey, StringUtils.join(xformVals, ",")));
        // Load the destination class and defrost it so it is eligible for modifications
        clazz.defrost();

        int index = 0;
        for (String xformVal : xformVals) {
          // Load the source class
          String trimmed = xformVal.trim();
          classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader()));
          CtClass template = classPool.get(trimmed);

          // Add in extra interfaces
          CtClass[] interfacesToCopy = template.getInterfaces();
          for (CtClass i : interfacesToCopy) {
            checkInterfaces:
            {
              CtClass[] myInterfaces = clazz.getInterfaces();
              for (CtClass myInterface : myInterfaces) {
                if (myInterface.getName().equals(i.getName())) {
                  if (xformSkipOverlaps[index]) {
                    break checkInterfaces;
                  } else {
                    throw new RuntimeException(
                        "Duplicate interface detected " + myInterface.getName());
                  }
                }
              }
              logger.debug(String.format("Adding interface [%s]", i.getName()));
              clazz.addInterface(i);
            }
          }

          // copy over any EntityListeners
          ClassFile classFile = clazz.getClassFile();
          ClassFile templateFile = template.getClassFile();
          ConstPool constantPool = classFile.getConstPool();
          buildClassLevelAnnotations(classFile, templateFile, constantPool);

          // Copy over all declared fields from the template class
          // Note that we do not copy over fields with the @NonCopiedField annotation
          CtField[] fieldsToCopy = template.getDeclaredFields();
          for (CtField field : fieldsToCopy) {
            if (field.hasAnnotation(NonCopied.class)) {
              logger.debug(String.format("Not adding field [%s]", field.getName()));
            } else {
              try {
                CtField ctField = clazz.getDeclaredField(field.getName());
                String originalSignature = ctField.getSignature();
                String mySignature = field.getSignature();
                if (!originalSignature.equals(mySignature)) {
                  throw new IllegalArgumentException(
                      "Field with name ("
                          + field.getName()
                          + ") and signature "
                          + "("
                          + field.getSignature()
                          + ") is targeted for weaving into ("
                          + clazz.getName()
                          + "). "
                          + "An incompatible field of the same name and signature of ("
                          + ctField.getSignature()
                          + ") "
                          + "already exists. The field in the target class should be updated to a different name, "
                          + "or made to have a matching type.");
                }
                if (xformSkipOverlaps[index]) {
                  logger.debug(String.format("Skipping overlapped field [%s]", field.getName()));
                  continue;
                }
              } catch (NotFoundException e) {
                // do nothing -- field does not exist
              }
              logger.debug(String.format("Adding field [%s]", field.getName()));
              CtField copiedField = new CtField(field, clazz);

              boolean defaultConstructorFound = false;

              String implClass = getImplementationType(field.getType().getName());

              // Look through all of the constructors in the implClass to see
              // if there is one that takes zero parameters
              try {
                CtConstructor[] implConstructors = classPool.get(implClass).getConstructors();
                if (implConstructors != null) {
                  for (CtConstructor cons : implConstructors) {
                    if (cons.getParameterTypes().length == 0) {
                      defaultConstructorFound = true;
                      break;
                    }
                  }
                }
              } catch (NotFoundException e) {
                // Do nothing -- if we don't find this implementation, it's probably because it's
                // an array. In this case, we will not initialize the field.
              }

              if (defaultConstructorFound) {
                clazz.addField(copiedField, "new " + implClass + "()");
              } else {
                clazz.addField(copiedField);
              }
            }
          }

          // Copy over all declared methods from the template class
          CtMethod[] methodsToCopy = template.getDeclaredMethods();
          for (CtMethod method : methodsToCopy) {
            if (method.hasAnnotation(NonCopied.class)) {
              logger.debug(String.format("Not adding method [%s]", method.getName()));
            } else {
              try {
                CtClass[] paramTypes = method.getParameterTypes();
                CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes);

                if (xformSkipOverlaps[index]) {
                  logger.debug(
                      String.format(
                          "Skipping overlapped method [%s]", methodDescription(originalMethod)));
                  continue;
                }

                if (transformedMethods.contains(methodDescription(originalMethod))) {
                  throw new RuntimeException(
                      "Method already replaced " + methodDescription(originalMethod));
                } else {
                  logger.debug(
                      String.format("Marking as replaced [%s]", methodDescription(originalMethod)));
                  transformedMethods.add(methodDescription(originalMethod));
                }

                logger.debug(String.format("Removing method [%s]", method.getName()));
                if (xformRenameMethodOverlaps[index]) {
                  originalMethod.setName(renameMethodPrefix + method.getName());
                } else {
                  clazz.removeMethod(originalMethod);
                }
              } catch (NotFoundException e) {
                // Do nothing -- we don't need to remove a method because it doesn't exist
              }

              logger.debug(String.format("Adding method [%s]", method.getName()));
              CtMethod copiedMethod = new CtMethod(method, clazz, null);
              clazz.addMethod(copiedMethod);
            }
          }
          index++;
        }

        if (xformTemplates.isEmpty()) {
          annotationTransformedClasses.add(convertedClassName);
        }
        logger.lifecycle(
            LifeCycleEvent.END,
            String.format(
                "Transform - Copying into [%s] from [%s]",
                xformKey, StringUtils.join(xformVals, ",")));
        return clazz.toBytecode();
      }
    } catch (ClassCircularityError error) {
      error.printStackTrace();
      throw error;
    } catch (Exception e) {
      throw new RuntimeException("Unable to transform class", e);
    } finally {
      if (clazz != null) {
        clazz.detach();
      }
    }

    return null;
  }
  public byte[] transform(
      ClassLoader loader,
      String className,
      Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain,
      byte[] classfileBuffer)
      throws IllegalClassFormatException {
    if (infos.isEmpty()) {
      return null;
    }
    String convertedClassName = className.replace('/', '.');
    SingleTableInheritanceInfo key = new SingleTableInheritanceInfo();
    key.setClassName(convertedClassName);
    int pos = infos.indexOf(key);
    if (pos >= 0) {
      try {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Converting " + convertedClassName + " to a SingleTable inheritance strategy.");
        }
        SingleTableInheritanceInfo myInfo = infos.get(pos);
        ClassFile classFile =
            new ClassFile(new DataInputStream(new ByteArrayInputStream(classfileBuffer)));
        ConstPool constantPool = classFile.getConstPool();
        AnnotationsAttribute annotationsAttribute =
            new AnnotationsAttribute(constantPool, AnnotationsAttribute.visibleTag);
        List<?> attributes = classFile.getAttributes();
        Iterator<?> itr = attributes.iterator();
        while (itr.hasNext()) {
          Object object = itr.next();
          if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) {
            AnnotationsAttribute attr = (AnnotationsAttribute) object;
            Annotation[] items = attr.getAnnotations();
            for (Annotation annotation : items) {
              String typeName = annotation.getTypeName();
              if (!typeName.equals(Inheritance.class.getName())
                  && ((myInfo.getDiscriminatorName() == null
                          && !typeName.equals(Table.class.getName()))
                      || myInfo.getDiscriminatorName() != null)) {
                annotationsAttribute.addAnnotation(annotation);
              }
            }
            itr.remove();
          }
        }
        Annotation inheritance = new Annotation(Inheritance.class.getName(), constantPool);
        ClassPool pool = ClassPool.getDefault();
        pool.importPackage("javax.persistence");
        pool.importPackage("java.lang");
        EnumMemberValue strategy =
            (EnumMemberValue)
                Annotation.createMemberValue(constantPool, pool.makeClass("InheritanceType"));
        strategy.setType(InheritanceType.class.getName());
        strategy.setValue(InheritanceType.SINGLE_TABLE.name());
        inheritance.addMemberValue("strategy", strategy);
        annotationsAttribute.addAnnotation(inheritance);
        if (myInfo.getDiscriminatorName() != null) {
          Annotation discriminator =
              new Annotation(DiscriminatorColumn.class.getName(), constantPool);
          StringMemberValue name = new StringMemberValue(constantPool);
          name.setValue(myInfo.getDiscriminatorName());
          discriminator.addMemberValue("name", name);
          EnumMemberValue discriminatorType =
              (EnumMemberValue)
                  Annotation.createMemberValue(constantPool, pool.makeClass("DiscriminatorType"));
          discriminatorType.setType(DiscriminatorType.class.getName());
          discriminatorType.setValue(myInfo.getDiscriminatorType().name());
          discriminator.addMemberValue("discriminatorType", discriminatorType);
          IntegerMemberValue length = new IntegerMemberValue(constantPool);
          length.setValue(myInfo.getDiscriminatorLength());
          discriminator.addMemberValue("length", length);

          annotationsAttribute.addAnnotation(discriminator);
        }
        classFile.addAttribute(annotationsAttribute);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream os = new DataOutputStream(bos);
        classFile.write(os);
        os.close();

        return bos.toByteArray();
      } catch (Exception ex) {
        ex.printStackTrace();
        throw new IllegalClassFormatException(
            "Unable to convert "
                + convertedClassName
                + " to a SingleTable inheritance strategy: "
                + ex.getMessage());
      }
    } else {
      return null;
    }
  }
      private URL computeResourceURL(Method method) throws NotFoundException, URISyntaxException {
        List<ResourceFileEntry> filesSimpleNames = new ArrayList<ResourceFileEntry>();
        boolean computeExtensions = false;
        CtMethod m = ctClass.getMethod(method.getName(), getDescriptor(method));
        MethodInfo minfo = m.getMethodInfo2();
        AnnotationsAttribute attr =
            (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.invisibleTag);
        if (attr != null) {
          Annotation an = attr.getAnnotation(Source.class.getName());
          if (an != null) {
            MemberValue[] mvArray = ((ArrayMemberValue) an.getMemberValue("value")).getValue();
            if (mvArray != null) {
              for (MemberValue mv : mvArray) {
                StringMemberValue smv = (StringMemberValue) mv;
                filesSimpleNames.add(new ResourceFileEntry(smv.getValue(), m));
              }
            }
          }
        }

        if (filesSimpleNames.isEmpty()) {
          // no @Source annotation detected
          filesSimpleNames.add(new ResourceFileEntry(method.getName(), m));
          computeExtensions = true;
        }

        List<URL> existingFiles = new ArrayList<URL>();

        for (ResourceFileEntry resourceEntry : filesSimpleNames) {
          String resourceName = resourceEntry.resourceName;
          CtClass declaringClass = resourceEntry.resourceMethod.getDeclaringClass();
          String baseDir = declaringClass.getPackageName().replaceAll("\\.", "/") + "/";
          String fileName =
              (resourceName.startsWith(baseDir)) ? resourceName : baseDir + resourceName;

          if (computeExtensions) {
            String[] extensions = getResourceDefaultExtensions(method);

            for (String extension : extensions) {
              String possibleFile = fileName + extension;
              URL url = GwtPatcher.class.getClassLoader().getResource(possibleFile);
              if (url != null) {
                existingFiles.add(url);
              }
            }
          } else {
            URL url = GwtPatcher.class.getClassLoader().getResource(fileName);
            if (url != null) {
              existingFiles.add(url);
            }
          }
        }

        if (existingFiles.isEmpty()) {
          throw new RuntimeException(
              "No resource file found for method "
                  + ctClass.getSimpleName()
                  + "."
                  + method.getName()
                  + "()");
        } else if (existingFiles.size() > 1) {
          throw new RuntimeException(
              "Too many resource files found for method "
                  + ctClass.getSimpleName()
                  + "."
                  + method.getName()
                  + "()");
        }

        return existingFiles.get(0);
      }