View Javadoc
1 package com.atlassian.util.profiling.object; 2 3 import com.atlassian.util.profiling.UtilTimerStack; 4 5 import java.lang.reflect.InvocationHandler; 6 import java.lang.reflect.Method; 7 import java.lang.reflect.Proxy; 8 import java.lang.reflect.InvocationTargetException; 9 10 /*** 11 * @author <a href="mailto:scott@atlassian.com">Scott Farquhar</a> 12 */ 13 public class ObjectProfiler 14 { 15 16 /*** 17 * Given a class, and an interface that it implements, return a proxied version of the class that implements 18 * the interface. 19 * <p> 20 * The usual use of this is to profile methods from Factory objects: 21 * <pre> 22 * public PersistenceManager getPersistenceManager() 23 * { 24 * return new DefaultPersistenceManager(); 25 * } 26 * 27 * instead write: 28 * public PersistenceManager getPersistenceManager() 29 * { 30 * return ObjectProfiler.getProfiledObject(PersistenceManager.class, new DefaultPersistenceManager()); 31 * } 32 * </pre> 33 * <p> 34 * A side effect of this is that you will no longer be able to downcast to DefaultPersistenceManager. This is probably a *good* thing. 35 * 36 * @param interfaceClazz The interface to implement. 37 * @param o The object to proxy 38 * @return A proxied object, or the input object if the interfaceClazz wasn't an interface. 39 */ 40 public static Object getProfiledObject(Class interfaceClazz, Object o) 41 { 42 //if we are not active - then do nothing 43 if (!UtilTimerStack.isActive()) 44 return o; 45 46 //this should always be true - you shouldn't be passing something that isn't an interface 47 if (interfaceClazz.isInterface()) 48 { 49 InvocationHandler timerHandler = new TimerInvocationHandler(o); 50 Object proxy = Proxy.newProxyInstance(interfaceClazz.getClassLoader(), 51 new Class[]{interfaceClazz}, timerHandler); 52 return proxy; 53 } 54 else 55 { 56 return o; 57 } 58 } 59 60 /*** 61 * A profiled call {@link Method#invoke(java.lang.Object, java.lang.Object[]). If {@link UtilTimerStack#isActive() } 62 * returns false, then no profiling is performed. 63 */ 64 public static Object profiledInvoke(Method target, Object value, Object[] args) throws IllegalAccessException, InvocationTargetException 65 { 66 //if we are not active - then do nothing 67 if (!UtilTimerStack.isActive()) 68 return target.invoke(value, args); 69 70 String logLine = new String(getTrimmedClassName(target) + "." + target.getName() + "()"); 71 72 UtilTimerStack.push(logLine); 73 try 74 { 75 Object returnValue = target.invoke(value, args); 76 77 //if the return value is an interface then we should also proxy it! 78 if (returnValue != null && target.getReturnType().isInterface()) 79 { 80 // System.out.println("Return type " + returnValue.getClass().getName() + " is being proxied " + target.getReturnType().getName() + " " + logLine); 81 InvocationHandler timerHandler = new TimerInvocationHandler(returnValue); 82 Object objectProxy = Proxy.newProxyInstance(returnValue.getClass().getClassLoader(), 83 new Class[]{target.getReturnType()}, timerHandler); 84 return objectProxy; 85 } 86 else 87 { 88 return returnValue; 89 } 90 } 91 finally 92 { 93 UtilTimerStack.pop(logLine); 94 } 95 } 96 97 /*** 98 * Given a method, get the Method name, with no package information. 99 */ 100 public static String getTrimmedClassName(Method method) 101 { 102 String classname = method.getDeclaringClass().getName(); 103 return classname.substring(classname.lastIndexOf('.') + 1); 104 } 105 106 } 107 108 class TimerInvocationHandler implements InvocationHandler 109 { 110 protected Object target; 111 112 public TimerInvocationHandler(Object target) 113 { 114 if (target == null) 115 throw new IllegalArgumentException("Target Object passed to timer cannot be null"); 116 this.target = target; 117 } 118 119 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 120 { 121 return ObjectProfiler.profiledInvoke(method, target, args); 122 } 123 124 }

This page was automatically generated by Maven