1/*** 2 * ASM tests 3 * Copyright (c) 2002-2005 France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30package org.objectweb.asm.commons; 31 32import java.io.IOException; 33import java.lang.reflect.InvocationTargetException; 34import java.lang.reflect.Method; 35 36import org.objectweb.asm.AbstractTest; 37import org.objectweb.asm.ClassAdapter; 38import org.objectweb.asm.ClassReader; 39import org.objectweb.asm.ClassVisitor; 40import org.objectweb.asm.ClassWriter; 41import org.objectweb.asm.MethodVisitor; 42import org.objectweb.asm.Opcodes; 43 44 45/** 46 * Simple example of using AdviceAdapter to implement tracing callback 47 * 48 * @author Eugene Kuleshov 49 */ 50public class AdviceAdapterTest2 extends AbstractTest { 51 52 public void test() throws Exception { 53 Class c = getClass(); 54 String name = c.getName(); 55 AdvisingClassLoader cl = new AdvisingClassLoader(name+"$"); 56 Class cc = cl.loadClass(name+"$B"); 57 Method m = cc.getMethod("run", new Class[] {Integer.TYPE}); 58 try { 59 m.invoke(null, new Object[] { new Integer(0)}); 60 } catch (InvocationTargetException e) { 61 throw (Exception) e.getTargetException(); 62 } 63 } 64 65 66 private static class AdvisingClassLoader extends ClassLoader { 67 private String prefix; 68 69 public AdvisingClassLoader(String prefix) throws IOException { 70 this.prefix = prefix; 71 } 72 73 public Class loadClass(String name) throws ClassNotFoundException { 74 if(name.startsWith(prefix)) { 75 try { 76 ClassWriter cw = new ClassWriter(true, true); 77 ClassReader cr = new ClassReader(getClass().getResourceAsStream( "/"+name.replace('.', '/')+".class")); 78 cr.accept(new AdviceClassAdapter(cw), false); 79 byte[] bytecode = cw.toByteArray(); 80 return super.defineClass(name, bytecode, 0, bytecode.length); 81 } catch(IOException ex) { 82 throw new ClassNotFoundException( "Load error: "+ex.toString(), ex); 83 } 84 } 85 return super.loadClass(name); 86 } 87 88 } 89 90 91 // test callback 92 private static int n = 0; 93 public static void enter(String msg) { 94 System.err.println(off().append("enter ").append(msg).toString()); 95 n++; 96 } 97 public static void exit(String msg) { 98 n--; 99 System.err.println(off().append("<").toString()); 100 } 101 private static StringBuffer off() { 102 StringBuffer sb = new StringBuffer(); 103 for (int i = 0; i < n; i++) { 104 sb.append(" "); 105 } 106 return sb; 107 } 108 109 110 static class AdviceClassAdapter extends ClassAdapter implements Opcodes { 111 private String cname; 112 113 public AdviceClassAdapter(ClassVisitor cv) { 114 super(cv); 115 } 116 117 public void visit( 118 int version, 119 int access, 120 String name, 121 String signature, 122 String superName, 123 String[] interfaces) 124 { 125 this.cname = name; 126 super.visit(version, access, name, signature, superName, interfaces); 127 } 128 129 public MethodVisitor visitMethod( 130 int access, 131 final String name, 132 final String desc, 133 String signature, 134 String[] exceptions) 135 { 136 MethodVisitor mv = cv.visitMethod(access, 137 name, 138 desc, 139 signature, 140 exceptions); 141 142 if (mv == null 143 || (access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) > 0) 144 { 145 return mv; 146 } 147 148 return new AdviceAdapter(mv, access, name, desc) { 149 protected void onMethodEnter() { 150 mv.visitLdcInsn(cname+"."+name+desc); 151 mv.visitMethodInsn(INVOKESTATIC, 152 "org/objectweb/asm/commons/AdviceAdapterTest2", 153 "enter", "(Ljava/lang/String;)V"); 154 } 155 156 protected void onMethodExit(int opcode) { 157 mv.visitLdcInsn(cname+"."+name+desc); 158 mv.visitMethodInsn(INVOKESTATIC, 159 "org/objectweb/asm/commons/AdviceAdapterTest2", 160 "exit", "(Ljava/lang/String;)V"); 161 } 162 163 }; 164 } 165 } 166 167 168 // TEST CLASSES 169 170 public static class A { 171 final String s; 172 173 public A(String s) { 174 this.s = s; 175 } 176 public A(A a) { 177 this.s = a.s; 178 } 179 } 180 181 182 public static class B extends A { 183 184 public B() { 185 super(new B("")); 186 test(this); 187 } 188 189 public B( A a) { 190 super(a); 191 test(this); 192 } 193 194 public B(String s) { 195 super(s==null ? new A( "") : new A(s)); 196 test(this); 197 } 198 199 private static A aa; 200 public B(String s, A a) { 201 this(s==null ? aa = new A( s) : a); 202 A aa = new A(""); 203 test(aa); 204 } 205 206 public B(String s, String s1) { 207 super(s!=null ? new A( getA(s1).s) : new A( s) ); 208 test(this); 209 } 210 211 212 private void test(Object b) { 213 } 214 private static A getA(String s) { 215 return new A(s); 216 } 217 218 // execute all 219 public static void run(int n) { 220 new B(); 221 new B( new A("")); 222 new B( new B()); 223 new B( "", new A("")); 224 new B( "", ""); 225 } 226 227 } 228 229} 230 231