RFR 8073056: Repeating annotations throws java.security.AccessControlException with a SecurityManager
Peter Levart
peter.levart at gmail.com
Thu Feb 26 22:04:15 UTC 2015
On 02/26/2015 10:27 PM, Peter Levart wrote:
>
> On 02/26/2015 05:34 PM, Mandy Chung wrote:
>>> The problem is with the default method
>>> AnnotatedElement::getDeclaredAnnotationsByType. If someone has an
>>> external implementation of AnnotatedElement (and one of the lessons
>>> from adding these methods in 8 was that there are other
>>> implementations) then if that external implementation haven’t added
>>> getDeclaredAnnotationsByType they will call into our
>>> AnnotationSupport. This is all fine if that external representation
>>> of AnnotatedElement uses our representation of Annotations, with
>>> Proxies and all. But I suspect that the conditions that would end up
>>> taking the non-proxy code path in the patch, will already fail in
>>> the check:
>>>
>>> AnnotationType annoType =
>>> AnnotationType.getInstance(containerClass);
>>> if (annoType == null)
>>> throw invalidContainerException(container, null);
>>>
>>> So what is the best thing to do here if the annotation is not Proxy
>>> based and is coming from an implementation of the AnnotatedElement
>>> interface that we don’t control and that is missing the methods
>>> added in 8?
>>
>> I did a quick search on my corpus and find only one reference to
>> sun.reflect.annotation.AnnotationType. Looks like external
>> implementation
>> doesn't get pass this.
>
> Now I'm missing something. Why would a custom non-Proxy based
> annotation not pass the above code? I don't see anything in
> AnnotationType implementation that would be dependent on annotation
> implementation to be a Proxy. AnnotationType only deals with the
> annotation type, which is an interface, not with implementation.
I verified this with the following code:
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
@CustomAnnTest.Containee("a")
@CustomAnnTest.Containee("b")
@CustomAnnTest.Containee("c")
public class CustomAnnTest {
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Container.class)
public @interface Containee {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
public @interface Container {
Containee[] value();
}
public static class MyElement implements AnnotatedElement {
@Override
public <T extends Annotation> T getAnnotation(Class<T>
annotationClass) {
for (Annotation ann : getDeclaredAnnotations()) {
if (ann.annotationType() == annotationClass) {
return annotationClass.cast(ann);
}
}
return null;
}
@Override
public Annotation[] getAnnotations() {
return getDeclaredAnnotations();
}
@Override
public Annotation[] getDeclaredAnnotations() {
return new Annotation[] {
new MyContainer(
new MyContainee("A"),
new MyContainee("B"),
new MyContainee("C")
)
};
}
static class MyContainee implements Containee {
final String value;
MyContainee(String value) {
this.value = value;
}
@Override
public String value() {
return value;
}
@Override
public Class<? extends Annotation> annotationType() {
return Containee.class;
}
@Override
public String toString() {
return "@" + annotationType().getName() + "(value=" +
value + ")";
}
}
static class MyContainer implements Container {
final Containee[] value;
MyContainer(Containee ... value) {
this.value = value;
}
@Override
public Containee[] value() {
return value;
}
@Override
public Class<? extends Annotation> annotationType() {
return Container.class;
}
@Override
public String toString() {
return "@" + annotationType().getName() + "(value=" +
Arrays.toString(value) + ")";
}
}
}
static void test(AnnotatedElement ae) {
System.out.println(ae + ":");
System.out.println(Arrays.toString(ae.getDeclaredAnnotations()));
System.out.println(ae.getAnnotation(Container.class));
System.out.println(ae.getAnnotation(Containee.class));
System.out.println(Arrays.toString(ae.getDeclaredAnnotationsByType(Containee.class)));
System.out.println();
}
public static void main(String[] args) {
test(CustomAnnTest.class);
test(new MyElement());
}
}
... it works without problems and prints the expected:
class jdk.test.CustomAnnTest:
[@jdk.test.CustomAnnTest$Container(value=[@jdk.test.CustomAnnTest$Containee(value=a),
@jdk.test.CustomAnnTest$Containee(value=b),
@jdk.test.CustomAnnTest$Containee(value=c)])]
@jdk.test.CustomAnnTest$Container(value=[@jdk.test.CustomAnnTest$Containee(value=a),
@jdk.test.CustomAnnTest$Containee(value=b),
@jdk.test.CustomAnnTest$Containee(value=c)])
null
[@jdk.test.CustomAnnTest$Containee(value=a),
@jdk.test.CustomAnnTest$Containee(value=b),
@jdk.test.CustomAnnTest$Containee(value=c)]
jdk.test.CustomAnnTest$MyElement at 3764951d:
[@jdk.test.CustomAnnTest$Container(value=[@jdk.test.CustomAnnTest$Containee(value=A),
@jdk.test.CustomAnnTest$Containee(value=B),
@jdk.test.CustomAnnTest$Containee(value=C)])]
@jdk.test.CustomAnnTest$Container(value=[@jdk.test.CustomAnnTest$Containee(value=A),
@jdk.test.CustomAnnTest$Containee(value=B),
@jdk.test.CustomAnnTest$Containee(value=C)])
null
[@jdk.test.CustomAnnTest$Containee(value=A),
@jdk.test.CustomAnnTest$Containee(value=B),
@jdk.test.CustomAnnTest$Containee(value=C)]
More information about the core-libs-dev
mailing list