1 2package android.hardware.camera2.utils; 3 4import java.lang.reflect.*; 5 6/** 7 * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism. 8 * 9 * @see android.hardware.camera2.utils.Decorator#newInstance 10 * 11 * @hide 12 */ 13public class Decorator<T> implements InvocationHandler { 14 15 public interface DecoratorListener { 16 /** 17 * This method is called before the target method is invoked 18 * @param args arguments to target method 19 * @param m Method being called 20 */ 21 void onBeforeInvocation(Method m, Object[] args); 22 /** 23 * This function is called after the target method is invoked 24 * if there were no uncaught exceptions 25 * @param args arguments to target method 26 * @param m Method being called 27 * @param result return value of target method 28 */ 29 void onAfterInvocation(Method m, Object[] args, Object result); 30 /** 31 * This method is called only if there was an exception thrown by the target method 32 * during its invocation. 33 * 34 * @param args arguments to target method 35 * @param m Method being called 36 * @param t Throwable that was thrown 37 * @return false to rethrow exception, true if the exception was handled 38 */ 39 boolean onCatchException(Method m, Object[] args, Throwable t); 40 /** 41 * This is called after the target method is invoked, regardless of whether or not 42 * there were any exceptions. 43 * @param args arguments to target method 44 * @param m Method being called 45 */ 46 void onFinally(Method m, Object[] args); 47 } 48 49 private final T mObject; 50 private final DecoratorListener mListener; 51 52 /** 53 * Create a decorator wrapping the specified object's method calls. 54 * 55 * @param obj the object whose method calls you want to intercept 56 * @param listener the decorator handler for intercepted method calls 57 * @param <T> the type of the element you want to wrap. This must be an interface. 58 * @return a wrapped interface-compatible T 59 */ 60 @SuppressWarnings("unchecked") 61 public static<T> T newInstance(T obj, DecoratorListener listener) { 62 return (T)java.lang.reflect.Proxy.newProxyInstance( 63 obj.getClass().getClassLoader(), 64 obj.getClass().getInterfaces(), 65 new Decorator<T>(obj, listener)); 66 } 67 68 private Decorator(T obj, DecoratorListener listener) { 69 this.mObject = obj; 70 this.mListener = listener; 71 } 72 73 @Override 74 public Object invoke(Object proxy, Method m, Object[] args) 75 throws Throwable 76 { 77 Object result = null; 78 try { 79 mListener.onBeforeInvocation(m, args); 80 result = m.invoke(mObject, args); 81 mListener.onAfterInvocation(m, args, result); 82 } catch (InvocationTargetException e) { 83 Throwable t = e.getTargetException(); 84 if (!mListener.onCatchException(m, args, t)) { 85 throw t; 86 } 87 } finally { 88 mListener.onFinally(m, args); 89 } 90 return result; 91 } 92} 93