| |
| package android.hardware.camera2.utils; |
| |
| import java.lang.reflect.*; |
| |
| /** |
| * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism. |
| * |
| * @see android.hardware.camera2.utils.Decorator#newInstance |
| * |
| * @hide |
| */ |
| public class Decorator<T> implements InvocationHandler { |
| |
| public interface DecoratorListener { |
| /** |
| * This method is called before the target method is invoked |
| * @param args arguments to target method |
| * @param m Method being called |
| */ |
| void onBeforeInvocation(Method m, Object[] args); |
| /** |
| * This function is called after the target method is invoked |
| * if there were no uncaught exceptions |
| * @param args arguments to target method |
| * @param m Method being called |
| * @param result return value of target method |
| */ |
| void onAfterInvocation(Method m, Object[] args, Object result); |
| /** |
| * This method is called only if there was an exception thrown by the target method |
| * during its invocation. |
| * |
| * @param args arguments to target method |
| * @param m Method being called |
| * @param t Throwable that was thrown |
| * @return false to rethrow exception, true if the exception was handled |
| */ |
| boolean onCatchException(Method m, Object[] args, Throwable t); |
| /** |
| * This is called after the target method is invoked, regardless of whether or not |
| * there were any exceptions. |
| * @param args arguments to target method |
| * @param m Method being called |
| */ |
| void onFinally(Method m, Object[] args); |
| } |
| |
| private final T mObject; |
| private final DecoratorListener mListener; |
| |
| /** |
| * Create a decorator wrapping the specified object's method calls. |
| * |
| * @param obj the object whose method calls you want to intercept |
| * @param listener the decorator handler for intercepted method calls |
| * @param <T> the type of the element you want to wrap. This must be an interface. |
| * @return a wrapped interface-compatible T |
| */ |
| @SuppressWarnings("unchecked") |
| public static<T> T newInstance(T obj, DecoratorListener listener) { |
| return (T)java.lang.reflect.Proxy.newProxyInstance( |
| obj.getClass().getClassLoader(), |
| obj.getClass().getInterfaces(), |
| new Decorator<T>(obj, listener)); |
| } |
| |
| private Decorator(T obj, DecoratorListener listener) { |
| this.mObject = obj; |
| this.mListener = listener; |
| } |
| |
| @Override |
| public Object invoke(Object proxy, Method m, Object[] args) |
| throws Throwable |
| { |
| Object result = null; |
| try { |
| mListener.onBeforeInvocation(m, args); |
| result = m.invoke(mObject, args); |
| mListener.onAfterInvocation(m, args, result); |
| } catch (InvocationTargetException e) { |
| Throwable t = e.getTargetException(); |
| if (!mListener.onCatchException(m, args, t)) { |
| throw t; |
| } |
| } finally { |
| mListener.onFinally(m, args); |
| } |
| return result; |
| } |
| } |