diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReader.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReader.java index e3ba64d..62f05f8 100644 --- a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReader.java +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReader.java @@ -66,9 +66,9 @@ } public boolean hasClassAnnotation(Class clazz, Class annotationType) { - return clazz.isAnnotationPresent(annotationType); + return getAnnotation(annotationType, clazz.getAnnotations()) != null; } - + public Annotation[] getAllFieldAnnotations(Field field, Locatable srcPos) { Annotation[] r = field.getAnnotations(); for( int i=0; i A getClassAnnotation(Class a, Class clazz, Locatable srcPos) { - return LocatableAnnotation.create(((Class)clazz).getAnnotation(a),srcPos); + return LocatableAnnotation.create(getAnnotation(a, clazz.getAnnotations()),srcPos); } + + @SuppressWarnings("unchecked") + public A getAnnotation(Class annotationType, Annotation[] anns) { + for (Annotation a : anns) { + if (a.annotationType() == annotationType) { + return (A) a; + } + } + // Two loops are necessary to allow meta-annotation override. + // This is due to the fact that Class.getAnnotations() does not guarantee + // any specific order of annotations returned - it might differ from run to run. + for (Annotation a : anns) { + for (Annotation metaAnn : a.annotationType().getAnnotations()) { + if (metaAnn.annotationType() == annotationType) { + return (A) metaAnn; + } + } + } + + return null; + } /** * Cache for package-level annotations. diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReaderTest.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReaderTest.java new file mode 100644 index 0000000..a1bb596 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/annotation/RuntimeInlineAnnotationReaderTest.java @@ -0,0 +1,89 @@ +package com.sun.xml.bind.v2.model.annotation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.junit.Test; + +public class RuntimeInlineAnnotationReaderTest { + + RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader(); + + @Test + public void testHasClassAnnotation() { + assertTrue(reader.hasClassAnnotation(Direct.class, XmlRootElement.class)); + assertTrue(reader.hasClassAnnotation(Direct.class, XmlType.class)); + + assertTrue(reader.hasClassAnnotation(RootBean.class, XmlRootElement.class)); + assertFalse(reader.hasClassAnnotation(RootBean.class, XmlType.class)); + + assertTrue(reader.hasClassAnnotation(TypeBean.class, XmlType.class)); + assertFalse(reader.hasClassAnnotation(TypeBean.class, XmlRootElement.class)); + + assertTrue(reader.hasClassAnnotation(FullBean.class, XmlRootElement.class)); + assertTrue(reader.hasClassAnnotation(FullBean.class, XmlType.class)); + + assertFalse(reader.hasClassAnnotation(InvalidBean.class, XmlRootElement.class)); + assertFalse(reader.hasClassAnnotation(InvalidBean.class, XmlType.class)); + } + + @Test + public void testOverrideAnnotation() { + XmlRootElement a = reader.getAnnotation(XmlRootElement.class, Override.class.getAnnotations()); + assertEquals("XOverrideX", a.name()); + } + + @Test + public void testNoOverrideAnnotation() { + XmlRootElement a = reader.getAnnotation(XmlRootElement.class, Override1.class.getAnnotations()); + assertEquals("YOverrideY", a.name()); + } + + @XmlRootElement + @XmlType + static final class Direct {} + + @Root + static final class RootBean {} + + @Type + static final class TypeBean {} + + @Bean + static final class FullBean {} + + @XmlRootElement(name = "XOverrideX") + @Bean + static final class Override {} + + @Bean + @XmlRootElement(name = "YOverrideY") + static final class Override1 {} + + @MetaMeta + static final class InvalidBean {} + + @XmlRootElement + @Retention(RetentionPolicy.RUNTIME) + static @interface Root {} + + @XmlType + @Retention(RetentionPolicy.RUNTIME) + static @interface Type {} + + @XmlRootElement + @XmlType + @Retention(RetentionPolicy.RUNTIME) + static @interface Bean {} + + @Bean + @Retention(RetentionPolicy.RUNTIME) + static @interface MetaMeta {} +}