001: /***
002: * ASM tests
003: * Copyright (c) 2002-2005 France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.objectweb.asm.commons;
030:
031: import java.io.IOException;
032: import java.lang.reflect.InvocationTargetException;
033: import java.lang.reflect.Method;
034:
035: import org.objectweb.asm.AbstractTest;
036: import org.objectweb.asm.ClassAdapter;
037: import org.objectweb.asm.ClassReader;
038: import org.objectweb.asm.ClassVisitor;
039: import org.objectweb.asm.ClassWriter;
040: import org.objectweb.asm.MethodVisitor;
041: import org.objectweb.asm.Opcodes;
042:
043: /**
044: * Simple example of using AdviceAdapter to implement tracing callback
045: *
046: * @author Eugene Kuleshov
047: */
048: public class AdviceAdapterUnitTest extends AbstractTest {
049:
050: public void test() throws Exception {
051: Class c = getClass();
052: String name = c.getName();
053: AdvisingClassLoader cl = new AdvisingClassLoader(name + "$");
054: Class cc = cl.loadClass(name + "$B");
055: Method m = cc.getMethod("run", new Class[] { Integer.TYPE });
056: try {
057: m.invoke(null, new Object[] { new Integer(0) });
058: } catch (InvocationTargetException e) {
059: throw (Exception) e.getTargetException();
060: }
061: }
062:
063: private static class AdvisingClassLoader extends ClassLoader {
064: private String prefix;
065:
066: public AdvisingClassLoader(final String prefix)
067: throws IOException {
068: this .prefix = prefix;
069: }
070:
071: public Class loadClass(final String name)
072: throws ClassNotFoundException {
073: if (name.startsWith(prefix)) {
074: try {
075: ClassWriter cw = new ClassWriter(
076: ClassWriter.COMPUTE_MAXS);
077: ClassReader cr = new ClassReader(getClass()
078: .getResourceAsStream(
079: "/" + name.replace('.', '/')
080: + ".class"));
081: cr.accept(new AdviceClassAdapter(cw),
082: ClassReader.EXPAND_FRAMES);
083: byte[] bytecode = cw.toByteArray();
084: return super .defineClass(name, bytecode, 0,
085: bytecode.length);
086: } catch (IOException ex) {
087: throw new ClassNotFoundException("Load error: "
088: + ex.toString(), ex);
089: }
090: }
091: return super .loadClass(name);
092: }
093:
094: }
095:
096: // test callback
097: private static int n = 0;
098:
099: public static void enter(final String msg) {
100: System.err.println(off().append("enter ").append(msg)
101: .toString());
102: n++;
103: }
104:
105: public static void exit(final String msg) {
106: n--;
107: System.err.println(off().append("<").toString());
108: }
109:
110: private static StringBuffer off() {
111: StringBuffer sb = new StringBuffer();
112: for (int i = 0; i < n; i++) {
113: sb.append(" ");
114: }
115: return sb;
116: }
117:
118: static class AdviceClassAdapter extends ClassAdapter implements
119: Opcodes {
120: private String cname;
121:
122: public AdviceClassAdapter(final ClassVisitor cv) {
123: super (cv);
124: }
125:
126: public void visit(final int version, final int access,
127: final String name, final String signature,
128: final String super Name, final String[] interfaces) {
129: this .cname = name;
130: super .visit(version, access, name, signature, super Name,
131: interfaces);
132: }
133:
134: public MethodVisitor visitMethod(final int access,
135: final String name, final String desc,
136: final String signature, final String[] exceptions) {
137: MethodVisitor mv = cv.visitMethod(access, name, desc,
138: signature, exceptions);
139:
140: if (mv == null
141: || (access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) > 0) {
142: return mv;
143: }
144:
145: return new AdviceAdapter(mv, access, name, desc) {
146: protected void onMethodEnter() {
147: mv.visitLdcInsn(cname + "." + name + desc);
148: mv
149: .visitMethodInsn(
150: INVOKESTATIC,
151: "org/objectweb/asm/commons/AdviceAdapterUnitTest",
152: "enter", "(Ljava/lang/String;)V");
153: }
154:
155: protected void onMethodExit(final int opcode) {
156: mv.visitLdcInsn(cname + "." + name + desc);
157: mv
158: .visitMethodInsn(
159: INVOKESTATIC,
160: "org/objectweb/asm/commons/AdviceAdapterUnitTest",
161: "exit", "(Ljava/lang/String;)V");
162: }
163:
164: };
165: }
166: }
167:
168: // TEST CLASSES
169:
170: public static class A {
171: final String s;
172:
173: public A(final String s) {
174: this .s = s;
175: }
176:
177: public A(final A a) {
178: this .s = a.s;
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(final A a) {
190: super (a);
191: test(this );
192: }
193:
194: public B(final String s) {
195: super (s == null ? new A("") : new A(s));
196: test(this );
197: }
198:
199: private static A aa;
200:
201: public B(final String s, final A a) {
202: this (s == null ? aa = new A(s) : a);
203: A aa = new A("");
204: test(aa);
205: }
206:
207: public B(final String s, final String s1) {
208: super (s != null ? new A(getA(s1).s) : new A(s));
209: test(this );
210: }
211:
212: private void test(final Object b) {
213: }
214:
215: private static A getA(final String s) {
216: return new A(s);
217: }
218:
219: // execute all
220: public static void run(final int n) {
221: new B();
222: new B(new A(""));
223: new B(new B());
224: new B("", new A(""));
225: new B("", "");
226: }
227:
228: }
229: }
|