package com.swtworkbench.community.xswt.scripting; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.omg.CORBA.portable.InvokeHandler; import com.swtworkbench.community.xswt.XSWTException; import com.swtworkbench.community.xswt.dataparser.IDataParserContext; import com.swtworkbench.community.xswt.dataparser.NonDisposableDataParser; public class InterfaceDataParser extends NonDisposableDataParser { private static class FunctionProxy implements InvocationHandler { protected Function fun; public FunctionProxy(Function fun) { this.fun = fun; } protected Object invoke(Method method, Object[] args) throws Throwable { if (fun.arity() != args.length) { throw new IllegalArgumentException(fun.getName() + " requires " + fun.arity() + " arguments but received " + args.length); } for (int i = 0; i < args.length; i++) { if (args[i] != null && (! fun.argumentType(i).isInstance(args[i]))) { throw new IllegalArgumentException(fun.getName() + "'s " + i + ". argument must be of " + fun.argumentType(i) + " but was " + args[i] + " of " + args[i].getClass()); } } return fun.invoke(args); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return invoke(method, args); } } private static class BindingsProxy extends FunctionProxy { private Bindings bindings; public BindingsProxy(Bindings bindings) { super(null); this.bindings = bindings; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object o = bindings.get(method.getName()); if (o == null) { return null; } if (! (o instanceof Function)) { throw new IllegalArgumentException(o + " is not a Function"); } fun = (Function)o; return invoke(method, args); } } private ClassLoader cl; public void setClassLoader(ClassLoader cl) { this.cl = cl; } public Object parse(String source, Class klass, IDataParserContext context) throws XSWTException { InvocationHandler handler = null; Bindings bindings = null; try { bindings = (Bindings)context.parse(source, Bindings.class); } catch (XSWTException e) { } if (bindings != null) { handler = new BindingsProxy(bindings); } else { Function fun = null; try { fun = (Function)context.parse(source, Function.class); } catch (XSWTException e) { } if (fun != null) { handler = new FunctionProxy(fun); } } if (handler == null) { return null; } ClassLoader cl = this.cl != null ? this.cl : getClass().getClassLoader(); return Proxy.newProxyInstance(cl, new Class[]{klass}, handler); } }