Merge changes from topic 'reflection_1_8'
* changes:
Revert "Revert "reflection: Add new AnnotatedElement 1.8 methods.""
reflect: Remove illegal invoke-direct to Proxy private method
diff --git a/luni/src/main/java/libcore/reflect/AnnotatedElements.java b/luni/src/main/java/libcore/reflect/AnnotatedElements.java
new file mode 100644
index 0000000..2fe2d2b
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/AnnotatedElements.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.reflect;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.IncompleteAnnotationException;
+import java.lang.annotation.Repeatable;
+import java.lang.reflect.*;
+import java.util.ArrayList;
+
+/**
+ * Implementation of {@link AnnotatedElement}'s 1.8 methods.
+ *
+ * <p>This implementation is shared between all the classes implementing {@link AnnotatedElement},
+ * avoiding code duplication.</p>
+ *
+ * @hide
+ */
+public final class AnnotatedElements {
+ /**
+ * Default implementation for {@link AnnotatedElement#getDeclaredAnnotation}.
+ *
+ * @return Directly present annotation of type {@code annotationClass} for {@code element},
+ * or {@code null} if none was found.
+ */
+ public static <T extends Annotation> T getDeclaredAnnotation(AnnotatedElement element,
+ Class<T> annotationClass) {
+ if (annotationClass == null) {
+ throw new NullPointerException("annotationClass");
+ }
+
+ Annotation[] annotations = element.getDeclaredAnnotations();
+
+ // Safeguard: getDeclaredAnnotations should never return null.
+ if (annotations == null) {
+ return null;
+ }
+
+ // The annotation might be directly present:
+ // Return the first (and only) annotation whose class matches annotationClass.
+ for (int i = 0; i < annotations.length; ++i) {
+ if (annotationClass.isInstance(annotations[i])) {
+ return (T)annotations[i]; // Safe because of above guard.
+ }
+ }
+
+ // The annotation was *not* directly present:
+ // If the array was empty, or we found no matches, return null.
+ return null;
+ }
+
+ /**
+ * Default implementation for {@link AnnotatedElement#getDeclaredAnnotationsByType}.
+ *
+ * @return Directly/indirectly present list of annotations of type {@code annotationClass} for
+ * {@code element}, or an empty array if none were found.
+ */
+ public static <T extends Annotation> T[] getDeclaredAnnotationsByType(AnnotatedElement element,
+ Class<T> annotationClass) {
+ if (annotationClass == null) {
+ throw new NullPointerException("annotationClass");
+ }
+
+ Annotation[] annotations = element.getDeclaredAnnotations();
+
+ // Store a list of repeatable annotations that have been extracted from their container.
+ ArrayList<T> unfoldedAnnotations = new ArrayList<T>();
+
+ Class<? extends Annotation> repeatableAnnotationClass =
+ getRepeatableAnnotationContainerClassFor(annotationClass);
+
+ for (int i = 0; i < annotations.length; ++i) {
+ if (annotationClass.isInstance(annotations[i])) {
+ // Is it directly present?
+ unfoldedAnnotations.add((T)annotations[i]); // Safe, guarded by above check.
+ } else if (repeatableAnnotationClass != null &&
+ repeatableAnnotationClass.isInstance(annotations[i])) {
+ // Is it repeatably (indirectly) present?
+ insertAnnotationValues(annotations[i], annotationClass, unfoldedAnnotations);
+ }
+ }
+
+ return unfoldedAnnotations.toArray((T[])Array.newInstance(annotationClass, 0));
+ }
+
+ /**
+ * Extracts annotations from a container annotation and inserts them into a list.
+ *
+ * <p>
+ * Given a complex annotation "annotation", it should have a "T[] value()" method on it.
+ * Call that method and add all of the nested annotations into unfoldedAnnotations list.
+ * </p>
+ */
+ private static <T extends Annotation> void insertAnnotationValues(Annotation annotation,
+ Class<T> annotationClass, ArrayList<T> unfoldedAnnotations) {
+ // annotation is a complex annotation which has elements of instance annotationClass
+ // (whose static type is T).
+ //
+ // @interface SomeName { <--- = annotation.getClass()
+ // ...
+ // T[] value(); <--- T.class == annotationClass
+ // }
+ //
+ // Use reflection to access these values.
+ Class<T[]> annotationArrayClass =
+ (Class<T[]>)((T[])Array.newInstance(annotationClass, 0)).getClass();
+
+ Method valuesMethod;
+ try {
+ valuesMethod = annotation.getClass().getDeclaredMethod("value");
+ // This will always succeed unless the annotation and its repeatable annotation class were
+ // recompiled separately, then this is a binary incompatibility error.
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError("annotation container = " + annotation +
+ "annotation element class = " + annotationClass + "; missing value() method");
+ } catch (SecurityException e) {
+ throw new IncompleteAnnotationException(annotation.getClass(), "value");
+ }
+
+ // Ensure that value() returns a T[]
+ if (!valuesMethod.getReturnType().isArray()) {
+ throw new AssertionError("annotation container = " + annotation +
+ "annotation element class = " + annotationClass + "; value() doesn't return array");
+ }
+
+ // Ensure that the T[] value() is actually the correct type (T==annotationClass).
+ if (!annotationClass.equals(valuesMethod.getReturnType().getComponentType())) {
+ throw new AssertionError("annotation container = " + annotation +
+ "annotation element class = " + annotationClass + "; value() returns incorrect type");
+ }
+
+ // Append those values into the existing list.
+ T[] nestedAnnotations;
+ try {
+ nestedAnnotations = (T[])valuesMethod.invoke(annotation); // Safe because of #getMethod.
+ } catch (IllegalAccessException|InvocationTargetException e) {
+ throw new AssertionError(e);
+ }
+
+ for (int i = 0; i < nestedAnnotations.length; ++i) {
+ unfoldedAnnotations.add(nestedAnnotations[i]);
+ }
+ }
+
+ /**
+ * Find the {@code \@Repeatable} container annotation class for an annotation class, or
+ * {@code null}.
+ *
+ * <p>
+ * Given:
+ *
+ * <code>
+ * @Repeatable(X.class)
+ * @interface SomeName { <--- = annotationClass
+ * }...
+ * </code>
+ *
+ * <p>
+ * Returns {@code X.class}
+ *
+ * Otherwise if there was no {@code \@Repeatable} annotation, return {@code null}.
+ * </p>
+ */
+ private static <T extends Annotation> Class<? extends Annotation>
+ getRepeatableAnnotationContainerClassFor(Class<T> annotationClass) {
+
+ Repeatable repeatableAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
+ return (repeatableAnnotation == null) ? null : repeatableAnnotation.value();
+ }
+
+ /**
+ * Default implementation of {@link AnnotatedElement#getAnnotationsByType}.
+ *
+ * <p>
+ * This method does not handle inherited annotations and is
+ * intended for use for {@code Method}, {@code Field}, {@code Package}.
+ * The {@link Class#getAnnotationsByType} is implemented explicitly.
+ * </p>
+ *
+ * @return Associated annotations of type {@code annotationClass} for {@code element}.
+ */
+ public static <T extends Annotation> T[] getAnnotationsByType(AnnotatedElement element,
+ Class<T> annotationClass) {
+ if (annotationClass == null) {
+ throw new NullPointerException("annotationClass");
+ }
+
+ // Find any associated annotations [directly or repeatably (indirectly) present on this class].
+ T[] annotations = element.getDeclaredAnnotationsByType(annotationClass);
+ if (annotations == null) {
+ throw new AssertionError("annotations must not be null"); // Internal error.
+ }
+
+ // If nothing was found, we would look for associated annotations recursively up to the root
+ // class. However this can only happen if AnnotatedElement is a Class, which is handled
+ // in the Class override of this method.
+ return annotations;
+ }
+
+ private AnnotatedElements() {
+ throw new AssertionError("Instances of AnnotatedElements not allowed");
+ }
+}
+
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index a912d90..0c5502b 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -381,6 +381,7 @@
luni/src/main/java/libcore/net/event/NetworkEventListener.java \
luni/src/main/java/libcore/net/http/HttpDate.java \
luni/src/main/java/libcore/net/http/ResponseUtils.java \
+ luni/src/main/java/libcore/reflect/AnnotatedElements.java \
luni/src/main/java/libcore/reflect/AnnotationAccess.java \
luni/src/main/java/libcore/reflect/AnnotationFactory.java \
luni/src/main/java/libcore/reflect/AnnotationMember.java \
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index e952660..de378da 100755
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -65,6 +65,7 @@
import java.lang.reflect.AccessibleObject;
import com.android.dex.Dex;
import dalvik.system.VMStack;
+import libcore.reflect.AnnotatedElements;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.InternalNames;
import libcore.reflect.GenericSignatureParser;
@@ -2465,9 +2466,56 @@
@Override public native Annotation[] getDeclaredAnnotations();
/**
- * Returns the annotation if it exists.
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
*/
- private native <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
+ @Override
+ public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+ return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ // Find any associated annotations [directly or repeatably (indirectly) present on this].
+ T[] annotations = AnnotatedElements.getAnnotationsByType(this, annotationClass);
+
+ if (annotations.length != 0) {
+ return annotations;
+ }
+
+ // Nothing was found, attempt looking for associated annotations recursively up to the root
+ // class if and only if:
+ // * The annotation class was marked with @Inherited.
+ //
+ // Inherited annotations are not coalesced into a single set: the first declaration found is
+ // returned.
+
+ if (annotationClass.isDeclaredAnnotationPresent(Inherited.class)) {
+ Class<?> superClass = getSuperclass(); // Returns null if klass's base is Object.
+
+ if (superClass != null) {
+ return superClass.getAnnotationsByType(annotationClass);
+ }
+ }
+
+ // Annotated was not marked with @Inherited, or no superclass.
+ return (T[]) Array.newInstance(annotationClass, 0); // Safe by construction.
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public native <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
/**
* Returns true if the annotation exists.
diff --git a/ojluni/src/main/java/java/lang/Package.java b/ojluni/src/main/java/java/lang/Package.java
index 0b1a036..4fbbf29 100755
--- a/ojluni/src/main/java/java/lang/Package.java
+++ b/ojluni/src/main/java/java/lang/Package.java
@@ -53,6 +53,8 @@
import sun.reflect.CallerSensitive;
import dalvik.system.VMStack;
+import libcore.reflect.AnnotatedElements;
+
/**
* {@code Package} objects contain version information
* about the implementation and specification of a Java package.
@@ -413,6 +415,35 @@
}
/**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+ return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ return AnnotatedElements.getAnnotationsByType(this, annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
+ return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
+ }
+ /**
* Construct a package instance with the specified version
* information.
* @param pkgName the name of the package
diff --git a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
index b7ace79..68c8555 100755
--- a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -30,6 +30,8 @@
import sun.reflect.Reflection;
import java.lang.annotation.Annotation;
+import libcore.reflect.AnnotatedElements;
+
/**
* The AccessibleObject class is the base class for Field, Method and
* Constructor objects. It provides the ability to flag a reflected
@@ -193,4 +195,34 @@
public Annotation[] getDeclaredAnnotations() {
throw new AssertionError("All subclasses should override this method");
}
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+ return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ return AnnotatedElements.getAnnotationsByType(this, annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ * @hide 1.8
+ */
+ @Override
+ public <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) {
+ return AnnotatedElements.getDeclaredAnnotation(this, annotationClass);
+ }
}
diff --git a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
index dc24483..b67b801 100755
--- a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2016 The Android Open Source Project
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -26,6 +27,7 @@
package java.lang.reflect;
import java.lang.annotation.Annotation;
+// import libcore.reflect.AnnotatedElements;
/**
* Represents an annotated element of the program currently running in this
@@ -71,7 +73,8 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.5
*/
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
+ /*default*/ boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
+ // { return getAnnotation(annotationClass) != null; }
/**
* Returns this element's annotation for the specified type if
@@ -109,4 +112,34 @@
* @since 1.5
*/
Annotation[] getDeclaredAnnotations();
+
+ /**
+ * Returns a directly-present annotation on {@code this} element, whose class is
+ * {@code annotationClass}, or {@code null} if nothing was found.
+ *
+ * @since 1.8
+ * @hide 1.8
+ */
+ /*default*/ <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass);
+ // { return AnnotatedElements.getDeclaredAnnotation(this, annotationClass); }
+
+ /**
+ * Returns a directly or indirectly present list of annotations on {@code this} element,
+ * whose class is {@code annotationClass}, or an empty array if nothing was found.
+ *
+ * @since 1.8
+ * @hide 1.8
+ */
+ /*default*/ <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
+ // { return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass); }
+
+ /**
+ * Returns an associated list of annotations on {@code this} element,
+ * whose class is {@code annotationClass}, or an empty array if nothing was found.
+ *
+ * @since 1.8
+ * @hide 1.8
+ */
+ /*default*/ <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
+ // { return AnnotatedElements.getAnnotationsByType(this, annotationClass); }
}
diff --git a/ojluni/src/main/java/java/lang/reflect/Proxy.java b/ojluni/src/main/java/java/lang/reflect/Proxy.java
index 3d27fc1..2f9d732 100755
--- a/ojluni/src/main/java/java/lang/reflect/Proxy.java
+++ b/ojluni/src/main/java/java/lang/reflect/Proxy.java
@@ -299,7 +299,6 @@
* @param h the invocation handler for this proxy instance
*/
protected Proxy(InvocationHandler h) {
- doNewInstanceCheck();
this.h = h;
}