| 68 | 1 package fschmidt.util.java; | 
|  | 2 | 
|  | 3 import java.lang.reflect.Method; | 
|  | 4 import java.util.Arrays; | 
|  | 5 import java.util.HashMap; | 
|  | 6 import java.util.Map; | 
|  | 7 import java.util.WeakHashMap; | 
|  | 8 | 
|  | 9 | 
|  | 10 public final class ClassUtils { | 
|  | 11 | 
|  | 12 	private ClassUtils() {}  // never | 
|  | 13 | 
|  | 14 	private static final class Key { | 
|  | 15 		private final String name; | 
|  | 16 		private final Class[] parameterTypes; | 
|  | 17 | 
|  | 18 		private Key(Method m) { | 
|  | 19 			this(m.getName(),m.getParameterTypes()); | 
|  | 20 		} | 
|  | 21 | 
|  | 22 		private Key(String name,Class[] parameterTypes) { | 
|  | 23 			this.name = name; | 
|  | 24 			this.parameterTypes = parameterTypes; | 
|  | 25 		} | 
|  | 26 | 
|  | 27 		public boolean equals(Object obj) { | 
|  | 28 			if( !(obj instanceof Key) ) | 
|  | 29 				return false; | 
|  | 30 			Key key = (Key)obj; | 
|  | 31 			return key.name.equals(name) && Arrays.equals(key.parameterTypes,parameterTypes); | 
|  | 32 		} | 
|  | 33 | 
|  | 34 		public int hashCode() { | 
|  | 35 			return name.hashCode()+31*Arrays.hashCode(parameterTypes); | 
|  | 36 		} | 
|  | 37 	} | 
|  | 38 | 
|  | 39 	private static final Map<Class,FutureValue<Map<Key,Method>>> cache = new WeakHashMap<Class,FutureValue<Map<Key,Method>>>(); | 
|  | 40 | 
|  | 41 	// return null if not found | 
|  | 42 	public static Method getMethod(final Class cls,String name,Class... parameterTypes) { | 
|  | 43 		FutureValue<Map<Key,Method>> ft; | 
|  | 44 		synchronized(cache) { | 
|  | 45 			ft = cache.get(cls); | 
|  | 46 			if( ft==null ) { | 
|  | 47 				ft = new FutureValue<Map<Key,Method>>() { | 
|  | 48 					protected Map<Key,Method> compute() { | 
|  | 49 						Map<Key,Method> map = new HashMap<Key,Method>(); | 
|  | 50 						for( Method m : cls.getMethods() ) { | 
|  | 51 							Method m2 = map.put(new Key(m),m); | 
|  | 52 							if( m2 != null ) | 
|  | 53 								throw new RuntimeException("duplicate methods "+m+" and "+m2); | 
|  | 54 						} | 
|  | 55 						return map; | 
|  | 56 					} | 
|  | 57 				}; | 
|  | 58 				cache.put(cls,ft); | 
|  | 59 			} | 
|  | 60 		} | 
|  | 61 		Key key = new Key(name,parameterTypes); | 
|  | 62 		return ft.get().get(key); | 
|  | 63 	} | 
|  | 64 | 
|  | 65 } |