blob: ed05dd21b9ebd29dd716662b3176f4a66d97b4c6 [file] [log] [blame]
Igor Murashkine363fbb2013-06-25 20:26:06 +00001
2package android.hardware.photography.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.photography.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}