/** * Copyright (c) Rich Hickey. All rights reserved. * The use and distribution terms for this software are covered by the * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) * which can be found in the file epl-v10.html at the root of this distribution. * By using this software in any fashion, you are agreeing to be bound by * the terms of this license. * You must not remove this notice, or any other, from this software. **/ /* rich Oct 4, 2007 */ package clojure.lang; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyHandler implements InvocationHandler{ //method-name-string->fn final IPersistentMap fns; public ProxyHandler(IPersistentMap fns){ this.fns = fns; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ Class rt = method.getReturnType(); IFn fn = (IFn) fns.valAt(method.getName()); if(fn == null) { if(rt == Void.TYPE) return null; else if(method.getName().equals("equals")) { return proxy == args[0]; } else if(method.getName().equals("hashCode")) { return System.identityHashCode(proxy); } else if(method.getName().equals("toString")) { return "Proxy: " + System.identityHashCode(proxy); } throw new UnsupportedOperationException(); } Object ret = fn.applyTo(ArraySeq.create(args)); if(rt == Void.TYPE) return null; else if(rt.isPrimitive()) { if(rt == Character.TYPE) return ret; else if(rt == Integer.TYPE) return ((Number) ret).intValue(); else if(rt == Long.TYPE) return ((Number) ret).longValue(); else if(rt == Float.TYPE) return ((Number) ret).floatValue(); else if(rt == Double.TYPE) return ((Number) ret).doubleValue(); else if(rt == Boolean.TYPE && !(ret instanceof Boolean)) return ret == null ? Boolean.FALSE : Boolean.TRUE; else if(rt == Byte.TYPE) return (byte) ((Number) ret).intValue(); else if(rt == Short.TYPE) return (short) ((Number) ret).intValue(); } return ret; } }