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 }