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