KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > ManagerHelperFactory


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.object.bytecode;
5
6 import com.tc.asm.MethodVisitor;
7 import com.tc.asm.Opcodes;
8 import com.tc.asm.Type;
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.Collections JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Map JavaDoc;
14
15 /**
16  * A helper class to assist in adding Manager method calls into instrumented classes <br>
17  * <br>
18  * Actually, this class could probably be generalized as some form of interface caller for instrumented classes
19  */

20 public class ManagerHelperFactory {
21   private final Class JavaDoc managerUtilClass;
22   private final Map JavaDoc methods;
23
24   public ManagerHelperFactory() {
25     this.managerUtilClass = ManagerUtil.class;
26     this.methods = findMethods();
27   }
28
29   private Map JavaDoc findMethods() {
30     Map JavaDoc map = new HashMap JavaDoc();
31
32     Method JavaDoc[] mgrUtilMethods = this.managerUtilClass.getDeclaredMethods();
33
34     for (int i = 0; i < mgrUtilMethods.length; i++) {
35       Method JavaDoc m = mgrUtilMethods[i];
36       String JavaDoc name = m.getName();
37       MethodDetail md = new MethodDetail(m);
38
39       if (map.containsKey(name)) {
40         throw new RuntimeException JavaDoc("Duplicated method name [" + name + "] on interface " + managerUtilClass.getName());
41       } else {
42         map.put(name, md);
43       }
44     }
45
46     return Collections.unmodifiableMap(map);
47   }
48
49   public ManagerHelper createHelper() {
50     return new ManagerHelperImpl();
51   }
52
53   private static class MethodDetail implements Opcodes {
54     final String JavaDoc name;
55     final String JavaDoc desc;
56     final boolean takesManagerAsAnArg;
57
58     MethodDetail(Method JavaDoc m) {
59       desc = Type.getMethodDescriptor(m);
60       name = m.getName();
61       takesManagerAsAnArg = hasManagerClass(m.getParameterTypes());
62     }
63
64     private boolean hasManagerClass(Class JavaDoc[] parameterTypes) {
65       if (parameterTypes == null) return false;
66       for (int i = 0; i < parameterTypes.length; i++) {
67         if (parameterTypes[i].getName().equals(Manager.class.getName())) { return true; }
68       }
69       return false;
70     }
71
72   }
73
74   private class ManagerHelperImpl implements ManagerHelper, Opcodes {
75     public ManagerHelperImpl() {
76       //
77
}
78
79     public void callManagerMethod(String JavaDoc name, MethodVisitor mv) {
80       MethodDetail md = findMethodDetail(name);
81       callMethod(md, mv);
82     }
83
84     private MethodDetail findMethodDetail(String JavaDoc name) {
85       MethodDetail md = (MethodDetail) methods.get(name);
86       if (md == null) {
87         // make formatter work
88
throw new RuntimeException JavaDoc("No such method [" + name + "] on manager class: " + managerUtilClass.getName());
89       }
90       return md;
91     }
92
93     private void callMethod(MethodDetail md, MethodVisitor mv) {
94       // TODO: We can easily optimize for manager methods that take 0/1/2? arguments. Provided that a few swap
95
// instructions are faster than an invokestatic
96
mv.visitMethodInsn(INVOKESTATIC, ManagerUtil.CLASS, md.name, md.desc);
97     }
98
99   }
100
101 }
Popular Tags