mirror of git://gcc.gnu.org/git/gcc.git
AnnotationInvocationHandler.java: Generify in a few places.
2007-03-02 Andrew Haley <aph@redhat.com> * 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. From-SVN: r122483
This commit is contained in:
parent
debac9f40d
commit
0618281a42
|
@ -1,3 +1,18 @@
|
||||||
|
2007-03-02 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
|
* 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 <aph@redhat.com>
|
2007-03-02 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
* sun/reflect/annotation/AnnotationInvocationHandler.java:
|
* sun/reflect/annotation/AnnotationInvocationHandler.java:
|
||||||
|
|
|
@ -7194,7 +7194,7 @@ sun/reflect/Reflection.java
|
||||||
|
|
||||||
sun_reflect_header_files = $(patsubst %.java,%.h,$(sun_reflect_source_files))
|
sun_reflect_header_files = $(patsubst %.java,%.h,$(sun_reflect_source_files))
|
||||||
sun_reflect_annotation_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/AnnotationParser.java \
|
||||||
classpath/sun/reflect/annotation/AnnotationType.java \
|
classpath/sun/reflect/annotation/AnnotationType.java \
|
||||||
classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
|
classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
|
||||||
|
|
Binary file not shown.
|
@ -8373,7 +8373,7 @@ sun/reflect.list: $(sun_reflect_source_files)
|
||||||
|
|
||||||
|
|
||||||
sun_reflect_annotation_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/AnnotationParser.java \
|
||||||
classpath/sun/reflect/annotation/AnnotationType.java \
|
classpath/sun/reflect/annotation/AnnotationType.java \
|
||||||
classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
|
classpath/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
|
||||||
|
|
|
@ -29,19 +29,19 @@ class sun::reflect::annotation::AnnotationInvocationHandler : public ::java::lan
|
||||||
public:
|
public:
|
||||||
AnnotationInvocationHandler(::java::lang::Class *, ::java::util::Map *);
|
AnnotationInvocationHandler(::java::lang::Class *, ::java::util::Map *);
|
||||||
static ::java::lang::annotation::Annotation * create(::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:
|
private:
|
||||||
static jboolean deepEquals(::java::lang::Object *, ::java::lang::Object *);
|
static jboolean deepEquals(::java::lang::Object *, ::java::lang::Object *);
|
||||||
static jint deepHashCode(::java::lang::Object *);
|
static jint deepHashCode(::java::lang::Object *);
|
||||||
public:
|
public:
|
||||||
static jint hashCode(::java::lang::Class *, ::java::util::Map *);
|
jint hashCode();
|
||||||
private:
|
private:
|
||||||
static ::java::lang::String * deepToString(::java::lang::Object *);
|
static ::java::lang::String * deepToString(::java::lang::Object *);
|
||||||
public:
|
public:
|
||||||
static ::java::lang::String * toString(::java::lang::Class *, ::java::util::Map *);
|
::java::lang::String * toString();
|
||||||
private:
|
private:
|
||||||
static ::java::lang::Class * getBoxedReturnType(::java::lang::reflect::Method *);
|
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:
|
public:
|
||||||
::java::lang::Object * invoke(::java::lang::Object *, ::java::lang::reflect::Method *, JArray< ::java::lang::Object * > *);
|
::java::lang::Object * invoke(::java::lang::Object *, ::java::lang::reflect::Method *, JArray< ::java::lang::Object * > *);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* sun.reflect.annotation.AnnotationInvocationHandler
|
/* sun.reflect.annotation.AnnotationInvocationHandler
|
||||||
Copyright (C) 2006
|
Copyright (C) 2006, 2007
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
@ -43,9 +43,9 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.AnnotationTypeMismatchException;
|
import java.lang.annotation.AnnotationTypeMismatchException;
|
||||||
import java.lang.annotation.IncompleteAnnotationException;
|
import java.lang.annotation.IncompleteAnnotationException;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -62,21 +62,21 @@ public final class AnnotationInvocationHandler
|
||||||
implements InvocationHandler, Serializable
|
implements InvocationHandler, Serializable
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 6182022883658399397L;
|
private static final long serialVersionUID = 6182022883658399397L;
|
||||||
private final Class type;
|
private final Class<? extends Annotation> type;
|
||||||
private final Map memberValues;
|
private final Map<String, ?> memberValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new invocation handler for an annotation proxy.
|
* Construct a new invocation handler for an annotation proxy.
|
||||||
* Note that the VM is responsible for filling the memberValues map
|
* Note that the VM is responsible for filling the memberValues map
|
||||||
* with the default values of all the annotation members.
|
* with the default values of all the annotation members.
|
||||||
*/
|
*/
|
||||||
public AnnotationInvocationHandler(Class type, Map memberValues)
|
public AnnotationInvocationHandler(Class<? extends Annotation> type, Map memberValues)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.memberValues = memberValues;
|
this.memberValues = (Map<String, ?>)memberValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Annotation create(Class type, Map memberValues)
|
public static Annotation create(Class<? extends Annotation> type, Map memberValues)
|
||||||
{
|
{
|
||||||
for (Method m : type.getDeclaredMethods())
|
for (Method m : type.getDeclaredMethods())
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,7 @@ public final class AnnotationInvocationHandler
|
||||||
* (can) use different representations of annotations that reuse this
|
* (can) use different representations of annotations that reuse this
|
||||||
* method.
|
* method.
|
||||||
*/
|
*/
|
||||||
public static boolean equals(Class type, Map memberValues, Object other)
|
public boolean equals(Object proxy, Object other)
|
||||||
{
|
{
|
||||||
if (type.isInstance(other))
|
if (type.isInstance(other))
|
||||||
{
|
{
|
||||||
|
@ -118,8 +118,12 @@ public final class AnnotationInvocationHandler
|
||||||
for (int i = 0; i < methods.length; i++)
|
for (int i = 0; i < methods.length; i++)
|
||||||
{
|
{
|
||||||
String key = methods[i].getName();
|
String key = methods[i].getName();
|
||||||
Object val = methods[i].invoke(other, new Object[0]);
|
Object val = methods[i].invoke(other, (Object[])null);
|
||||||
if (! deepEquals(memberValues.get(key), val))
|
Object thisVal
|
||||||
|
= invoke(proxy,
|
||||||
|
methods[i],
|
||||||
|
(Object[])null);
|
||||||
|
if (! deepEquals(thisVal, val))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -127,11 +131,7 @@ public final class AnnotationInvocationHandler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException _)
|
catch (Throwable _)
|
||||||
{
|
|
||||||
// Ignore exception, like the JDK
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException _)
|
|
||||||
{
|
{
|
||||||
// Ignore exception, like the JDK
|
// Ignore exception, like the JDK
|
||||||
}
|
}
|
||||||
|
@ -217,45 +217,30 @@ public final class AnnotationInvocationHandler
|
||||||
* (can) use different representations of annotations that reuse this
|
* (can) use different representations of annotations that reuse this
|
||||||
* method.
|
* method.
|
||||||
*/
|
*/
|
||||||
public static int hashCode(Class type, Map memberValues)
|
public int hashCode()
|
||||||
{
|
{
|
||||||
int h = 0;
|
int h = 0;
|
||||||
Iterator iter = memberValues.keySet().iterator();
|
Iterator iter = memberValues.keySet().iterator();
|
||||||
while (iter.hasNext())
|
while (iter.hasNext())
|
||||||
{
|
{
|
||||||
Object key = iter.next();
|
Object key = iter.next();
|
||||||
Object val = memberValues.get(key);
|
try
|
||||||
|
{
|
||||||
|
Object val
|
||||||
|
= invoke(null,
|
||||||
|
type.getDeclaredMethod((String)key, (Class[])null),
|
||||||
|
(Object[])null);
|
||||||
h += deepHashCode(val) ^ 127 * key.hashCode();
|
h += deepHashCode(val) ^ 127 * key.hashCode();
|
||||||
}
|
}
|
||||||
|
catch (Throwable _)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String deepToString(Object obj)
|
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[])
|
if (obj instanceof Object[])
|
||||||
return Arrays.toString((Object[]) obj);
|
return Arrays.toString((Object[]) obj);
|
||||||
|
|
||||||
|
@ -267,7 +252,7 @@ public final class AnnotationInvocationHandler
|
||||||
* (can) use different representations of annotations that reuse this
|
* (can) use different representations of annotations that reuse this
|
||||||
* method.
|
* method.
|
||||||
*/
|
*/
|
||||||
public static String toString(Class type, Map memberValues)
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append('@').append(type.getName()).append('(');
|
sb.append('@').append(type.getName()).append('(');
|
||||||
|
@ -284,6 +269,7 @@ public final class AnnotationInvocationHandler
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Class getBoxedReturnType(Method method)
|
private static Class getBoxedReturnType(Method method)
|
||||||
{
|
{
|
||||||
Class returnType = method.getReturnType();
|
Class returnType = method.getReturnType();
|
||||||
|
@ -315,51 +301,106 @@ public final class AnnotationInvocationHandler
|
||||||
return returnType;
|
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[])
|
if (! val.getClass().isArray())
|
||||||
return ((boolean[]) obj).clone();
|
return val;
|
||||||
|
|
||||||
if (obj instanceof byte[])
|
Object[] srcArray = (Object[])val;
|
||||||
return ((byte[]) obj).clone();
|
final int len = srcArray.length;
|
||||||
|
|
||||||
if (obj instanceof char[])
|
if (dstType.getComponentType().isPrimitive())
|
||||||
return ((char[]) obj).clone();
|
{
|
||||||
|
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[])
|
if (dstType == byte[].class)
|
||||||
return ((short[]) obj).clone();
|
{
|
||||||
|
byte[] dst = new byte[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
dst[i] = (Byte)srcArray[i];
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj instanceof int[])
|
if (dstType == char[].class)
|
||||||
return ((int[]) obj).clone();
|
{
|
||||||
|
char[] dst = new char[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
dst[i] = (Character)srcArray[i];
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj instanceof float[])
|
if (dstType == short[].class)
|
||||||
return ((float[]) obj).clone();
|
{
|
||||||
|
short[] dst = new short[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
dst[i] = (Short)srcArray[i];
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj instanceof long[])
|
if (dstType == int[].class)
|
||||||
return ((long[]) obj).clone();
|
{
|
||||||
|
int[] dst = new int[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
dst[i] = (Integer)srcArray[i];
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj instanceof double[])
|
if (dstType == long[].class)
|
||||||
return ((double[]) obj).clone();
|
{
|
||||||
|
long[] dst = new long[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
dst[i] = (Long)srcArray[i];
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj instanceof Object[])
|
if (dstType == float[].class)
|
||||||
return ((Object[]) obj).clone();
|
{
|
||||||
|
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)
|
public Object invoke(Object proxy, Method method, Object[] args)
|
||||||
throws Throwable
|
throws Throwable
|
||||||
{
|
{
|
||||||
String methodName = method.getName().intern();
|
String methodName = method.getName().intern();
|
||||||
|
|
||||||
if (args == null || args.length == 0)
|
if (args == null || args.length == 0)
|
||||||
{
|
{
|
||||||
if (methodName == "toString")
|
if (methodName == "toString")
|
||||||
{
|
{
|
||||||
return toString(type, memberValues);
|
return toString();
|
||||||
}
|
}
|
||||||
else if (methodName == "hashCode")
|
else if (methodName == "hashCode")
|
||||||
{
|
{
|
||||||
return Integer.valueOf(hashCode(type, memberValues));
|
return Integer.valueOf(hashCode());
|
||||||
}
|
}
|
||||||
else if (methodName == "annotationType")
|
else if (methodName == "annotationType")
|
||||||
{
|
{
|
||||||
|
@ -372,15 +413,19 @@ public final class AnnotationInvocationHandler
|
||||||
{
|
{
|
||||||
throw new IncompleteAnnotationException(type, methodName);
|
throw new IncompleteAnnotationException(type, methodName);
|
||||||
}
|
}
|
||||||
if (! getBoxedReturnType(method).isInstance(val))
|
try
|
||||||
{
|
{
|
||||||
throw new AnnotationTypeMismatchException(method,
|
|
||||||
val.getClass().getName());
|
|
||||||
}
|
|
||||||
if (val.getClass().isArray())
|
if (val.getClass().isArray())
|
||||||
{
|
val = coerce((Object[])val, method.getReturnType());
|
||||||
val = arrayClone(val);
|
|
||||||
}
|
}
|
||||||
|
catch (ArrayStoreException _)
|
||||||
|
{
|
||||||
|
throw new AnnotationTypeMismatchException
|
||||||
|
(method, val.getClass().getName());
|
||||||
|
}
|
||||||
|
if (! getBoxedReturnType(method).isInstance(val))
|
||||||
|
throw (new AnnotationTypeMismatchException
|
||||||
|
(method, val.getClass().getName()));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,7 +433,7 @@ public final class AnnotationInvocationHandler
|
||||||
{
|
{
|
||||||
if (methodName == "equals")
|
if (methodName == "equals")
|
||||||
{
|
{
|
||||||
return Boolean.valueOf(equals(type, memberValues, args[0]));
|
return Boolean.valueOf(equals(proxy, args[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InternalError("Invalid annotation proxy");
|
throw new InternalError("Invalid annotation proxy");
|
||||||
|
|
Loading…
Reference in New Issue