View Javadoc

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 net.sf.jour.InterceptorException;
24  
25  import javassist.*;
26  import javassist.CtConstructor;
27  import javassist.CtMethod;
28  
29  /***
30   * TODO Add docs
31   *
32   * Contributing Author(s):
33   *
34   *   Misha Lifschitz <mishalifschitz at users.sourceforge.net> (Inital implementation)
35   *   Vlad Skarzhevskyy <vlads at users.sourceforge.net> (Inital implementation)
36   *
37   * @author vlads
38   * @version $Revision: 1.3 $ ($Author: vlads $) $Date: 2004/12/05 02:25:20 $
39   */
40  public class MethodExecutionTimeInstrumentor extends AbstractInstrumentor implements
41          InstrumentorConsts {
42      /***
43       * DOCUMENT ME!
44       * 
45       * @param clazz
46       *            DOCUMENT ME!
47       * 
48       * @throws InterceptorException
49       *             DOCUMENT ME!
50       */
51      public boolean instrumentClass(CtClass clazz) throws InterceptorException {
52  		return false;
53      }
54  
55      /***
56       * DOCUMENT ME!
57       * 
58       * @param clazz
59       *            DOCUMENT ME!
60       * @param method
61       *            DOCUMENT ME!
62       * 
63       * @throws InterceptorException
64       *             DOCUMENT ME!
65       */
66      public boolean instrumentMethod(CtClass clazz, CtMethod method) throws InterceptorException {
67          addTiming(clazz, method);
68  		return true;
69      }
70  
71      /***
72       * DOCUMENT ME!
73       * 
74       * @param clazz
75       *            DOCUMENT ME!
76       * @param constructor
77       *            DOCUMENT ME!
78       * 
79       * @throws InterceptorException
80       *             DOCUMENT ME!
81       */
82      public boolean instrumentConstructor(CtClass clazz, CtConstructor constructor)
83              throws InterceptorException {
84           return false;
85      }
86  
87      private static void addTiming(CtClass clazz, CtMethod method) throws InterceptorException {
88          try {
89          String mname = method.getName();
90          //  rename old method to synthetic name, then duplicate the
91          //  method with original name for use as interceptor
92          String nname = "jour$"+ mname + "$impl";
93          method.setName(nname);
94          CtMethod mnew = CtNewMethod.copy(method, mname, clazz, null);
95  
96          //  start the body text generation by saving the start time
97          //  to a local variable, then call the timed method; the
98          //  actual code generated needs to depend on whether the
99          //  timed method returns a value
100         String type = method.getReturnType().getName();
101         StringBuffer body = new StringBuffer();
102         body.append("{\nlong start = System.currentTimeMillis();\n");
103         if (!"void".equals(type)) {
104             body.append(type + " result = ");
105         }
106         body.append(nname + "($$);\n");
107 
108         //  finish body text generation with call to print the timing
109         //  information, and return saved value (if not void)
110         body.append("net.sf.jour.rt.agent.Elog.logEvent(new net.sf.jour.rt.agent.MethodExecutionTimeEvent(\"" + mname + "\", System.currentTimeMillis()-start));\n");
111         if (!"void".equals(type)) {
112             body.append("return result;\n");
113         }
114         body.append("}");
115 
116         //  replace the body of the interceptor method with generated
117         //  code block and add it to class
118         mnew.setBody(body.toString());
119         clazz.addMethod(mnew);
120         } catch (Exception e) {
121             e.printStackTrace();
122             throw new InterceptorException("Failed to add timing to method " + method.getName());
123         }
124     }
125 }