@Override
  public boolean transform(
      ClassLoader loader,
      String className,
      Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain,
      ClassFile file)
      throws IllegalClassFormatException, BadBytecode {

    /**
     * Hack up the proxy factory so it stores the proxy ClassFile. We need this to regenerate
     * proxies.
     */
    if (file.getName().equals("org.jboss.weld.bean.proxy.ProxyFactory")) {
      for (final MethodInfo method : (List<MethodInfo>) file.getMethods()) {
        if (method.getName().equals("createProxyClass")) {
          final MethodInvokationManipulator methodInvokationManipulator =
              new MethodInvokationManipulator();
          methodInvokationManipulator.replaceVirtualMethodInvokationWithStatic(
              ClassLoader.class.getName(),
              WeldProxyClassLoadingDelegate.class.getName(),
              "loadClass",
              "(Ljava/lang/String;)Ljava/lang/Class;",
              "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",
              loader);
          methodInvokationManipulator.replaceVirtualMethodInvokationWithStatic(
              "org.jboss.weld.util.bytecode.ClassFileUtils",
              WeldProxyClassLoadingDelegate.class.getName(),
              "toClass",
              "(Ljavassist/bytecode/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;",
              "(Ljavassist/bytecode/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;",
              loader);
          HashSet<MethodInfo> modifiedMethods = new HashSet<MethodInfo>();
          methodInvokationManipulator.transformClass(file, loader, true, modifiedMethods);
          for (MethodInfo m : modifiedMethods) {
            m.rebuildStackMap(ClassPool.getDefault());
          }
          return true;
        } else if (method.getName().equals("<init>")) {

          Integer beanArgument = null;
          int count = 0;
          for (final String paramType :
              DescriptorUtils.descriptorStringToParameterArray(method.getDescriptor())) {
            if (paramType.equals("javax/enterprise/inject/spi/Bean")) {
              beanArgument = count;
              break;
            } else if (paramType.equals("D") || paramType.equals("J")) {
              count += 2;
            } else {
              count++;
            }
          }
          if (beanArgument == null) {
            log.error(
                "Constructor org.jboss.weld.bean.proxy.ProxyFactory.<init>"
                    + method.getDescriptor()
                    + " does not have a bean parameter, proxies produced by this factory will not be reloadable");
            continue;
          }

          // similar to other tracked instances
          // but we need a strong ref
          Bytecode code = new Bytecode(file.getConstPool());
          code.addAload(0);
          code.addAload(beanArgument);
          code.addInvokestatic(
              WeldClassChangeAware.class.getName(),
              "addProxyFactory",
              "(Lorg/jboss/weld/bean/proxy/ProxyFactory;)V");
          CodeIterator it = method.getCodeAttribute().iterator();
          it.skipConstructor();
          it.insert(code.get());
        }
      }
    }
    return false;
  }
Example #2
0
 /**
  * Rebuilds a stack map table if the class file is for Java 6 or later. Java 5 or older Java VMs
  * do not recognize a stack map table.
  *
  * @param pool used for making type hierarchy.
  * @param cf rebuild if this class file is for Java 6 or later.
  * @see #rebuildStackMap(ClassPool)
  * @since 3.6
  */
 public void rebuildStackMapIf6(ClassPool pool, ClassFile cf) throws BadBytecode {
   if (cf.getMajorVersion() >= ClassFile.JAVA_6) rebuildStackMap(pool);
 }