01: /* FacadeInvoker.java
02:
03: {{IS_NOTE
04:
05: Purpose:
06: Description:
07: History:
08: 2001/11/27 20:06:18, Create, Tom M. Yeh.
09: }}IS_NOTE
10:
11: Copyright (C) 2001 Potix Corporation. All Rights Reserved.
12:
13: {{IS_RIGHT
14: This program is distributed under GPL Version 2.0 in the hope that
15: it will be useful, but WITHOUT ANY WARRANTY.
16: }}IS_RIGHT
17: */
18: package org.zkoss.lang.reflect;
19:
20: import java.lang.reflect.Method;
21: import java.lang.reflect.Proxy;
22: import java.lang.reflect.InvocationHandler;
23: import java.lang.reflect.InvocationTargetException;
24:
25: import org.zkoss.lang.Classes;
26:
27: /**
28: * The facade invocation handler. Like the facade pattern, this invocation
29: * handler is used to facade an object with a set of interfaces.
30: *
31: * <p>This Invocation handler assumes the object being facaded
32: * (aka, the target) has all methods of these interfaces, but it might not
33: * implement all of these interfaces directly.
34: *
35: * <p>It happens when you need to provide interfaces to classes that
36: * come from third parties.
37: *
38: * <p>Example:<br>
39: *<pre><code>class A {
40: * public void f() {...}
41: *}
42: *interface I {
43: * public void f();
44: *}</code>
45: *Then, you could do:
46: *<code>I i = (I)FacadeInvoker.newInstance(new A(), new Class[] {I});</code></pre>
47: *
48: * @author tomyeh
49: */
50: public class FacadeInvoker implements InvocationHandler {
51: /** The target that really implements the interfaces. */
52: private Object _target;
53:
54: /**
55: * Creates an object that implements the giving interfaces by
56: * wrapping a giving object, traget.
57: *
58: * <p>The target must have all methods in all given interfaces,
59: * but might not implement all these interfaces.
60: */
61: public static final Object newInstance(Object target,
62: Class[] interfaces, ClassLoader clsLoader) {
63: return Proxy.newProxyInstance(clsLoader, interfaces,
64: new FacadeInvoker(target));
65: }
66:
67: /**
68: * Creates an object that implements the giving interfaces by
69: * wrapping a giving object, traget.
70: * <p>A shortcut: newInstance(
71: * target, interfaces, Thread.currentThread().getContextClassLoader()).
72: */
73: public static final Object newInstance(Object target,
74: Class[] interfaces) {
75: return newInstance(target, interfaces, Thread.currentThread()
76: .getContextClassLoader());
77: }
78:
79: protected FacadeInvoker(Object target) {
80: _target = target;
81: }
82:
83: //-- InvocationInvoker --//
84: public Object invoke(Object proxy, Method method, Object[] args)
85: throws Throwable {
86: Class cls = _target.getClass();
87: if (!method.getDeclaringClass().isAssignableFrom(cls))
88: method = Classes.getMethodInPublic(cls, method.getName(),
89: method.getParameterTypes());
90:
91: try {
92: return method.invoke(_target, args);
93: } catch (InvocationTargetException ex) {
94: throw ex.getCause();
95: }
96: }
97: }
|