diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 96cdf2dcbda..bddc9986302 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,18 @@ +2007-03-02 Andrew Haley + + * sun/reflect/annotation/AnnotationInvocationHandler.java: + Generify in a few places. + (equals): Rewrite to use invoke on local proxy. + (deepToString): Remove most of it. + (toString): Make nonstatic. + (arrayClone): Delete. + (coerce): New method. + (invoke): Rewrite to handle gcj's structures correctly. + * java/lang/natClass.cc (getDeclaredAnnotations): Fix test for + null loader. + * sources.am: Regenerate. + * Makefile.am: Likewise. + 2007-03-02 Andrew Haley * sun/reflect/annotation/AnnotationInvocationHandler.java: diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 96cd2d11bd7..99433510638 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -7194,7 +7194,7 @@ sun/reflect/Reflection.java sun_reflect_header_files = $(patsubst %.java,%.h,$(sun_reflect_source_files)) sun_reflect_annotation_source_files = \ -classpath/sun/reflect/annotation/AnnotationInvocationHandler.java \ +sun/reflect/annotation/AnnotationInvocationHandler.java \ classpath/sun/reflect/annotation/AnnotationParser.java \ classpath/sun/reflect/annotation/AnnotationType.java \ classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \ diff --git a/libjava/classpath/lib/sun/reflect/annotation/AnnotationInvocationHandler.class b/libjava/classpath/lib/sun/reflect/annotation/AnnotationInvocationHandler.class index e70c2bbcd7b..2e3036326cd 100644 Binary files a/libjava/classpath/lib/sun/reflect/annotation/AnnotationInvocationHandler.class and b/libjava/classpath/lib/sun/reflect/annotation/AnnotationInvocationHandler.class differ diff --git a/libjava/sources.am b/libjava/sources.am index 77e7796ff33..e9adc2178f7 100644 --- a/libjava/sources.am +++ b/libjava/sources.am @@ -8373,7 +8373,7 @@ sun/reflect.list: $(sun_reflect_source_files) sun_reflect_annotation_source_files = \ -classpath/sun/reflect/annotation/AnnotationInvocationHandler.java \ +sun/reflect/annotation/AnnotationInvocationHandler.java \ classpath/sun/reflect/annotation/AnnotationParser.java \ classpath/sun/reflect/annotation/AnnotationType.java \ classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \ diff --git a/libjava/sun/reflect/annotation/AnnotationInvocationHandler.h b/libjava/sun/reflect/annotation/AnnotationInvocationHandler.h index 0679e3c3fd5..356c8a029c8 100644 --- a/libjava/sun/reflect/annotation/AnnotationInvocationHandler.h +++ b/libjava/sun/reflect/annotation/AnnotationInvocationHandler.h @@ -29,19 +29,19 @@ class sun::reflect::annotation::AnnotationInvocationHandler : public ::java::lan public: AnnotationInvocationHandler(::java::lang::Class *, ::java::util::Map *); static ::java::lang::annotation::Annotation * create(::java::lang::Class *, ::java::util::Map *); - static jboolean equals(::java::lang::Class *, ::java::util::Map *, ::java::lang::Object *); + jboolean equals(::java::lang::Object *, ::java::lang::Object *); private: static jboolean deepEquals(::java::lang::Object *, ::java::lang::Object *); static jint deepHashCode(::java::lang::Object *); public: - static jint hashCode(::java::lang::Class *, ::java::util::Map *); + jint hashCode(); private: static ::java::lang::String * deepToString(::java::lang::Object *); public: - static ::java::lang::String * toString(::java::lang::Class *, ::java::util::Map *); + ::java::lang::String * toString(); private: static ::java::lang::Class * getBoxedReturnType(::java::lang::reflect::Method *); - ::java::lang::Object * arrayClone(::java::lang::Object *); + ::java::lang::Object * coerce(::java::lang::Object *, ::java::lang::Class *); public: ::java::lang::Object * invoke(::java::lang::Object *, ::java::lang::reflect::Method *, JArray< ::java::lang::Object * > *); private: diff --git a/libjava/sun/reflect/annotation/AnnotationInvocationHandler.java b/libjava/sun/reflect/annotation/AnnotationInvocationHandler.java index ccfe86039cc..f883faa16ac 100644 --- a/libjava/sun/reflect/annotation/AnnotationInvocationHandler.java +++ b/libjava/sun/reflect/annotation/AnnotationInvocationHandler.java @@ -1,5 +1,5 @@ /* sun.reflect.annotation.AnnotationInvocationHandler - Copyright (C) 2006 + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -8,7 +8,7 @@ GNU Classpath 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 2, or (at your option) any later version. - + GNU Classpath 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 @@ -43,9 +43,9 @@ import java.lang.annotation.Annotation; import java.lang.annotation.AnnotationTypeMismatchException; import java.lang.annotation.IncompleteAnnotationException; import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.lang.reflect.Array; import java.util.Arrays; import java.util.Iterator; import java.util.Map; @@ -62,21 +62,21 @@ public final class AnnotationInvocationHandler implements InvocationHandler, Serializable { private static final long serialVersionUID = 6182022883658399397L; - private final Class type; - private final Map memberValues; + private final Class type; + private final Map memberValues; /** * Construct a new invocation handler for an annotation proxy. * Note that the VM is responsible for filling the memberValues map * with the default values of all the annotation members. */ - public AnnotationInvocationHandler(Class type, Map memberValues) + public AnnotationInvocationHandler(Class type, Map memberValues) { this.type = type; - this.memberValues = memberValues; + this.memberValues = (Map)memberValues; } - public static Annotation create(Class type, Map memberValues) + public static Annotation create(Class type, Map memberValues) { for (Method m : type.getDeclaredMethods()) { @@ -106,7 +106,7 @@ public final class AnnotationInvocationHandler * (can) use different representations of annotations that reuse this * method. */ - public static boolean equals(Class type, Map memberValues, Object other) + public boolean equals(Object proxy, Object other) { if (type.isInstance(other)) { @@ -118,8 +118,12 @@ public final class AnnotationInvocationHandler for (int i = 0; i < methods.length; i++) { String key = methods[i].getName(); - Object val = methods[i].invoke(other, new Object[0]); - if (! deepEquals(memberValues.get(key), val)) + Object val = methods[i].invoke(other, (Object[])null); + Object thisVal + = invoke(proxy, + methods[i], + (Object[])null); + if (! deepEquals(thisVal, val)) { return false; } @@ -127,11 +131,7 @@ public final class AnnotationInvocationHandler return true; } } - catch (IllegalAccessException _) - { - // Ignore exception, like the JDK - } - catch (InvocationTargetException _) + catch (Throwable _) { // Ignore exception, like the JDK } @@ -217,45 +217,30 @@ public final class AnnotationInvocationHandler * (can) use different representations of annotations that reuse this * method. */ - public static int hashCode(Class type, Map memberValues) + public int hashCode() { int h = 0; Iterator iter = memberValues.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); - Object val = memberValues.get(key); - h += deepHashCode(val) ^ 127 * key.hashCode(); + try + { + Object val + = invoke(null, + type.getDeclaredMethod((String)key, (Class[])null), + (Object[])null); + h += deepHashCode(val) ^ 127 * key.hashCode(); + } + catch (Throwable _) + { + } } return h; } private static String deepToString(Object obj) { - if (obj instanceof boolean[]) - return Arrays.toString((boolean[]) obj); - - if (obj instanceof byte[]) - return Arrays.toString((byte[]) obj); - - if (obj instanceof char[]) - return Arrays.toString((char[]) obj); - - if (obj instanceof short[]) - return Arrays.toString((short[]) obj); - - if (obj instanceof int[]) - return Arrays.toString((int[]) obj); - - if (obj instanceof float[]) - return Arrays.toString((float[]) obj); - - if (obj instanceof long[]) - return Arrays.toString((long[]) obj); - - if (obj instanceof double[]) - return Arrays.toString((double[]) obj); - if (obj instanceof Object[]) return Arrays.toString((Object[]) obj); @@ -267,7 +252,7 @@ public final class AnnotationInvocationHandler * (can) use different representations of annotations that reuse this * method. */ - public static String toString(Class type, Map memberValues) + public String toString() { StringBuffer sb = new StringBuffer(); sb.append('@').append(type.getName()).append('('); @@ -284,6 +269,7 @@ public final class AnnotationInvocationHandler return sb.toString(); } + private static Class getBoxedReturnType(Method method) { Class returnType = method.getReturnType(); @@ -315,51 +301,106 @@ public final class AnnotationInvocationHandler return returnType; } - private Object arrayClone(Object obj) + // This is slightly awkward. When the value of an annotation is an + // array, libgcj constructs an Object[], but the value() method + // returns an arrays of the appropriate primitive type. We should + // perhaps save the resulting array rather than the Object[]. + + private Object coerce(Object val, Class dstType) + throws ArrayStoreException { - if (obj instanceof boolean[]) - return ((boolean[]) obj).clone(); + if (! val.getClass().isArray()) + return val; - if (obj instanceof byte[]) - return ((byte[]) obj).clone(); + Object[] srcArray = (Object[])val; + final int len = srcArray.length; - if (obj instanceof char[]) - return ((char[]) obj).clone(); + if (dstType.getComponentType().isPrimitive()) + { + if (dstType == boolean[].class) + { + boolean[] dst = new boolean[len]; + for (int i = 0; i < len; i++) + dst[i] = (Boolean)srcArray[i]; + return dst; + } - if (obj instanceof short[]) - return ((short[]) obj).clone(); + if (dstType == byte[].class) + { + byte[] dst = new byte[len]; + for (int i = 0; i < len; i++) + dst[i] = (Byte)srcArray[i]; + return dst; + } - if (obj instanceof int[]) - return ((int[]) obj).clone(); + if (dstType == char[].class) + { + char[] dst = new char[len]; + for (int i = 0; i < len; i++) + dst[i] = (Character)srcArray[i]; + return dst; + } - if (obj instanceof float[]) - return ((float[]) obj).clone(); + if (dstType == short[].class) + { + short[] dst = new short[len]; + for (int i = 0; i < len; i++) + dst[i] = (Short)srcArray[i]; + return dst; + } - if (obj instanceof long[]) - return ((long[]) obj).clone(); + if (dstType == int[].class) + { + int[] dst = new int[len]; + for (int i = 0; i < len; i++) + dst[i] = (Integer)srcArray[i]; + return dst; + } - if (obj instanceof double[]) - return ((double[]) obj).clone(); + if (dstType == long[].class) + { + long[] dst = new long[len]; + for (int i = 0; i < len; i++) + dst[i] = (Long)srcArray[i]; + return dst; + } - if (obj instanceof Object[]) - return ((Object[]) obj).clone(); + if (dstType == float[].class) + { + float[] dst = new float[len]; + for (int i = 0; i < len; i++) + dst[i] = (Float)srcArray[i]; + return dst; + } - return obj; + if (dstType == double[].class) + { + double[] dst = new double[len]; + for (int i = 0; i < len; i++) + dst[i] = (Double)srcArray[i]; + return dst; + } + } + + Object dst = Array.newInstance(dstType.getComponentType(), len); + System.arraycopy((Object)srcArray, 0, dst, 0, len); + return dst; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName().intern(); + if (args == null || args.length == 0) { if (methodName == "toString") { - return toString(type, memberValues); + return toString(); } else if (methodName == "hashCode") { - return Integer.valueOf(hashCode(type, memberValues)); + return Integer.valueOf(hashCode()); } else if (methodName == "annotationType") { @@ -372,15 +413,19 @@ public final class AnnotationInvocationHandler { throw new IncompleteAnnotationException(type, methodName); } + try + { + if (val.getClass().isArray()) + val = coerce((Object[])val, method.getReturnType()); + } + catch (ArrayStoreException _) + { + throw new AnnotationTypeMismatchException + (method, val.getClass().getName()); + } if (! getBoxedReturnType(method).isInstance(val)) - { - throw new AnnotationTypeMismatchException(method, - val.getClass().getName()); - } - if (val.getClass().isArray()) - { - val = arrayClone(val); - } + throw (new AnnotationTypeMismatchException + (method, val.getClass().getName())); return val; } } @@ -388,7 +433,7 @@ public final class AnnotationInvocationHandler { if (methodName == "equals") { - return Boolean.valueOf(equals(type, memberValues, args[0])); + return Boolean.valueOf(equals(proxy, args[0])); } } throw new InternalError("Invalid annotation proxy");