001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.bytecode;
005:
006: import com.tc.asm.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.Label;
009: import com.tc.asm.MethodAdapter;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012:
013: /**
014: *
015: * This custom adapter instrument java.lang.reflect.Proxy class so that all DSO interfaces
016: * added to the Proxy class will be filtered out in the getProxyClass method.
017: */
018: public class JavaLangReflectProxyClassAdapter extends ClassAdapter
019: implements Opcodes {
020: private final static String FILTER_INTERFACES_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX
021: + "filterInterfaces";
022: private final static String PROXY_INTERFACES_FIELD_NAME = ByteCodeUtil.TC_FIELD_PREFIX
023: + "proxyInterfaces";
024:
025: public JavaLangReflectProxyClassAdapter(ClassVisitor cv) {
026: super (cv);
027: }
028:
029: public MethodVisitor visitMethod(int access, String name,
030: String desc, String signature, String[] exceptions) {
031: MethodVisitor mv = super .visitMethod(access, name, desc,
032: signature, exceptions);
033: if ("getProxyClass".equals(name)
034: && "(Ljava/lang/ClassLoader;[Ljava/lang/Class;)Ljava/lang/Class;"
035: .equals(desc)) {
036: mv = new FilterInterfacesMethodAdapter(mv);
037: } else if ("<clinit>".equals(name)) {
038: mv = new StaticInitializerMethodAdapter(mv);
039: }
040:
041: return mv;
042: }
043:
044: public void visitEnd() {
045: addProxyInterfacesField();
046: addFilterInterfacesMethod();
047: super .visitEnd();
048: }
049:
050: private void addProxyInterfacesField() {
051: cv.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC
052: + ACC_SYNTHETIC, PROXY_INTERFACES_FIELD_NAME,
053: "[Ljava/lang/Class;", null, null);
054: }
055:
056: private void addFilterInterfacesMethod() {
057: MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC
058: + ACC_SYNTHETIC, FILTER_INTERFACES_METHOD_NAME,
059: "([Ljava/lang/Class;)[Ljava/lang/Class;", null, null);
060: mv.visitCode();
061: Label l0 = new Label();
062: mv.visitLabel(l0);
063: mv.visitTypeInsn(NEW, "java/util/ArrayList");
064: mv.visitInsn(DUP);
065: mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList",
066: "<init>", "()V");
067: mv.visitVarInsn(ASTORE, 1);
068: Label l1 = new Label();
069: mv.visitLabel(l1);
070: mv.visitInsn(ICONST_0);
071: mv.visitVarInsn(ISTORE, 2);
072: Label l2 = new Label();
073: mv.visitLabel(l2);
074: Label l3 = new Label();
075: mv.visitJumpInsn(GOTO, l3);
076: Label l4 = new Label();
077: mv.visitLabel(l4);
078: mv.visitVarInsn(ALOAD, 0);
079: mv.visitVarInsn(ILOAD, 2);
080: mv.visitInsn(AALOAD);
081: mv.visitVarInsn(ASTORE, 3);
082: Label l5 = new Label();
083: mv.visitLabel(l5);
084: mv.visitInsn(ICONST_0);
085: mv.visitVarInsn(ISTORE, 4);
086: Label l6 = new Label();
087: mv.visitLabel(l6);
088: mv.visitInsn(ICONST_0);
089: mv.visitVarInsn(ISTORE, 5);
090: Label l7 = new Label();
091: mv.visitLabel(l7);
092: Label l8 = new Label();
093: mv.visitJumpInsn(GOTO, l8);
094: Label l9 = new Label();
095: mv.visitLabel(l9);
096: mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy",
097: PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
098: mv.visitVarInsn(ILOAD, 5);
099: mv.visitInsn(AALOAD);
100: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName",
101: "()Ljava/lang/String;");
102: mv.visitVarInsn(ALOAD, 3);
103: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName",
104: "()Ljava/lang/String;");
105: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
106: "(Ljava/lang/Object;)Z");
107: Label l10 = new Label();
108: mv.visitJumpInsn(IFEQ, l10);
109: Label l11 = new Label();
110: mv.visitLabel(l11);
111: mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy",
112: PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
113: mv.visitVarInsn(ILOAD, 5);
114: mv.visitInsn(AALOAD);
115: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName",
116: "()Ljava/lang/String;");
117: mv.visitLdcInsn("com.tc");
118: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String",
119: "startsWith", "(Ljava/lang/String;)Z");
120: mv.visitJumpInsn(IFEQ, l10);
121: Label l12 = new Label();
122: mv.visitLabel(l12);
123: mv.visitInsn(ICONST_1);
124: mv.visitVarInsn(ISTORE, 4);
125: Label l13 = new Label();
126: mv.visitLabel(l13);
127: Label l14 = new Label();
128: mv.visitJumpInsn(GOTO, l14);
129: mv.visitLabel(l10);
130: mv.visitIincInsn(5, 1);
131: mv.visitLabel(l8);
132: mv.visitVarInsn(ILOAD, 5);
133: mv.visitFieldInsn(GETSTATIC, "java/lang/reflect/Proxy",
134: PROXY_INTERFACES_FIELD_NAME, "[Ljava/lang/Class;");
135: mv.visitInsn(ARRAYLENGTH);
136: mv.visitJumpInsn(IF_ICMPLT, l9);
137: mv.visitLabel(l14);
138: mv.visitVarInsn(ILOAD, 4);
139: Label l15 = new Label();
140: mv.visitJumpInsn(IFNE, l15);
141: Label l16 = new Label();
142: mv.visitLabel(l16);
143: mv.visitVarInsn(ALOAD, 1);
144: mv.visitVarInsn(ALOAD, 3);
145: mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add",
146: "(Ljava/lang/Object;)Z");
147: mv.visitInsn(POP);
148: mv.visitLabel(l15);
149: mv.visitIincInsn(2, 1);
150: mv.visitLabel(l3);
151: mv.visitVarInsn(ILOAD, 2);
152: mv.visitVarInsn(ALOAD, 0);
153: mv.visitInsn(ARRAYLENGTH);
154: mv.visitJumpInsn(IF_ICMPLT, l4);
155: Label l17 = new Label();
156: mv.visitLabel(l17);
157: mv.visitVarInsn(ALOAD, 1);
158: mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size",
159: "()I");
160: mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
161: mv.visitVarInsn(ASTORE, 2);
162: Label l18 = new Label();
163: mv.visitLabel(l18);
164: mv.visitVarInsn(ALOAD, 1);
165: mv.visitVarInsn(ALOAD, 2);
166: mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List",
167: "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
168: mv.visitInsn(POP);
169: Label l19 = new Label();
170: mv.visitLabel(l19);
171: mv.visitVarInsn(ALOAD, 2);
172: mv.visitInsn(ARETURN);
173: Label l20 = new Label();
174: mv.visitLabel(l20);
175: mv.visitMaxs(0, 0);
176: mv.visitEnd();
177: }
178:
179: private static class FilterInterfacesMethodAdapter extends
180: MethodAdapter implements Opcodes {
181: public FilterInterfacesMethodAdapter(MethodVisitor mv) {
182: super (mv);
183: }
184:
185: public void visitCode() {
186: super .visitCode();
187: mv.visitVarInsn(ALOAD, 1);
188: mv.visitMethodInsn(INVOKESTATIC, "java/lang/reflect/Proxy",
189: FILTER_INTERFACES_METHOD_NAME,
190: "([Ljava/lang/Class;)[Ljava/lang/Class;");
191: mv.visitVarInsn(ASTORE, 1);
192: }
193: }
194:
195: private static class StaticInitializerMethodAdapter extends
196: MethodAdapter implements Opcodes {
197: public StaticInitializerMethodAdapter(MethodVisitor mv) {
198: super (mv);
199: }
200:
201: public void visitInsn(int opcode) {
202: if (RETURN == opcode) {
203: mv.visitTypeInsn(NEW, "java/lang/reflect/Proxy");
204: mv.visitInsn(DUP);
205: mv.visitMethodInsn(INVOKESPECIAL,
206: "java/lang/reflect/Proxy", "<init>", "()V");
207: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object",
208: "getClass", "()Ljava/lang/Class;");
209: mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
210: "getInterfaces", "()[Ljava/lang/Class;");
211: mv.visitFieldInsn(PUTSTATIC, "java/lang/reflect/Proxy",
212: PROXY_INTERFACES_FIELD_NAME,
213: "[Ljava/lang/Class;");
214: }
215: super.visitInsn(opcode);
216: }
217: }
218:
219: }
|