/* FacadeInvoker.java Purpose: Description: History: 2001/11/27 20:06:18, Create, Tom M. Yeh. Copyright (C) 2001 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.lang.reflect; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import org.zkoss.lang.Classes; /** * The facade invocation handler. Like the facade pattern, this invocation * handler is used to facade an object with a set of interfaces. * * <p>This Invocation handler assumes the object being facaded * (a.k.a, the target) has all methods of these interfaces, but it might not * implement all of these interfaces directly. * * <p>It happens when you need to provide interfaces to classes that * come from third parties. * * <p>Example:<br> *<pre><code>class A { * public void f() {...} *} *interface I { * public void f(); *}</code> *Then, you could do: *<code>I i = (I)FacadeInvoker.newInstance(new A(), new Class[] {I});</code></pre> * * @author tomyeh */ public class FacadeInvoker implements InvocationHandler { /** The target that really implements the interfaces. */ private Object _target; /** * Creates an object that implements the giving interfaces by * wrapping a giving object, target. * * <p>The target must have all methods in all given interfaces, * but might not implement all these interfaces. */ public static final Object newInstance (Object target, Class[] interfaces, ClassLoader clsLoader) { return Proxy.newProxyInstance( clsLoader, interfaces, new FacadeInvoker(target)); } /** * Creates an object that implements the giving interfaces by * wrapping a giving object, target. * <p>A shortcut: newInstance( * target, interfaces, Thread.currentThread().getContextClassLoader()). */ public static final Object newInstance(Object target, Class[] interfaces) { ClassLoader cl = Classes.getContextClassLoader(FacadeInvoker.class); return newInstance(target, interfaces, cl != null ? cl: FacadeInvoker.class.getClassLoader()); } protected FacadeInvoker(Object target) { _target = target; } //-- InvocationInvoker --// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Class cls = _target.getClass(); if (!method.getDeclaringClass().isAssignableFrom(cls)) method = Classes.getMethodInPublic( cls, method.getName(), method.getParameterTypes()); try { return method.invoke(_target, args); }catch(InvocationTargetException ex) { throw ex.getCause(); } } }