1 /*
2 * Jour - java profiler and monitoring library
3 *
4 * Copyright (C) 2004 Jour team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21 package net.sf.jour.instrumentor;
22
23 import javassist.CtClass;
24 import javassist.CtConstructor;
25 import javassist.CtMethod;
26 import javassist.CtNewMethod;
27 import net.sf.jour.InterceptorException;
28
29 /**
30 *
31 * Contributing Author(s):
32 *
33 * Misha Lifschitz <mishalifschitz at users.sourceforge.net> (Inital implementation)
34 * Vlad Skarzhevskyy <vlads at users.sourceforge.net> (Inital implementation)
35 *
36 * @author vlads
37 * @version $Revision: 46 $ ($Author: vlads $) $Date: 2007-08-28 14:30:40 -0400 (Tue, 28 Aug 2007) $
38 */
39 public class MethodExecutionTimeInstrumentor extends AbstractInstrumentor implements
40 InstrumentorConsts {
41
42 public boolean instrumentClass(CtClass clazz) throws InterceptorException {
43 return false;
44 }
45
46 public boolean instrumentMethod(CtClass clazz, CtMethod method) throws InterceptorException {
47 addTiming(clazz, method);
48 return true;
49 }
50
51 public boolean instrumentConstructor(CtClass clazz, CtConstructor constructor)
52 throws InterceptorException {
53 return false;
54 }
55
56 private static void addTiming(CtClass clazz, CtMethod method) throws InterceptorException {
57 try {
58 String mname = method.getName();
59 // rename old method to synthetic name, then duplicate the
60 // method with original name for use as interceptor
61 String nname = "jour$"+ mname + "$impl";
62 method.setName(nname);
63 CtMethod mnew = CtNewMethod.copy(method, mname, clazz, null);
64
65 // start the body text generation by saving the start time
66 // to a local variable, then call the timed method; the
67 // actual code generated needs to depend on whether the
68 // timed method returns a value
69 String type = method.getReturnType().getName();
70 StringBuffer body = new StringBuffer();
71 body.append("{\nlong start = System.currentTimeMillis();\n");
72 if (!"void".equals(type)) {
73 body.append(type + " result = ");
74 }
75 body.append(nname + "($$);\n");
76
77 // finish body text generation with call to print the timing
78 // information, and return saved value (if not void)
79 //body.append("net.sf.jour.rt.agent.Elog.logEvent(new net.sf.jour.rt.agent.MethodExecutionTimeEvent(\"" + mname + "\", System.currentTimeMillis()-start));\n");
80 body.append("System.out.println(\"" + mname + "\" + System.currentTimeMillis()-start));\n");
81 if (!"void".equals(type)) {
82 body.append("return result;\n");
83 }
84 body.append("}");
85
86 // replace the body of the interceptor method with generated
87 // code block and add it to class
88 mnew.setBody(body.toString());
89 clazz.addMethod(mnew);
90 } catch (Exception e) {
91 e.printStackTrace();
92 throw new InterceptorException("Failed to add timing to method " + method.getName());
93 }
94 }
95 }