/** Copyright 2008, 2009 Mark Hooijkaas This file is part of the Caas tool. The Caas tool is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The Caas tool is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Caas tool. If not, see <http://www.gnu.org/licenses/>. */ package org.kisst.util; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectionUtil { public static Constructor<?> getConstructor(String classname, Class<?>[] signature) { try { Class<?> c = Class.forName(classname); return getConstructor(c, signature); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Field getField(Class<?> cls, String name) { try { return cls.getDeclaredField(name); } catch (SecurityException e) {throw new RuntimeException(e); } catch (NoSuchFieldException e) { return null; } } public static Method getMethod(Class<?> cls, String name, Class<?>[] signature) { Method[] metharr = cls.getDeclaredMethods(); for (Method meth :metharr) { if (name.equals(meth.getName())) { Class<?>[] paramtypes = meth.getParameterTypes(); if (java.util.Arrays.equals(signature, paramtypes)) return meth; } } return null; } public static Constructor<?> getFirstCompatibleConstructor(Class<?> cls, Class<?>[] signature) { Constructor<?>[] consarr = cls.getDeclaredConstructors(); for (int i=0; i<consarr.length; i++) { Class<?>[] paramtypes = consarr[i].getParameterTypes(); if (paramtypes.length!=signature.length) continue; boolean compatible=true; for (int j=0; j<signature.length; j++) { if (!signature[j].isAssignableFrom(paramtypes[j])) compatible=false; } if (compatible) return consarr[i]; } return null; } public static Constructor<?> getConstructor(Class<?> cls, Class<?>[] signature) { Constructor<?>[] consarr = cls.getDeclaredConstructors(); for (int i=0; i<consarr.length; i++) { Class<?>[] paramtypes = consarr[i].getParameterTypes(); if (java.util.Arrays.equals(signature, paramtypes)) return consarr[i]; } return null; } public static Object invoke(Object o, Method m, Object[] args) { try { m.setAccessible(true); return m.invoke(o, args); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) {e.getCause().printStackTrace(); throw new RuntimeException(e.getCause()); } } public static Object invoke(Object o, String name, Object[] args) { return invoke(o.getClass(),o, name, args); } public static Object invoke(Class<?> c, Object o, String name, Object[] args) { try { return invoke(o, c.getDeclaredMethod(name, getSignature(args)), args); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } private static Class<?>[] getSignature(Object[] args) { Class<?>[] signature=new Class[args.length]; for (int i=0; i<args.length; i++) signature[i]=args[i].getClass(); return signature; } public static Class<?> findClass(String name) { try { return Class.forName(name); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Object createObject(String classname, Object[] args) { return createObject(findClass(classname), args); } public static Object createObject(Class<?> c, Object[] args) { Constructor<?> cons= getFirstCompatibleConstructor(c,getSignature(args)); return createObject(cons,args); } public static Object createObject(Constructor<?> cons, Object[] args) { try { cons.setAccessible(true); return cons.newInstance(args); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } public static Object createObject(String classname) { return createObject(findClass(classname)); } public static Object createObject(Class<?> c) { try { return c.newInstance(); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } } public static String toString(Object obj, String... fields) { StringBuilder result= new StringBuilder(obj.getClass().getSimpleName()+"("); String sep=""; if (fields!=null) for (String field: fields) { if (field!=null) { result.append(sep); result.append(field); sep=","; } } result.append(")"); return result.toString(); } public static String toString(Object obj) { return toString(obj,0); } public static String toString(Object obj, int depth) { // TODO: special support for Hashmaps? Lists, etc. Better indentation, newline support etc? if (obj==null) return "null"; if (obj instanceof String) return "\""+obj+"\""; // TODO: escape quotes? if (obj instanceof Number) return obj.toString(); if (obj instanceof Boolean) return obj.toString(); if (depth<0) return obj.getClass().getSimpleName()+"()"; depth--; StringBuilder result= new StringBuilder(); result.append(obj.getClass().getSimpleName()+"("); String sep=""; for (Field field : obj.getClass().getFields()) { try { if (! Modifier.isStatic(field.getModifiers())) { result.append(sep+field.getName()+"="+toString(field.get(obj), depth)); sep=", "; } } catch (IllegalArgumentException e) { throw new RuntimeException(e);} catch (IllegalAccessException e) { throw new RuntimeException(e);} } result.append(")"); return result.toString(); } }