JavaLangReflectProxyClassAdapter.java :  » Net » Terracotta » com » tc » object » bytecode » Java Open Source

Java Open Source » Net » Terracotta 
Terracotta » com » tc » object » bytecode » JavaLangReflectProxyClassAdapter.java
/*
 * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice.  All rights reserved.
 */
package com.tc.object.bytecode;

import com.tc.asm.ClassAdapter;
import com.tc.asm.ClassVisitor;
import com.tc.asm.Label;
import com.tc.asm.MethodAdapter;
import com.tc.asm.MethodVisitor;
import com.tc.asm.Opcodes;

/**
 * 
 * This custom adapter instrument java.lang.reflect.Proxy class so that all DSO interfaces
 * added to the Proxy class will be filtered out in the getProxyClass method.
 */
public class JavaLangReflectProxyClassAdapter extends ClassAdapter implements Opcodes {
  private final static String FILTER_INTERFACES_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "filterInterfaces";
  private final static String PROXY_INTERFACES_FIELD_NAME = ByteCodeUtil.TC_FIELD_PREFIX + "proxyInterfaces";
  
  public JavaLangReflectProxyClassAdapter(ClassVisitor cv) {
    super(cv);
  }
  
  public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    if ("getProxyClass".equals(name) && "(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Class;".equals(desc)) {
      mv = new FilterInterfacesMethodAdapter(mv);
    } else if ("<clinit>".equals(name)) {
      mv = new StaticInitializerMethodAdapter(mv);
    }
    
    return mv;
  }  
  
  public void visitEnd() {
    addProxyInterfacesField();
    addFilterInterfacesMethod();
    super.visitEnd();
  }
  
  private void addProxyInterfacesField() {
    cv.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC, PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;", null, null);
  }
  
  private void addFilterInterfacesMethod() {
    MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, FILTER_INTERFACES_METHOD_NAME, "([Ljava/lang/Class;)[Ljava/lang/Class;", null, null);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    mv.visitTypeInsn(NEW, "java/util/ArrayList");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V");
    mv.visitVarInsn(ASTORE, 1);
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitInsn(ICONST_0);
    mv.visitVarInsn(ISTORE, 2);
    Label l2 = new Label();
    mv.visitLabel(l2);
    Label l3 = new Label();
    mv.visitJumpInsn(GOTO, l3);
    Label l4 = new Label();
    mv.visitLabel(l4);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ILOAD, 2);
    mv.visitInsn(AALOAD);
    mv.visitVarInsn(ASTORE, 3);
    Label l5 = new Label();
    mv.visitLabel(l5);
    mv.visitInsn(ICONST_0);
    mv.visitVarInsn(ISTORE, 4);
    Label l6 = new Label();
    mv.visitLabel(l6);
    mv.visitInsn(ICONST_0);
    mv.visitVarInsn(ISTORE, 5);
    Label l7 = new Label();
    mv.visitLabel(l7);
    Label l8 = new Label();
    mv.visitJumpInsn(GOTO, l8);
    Label l9 = new Label();
    mv.visitLabel(l9);
    mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy", PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
    mv.visitVarInsn(ILOAD, 5);
    mv.visitInsn(AALOAD);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
    mv.visitVarInsn(ALOAD, 3);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
    Label l10 = new Label();
    mv.visitJumpInsn(IFEQ, l10);
    Label l11 = new Label();
    mv.visitLabel(l11);
    mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy", PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
    mv.visitVarInsn(ILOAD, 5);
    mv.visitInsn(AALOAD);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
    mv.visitLdcInsn("com.tc");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "startsWith", "(Ljava/lang/String;)Z");
    mv.visitJumpInsn(IFEQ, l10);
    Label l12 = new Label();
    mv.visitLabel(l12);
    mv.visitInsn(ICONST_1);
    mv.visitVarInsn(ISTORE, 4);
    Label l13 = new Label();
    mv.visitLabel(l13);
    Label l14 = new Label();
    mv.visitJumpInsn(GOTO, l14);
    mv.visitLabel(l10);
    mv.visitIincInsn(5, 1);
    mv.visitLabel(l8);
    mv.visitVarInsn(ILOAD, 5);
    mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy", PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
    mv.visitInsn(ARRAYLENGTH);
    mv.visitJumpInsn(IF_ICMPLT, l9);
    mv.visitLabel(l14);
    mv.visitVarInsn(ILOAD, 4);
    Label l15 = new Label();
    mv.visitJumpInsn(IFNE, l15);
    Label l16 = new Label();
    mv.visitLabel(l16);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 3);
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z");
    mv.visitInsn(POP);
    mv.visitLabel(l15);
    mv.visitIincInsn(2, 1);
    mv.visitLabel(l3);
    mv.visitVarInsn(ILOAD, 2);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ARRAYLENGTH);
    mv.visitJumpInsn(IF_ICMPLT, l4);
    Label l17 = new Label();
    mv.visitLabel(l17);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I");
    mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
    mv.visitVarInsn(ASTORE, 2);
    Label l18 = new Label();
    mv.visitLabel(l18);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
    mv.visitInsn(POP);
    Label l19 = new Label();
    mv.visitLabel(l19);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitInsn(ARETURN);
    Label l20 = new Label();
    mv.visitLabel(l20);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
  }

  private static class FilterInterfacesMethodAdapter extends MethodAdapter implements Opcodes {
    public FilterInterfacesMethodAdapter(MethodVisitor mv) {
      super(mv);
    }
    
    public void visitCode() {
      super.visitCode();
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(INVOKESTATIC, "java/lang/reflect/Proxy", FILTER_INTERFACES_METHOD_NAME, "([Ljava/lang/Class;)[Ljava/lang/Class;");
      mv.visitVarInsn(ASTORE, 1);
    }
  }
  
  private static class StaticInitializerMethodAdapter extends MethodAdapter implements Opcodes {
    public StaticInitializerMethodAdapter(MethodVisitor mv) {
      super(mv);
    }
    
    public void visitInsn(int opcode) {
      if (RETURN == opcode) {
        mv.visitTypeInsn(NEW, "java/lang/reflect/Proxy");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/Proxy", "<init>", "()V");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getInterfaces", "()[Ljava/lang/Class;");
        mv.visitFieldInsn(PUTSTATIC, "java/lang/reflect/Proxy", PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
      }
      super.visitInsn(opcode);
    }
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.