package xapi.reflect.impl; import xapi.annotation.inject.SingletonDefault; import xapi.reflect.service.ReflectionService; import xapi.util.X_Util; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; @SingletonDefault(implFor=ReflectionService.class) public class ReflectionServiceDefault implements ReflectionService{ @Override @SuppressWarnings("unchecked") public <T> T[] newArray(Class<T> classLit, int dimension) { return (T[])Array.newInstance(classLit, dimension); } @Override @SuppressWarnings("unchecked") public <T> T[][] newArray(Class<T> classLit, int dim1, int dim2) { return (T[][])Array.newInstance(classLit, dim1, dim2); } @Override @SuppressWarnings("unchecked") public <T> T[][][] newArray(Class<T> classLit, int dim1, int dim2, int dim3) { return (T[][][])Array.newInstance(classLit, dim1, dim2, dim3); } @Override public <T> Class<T> magicClass(Class<T> classLit) { return classLit; } @Override public Package getPackage(String parentName, ClassLoader cl) { Package pkg = Package.getPackage(parentName); if (pkg == null) { String pkgInfo = parentName.replace('.', '/')+"/package-info.class"; URL loc = cl.getResource(pkgInfo); if (loc != null) { try { cl.loadClass(parentName+".package-info"); pkg = Package.getPackage(parentName); } catch (ClassNotFoundException ignored) {} } } return pkg; } /** */ public Object invokeDefaultMethod(final Method method, final Object ... params) { // create a crappy proxy of the declaring interface of this method (if it's default, it's an interface / annotation) // this proxy will fail to invoke any non-default methods. If you need concrete methods, you need to use a real instance. final Object t = java.lang.reflect.Proxy.newProxyInstance(getClassLoader(), new Class<?>[]{method.getDeclaringClass()},new java.lang.reflect.InvocationHandler() { @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { return null; } }); return invokeDefaultMethod(t, method, params); } @Override public Object invokeDefaultMethod(Object instance, final Method method, final Object ... params) { try { // Use reflection on some reflection classes to get access to a Lookup object we aren't supposed to touch :-) // TODO: add proper security wrapper code final Field field = java.lang.invoke.MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); field.setAccessible(true); final java.lang.invoke.MethodHandles.Lookup lookup = (java.lang.invoke.MethodHandles.Lookup) field.get(null); final Object value = lookup .unreflectSpecial(method, method.getDeclaringClass()) .bindTo(instance) .invokeWithArguments(params); return value; } catch (Throwable e) { e.printStackTrace(); throw X_Util.rethrow(e); } } protected ClassLoader getClassLoader() { return Thread.currentThread().getContextClassLoader(); } @Override public Package getPackage(Object o) { return o.getClass().getPackage(); } }