KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > interceptor > InvocationInterceptor


1 /*
2  * Copyright(C) 2001 Mika Riekkinen, Joni Suominen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or(at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package alt.jiapi.interceptor;
20
21 import java.lang.reflect.InvocationHandler JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.apache.log4j.Category;
30
31 import alt.jiapi.InstrumentationContext;
32 import alt.jiapi.InstrumentationDescriptor;
33 import alt.jiapi.reflect.Signature;
34
35 import alt.jiapi.event.EventProducer;
36
37 /**
38  * InvocationInterceptor intercepts method invocations and
39  * delegates invocations to InvokeHandler.<p>
40  * Following code snippet is an example, how to initialize
41  * InvocationInterceptor:
42  *
43  * <pre>
44  * InstrumentationContext ctx = new InstrumentationContext();
45  * InstrumentationDescriptor id = new InstrumentationDescriptor();
46  * id.addInclusionRule("samples.*");
47  * ctx.addInstrumentationDescriptor(id);
48  *
49  * InvocationInterceptor ii = new InvocationInterceptor(id, "java*",this);
50  * </pre>
51  *
52  * @author Mika Riekkinen
53  * @version $Revision: 1.9 $ $Date: 2004/04/11 14:22:58 $
54  */

55 public class InvocationInterceptor extends EventProducer {
56     private InvocationHandler JavaDoc handler;
57     private HashMap JavaDoc rmCache = new HashMap JavaDoc();
58
59     /**
60      * Constructor. Resolution is set to '*'.
61      *
62      * @param id Instrumentation decsriptor, that this InvocationInterceptor
63      * registers itself to.
64      * @param handler InvocationHandler
65      */

66     public InvocationInterceptor(InstrumentationDescriptor id, InvocationHandler JavaDoc handler) {
67         this(id, "*", handler);
68     }
69
70
71     /**
72      * Creates new InvocationInterceptor. Resolution tells, which
73      * methods are to be intercepted.
74      *
75      * @param id Instrumentation decsriptor, that this InvocationInterceptor
76      * registers itself to.
77      * @param resolution Resolution, that is used to select which
78      * methods will be intercepted.
79      * @param handler InvocationHandler
80      */

81     public InvocationInterceptor(InstrumentationDescriptor id,
82                                  String JavaDoc resolution, InvocationHandler JavaDoc handler){
83         this(id, new String JavaDoc[] { resolution }, handler);
84     }
85
86
87     /**
88      * Creates new InvocationInterceptor.
89      *
90      * @param id Instrumentation decsriptor, that this InvocationInterceptor
91      * registers itself to.
92      * @param resolutions Resolutions, that is used further to select which
93      * methods will trigger events to be produced.
94      * @param handler InvocationHandler
95      */

96     public InvocationInterceptor(InstrumentationDescriptor id,
97                                  String JavaDoc[] resolutions,
98                                  InvocationHandler JavaDoc handler) {
99         super(resolutions);
100         this.handler = handler;
101
102         id.addInstrumentor(new InvocationInstrumentor(this, handler));
103     }
104
105
106
107     /**
108      * Called by Jiapi runtime.
109      * @param o if invocation is being made to an static method,
110      * this parameter holds a Class of the called method,
111      * otherwise this is the instance, that invocation should be
112      * acted on.
113      * @param name of the method to call
114      * @param args Arguments of the method
115      */

116     public Object JavaDoc invokeMethod(Object JavaDoc o, String JavaDoc name, Object JavaDoc[] args,
117                                String JavaDoc signature) throws Throwable JavaDoc {
118         try {
119             Method JavaDoc m = null;
120             Class JavaDoc c = null;
121             if (o instanceof Class JavaDoc) { // invokestatic
122
c = (Class JavaDoc)o;
123             }
124             else { // invokevirtual
125
c = o.getClass();
126             }
127
128             //System.out.println("Signature: " + signature);
129

130             //long l1 = System.currentTimeMillis();
131
m = getReflectionMethod(c, name, args, signature);
132             //long l2 = System.currentTimeMillis();
133
//System.out.println((l2-l1));
134

135             Object JavaDoc r = handler.invoke(o, m, args);
136             return r;
137         }
138         catch(java.lang.reflect.InvocationTargetException JavaDoc ite) {
139             throw ite.getTargetException();
140         }
141         catch(Throwable JavaDoc t) {
142             t.printStackTrace();
143             throw t;
144         }
145     }
146
147
148     private Method JavaDoc getReflectionMethod(Class JavaDoc c, String JavaDoc name, Object JavaDoc[] args,
149                                        String JavaDoc signature) {
150         Method JavaDoc m = null;
151
152         // NOTE: cache should be configurable. It can potentially
153
// consume a lot of memory
154
m = (Method JavaDoc)rmCache.get(signature);
155         if (m != null) {
156             return m;
157         }
158         
159         String JavaDoc sign = signature.substring(signature.lastIndexOf('('));
160         Signature s = new Signature(sign);
161
162         String JavaDoc[] paramTypes = s.getParameters();
163
164         try {
165             Class JavaDoc[] params = params = new Class JavaDoc[args.length];
166
167             for (int i = 0; i < args.length; i++) {
168                 params[i] = args[i].getClass();
169
170                 // BUG: Following code segment makes a false
171
// assumption, that java.lang.Integer etc. allways
172
// represents a primitive type
173
if ("int".equals(paramTypes[i])) {
174                     params[i] = Integer.TYPE;
175                 }
176                 else if ("long".equals(paramTypes[i])) {
177                     params[i] = Long.TYPE;
178                 }
179                 else if ("char".equals(paramTypes[i])) {
180                     params[i] = Character.TYPE;
181                 }
182                 else if ("boolean".equals(paramTypes[i])) {
183                     params[i] = Boolean.TYPE;
184                 }
185                 else if ("byte".equals(paramTypes[i])) {
186                     params[i] = Byte.TYPE;
187                 }
188                 else if ("float".equals(paramTypes[i])) {
189                     params[i] = Float.TYPE;
190                 }
191                 else if ("double".equals(paramTypes[i])) {
192                     params[i] = Double.TYPE;
193                 }
194             }
195
196             m = c.getMethod(name, params);
197         }
198         catch(Exception JavaDoc e) {
199             e.printStackTrace();
200         }
201
202         rmCache.put(signature, m);
203
204         return m;
205     }
206 }
207
208
Popular Tags