JUNEAU-169 Dynamic annotations.
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfClassMeta.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfClassMeta.java
index 8161a74..322f563 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfClassMeta.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfClassMeta.java
@@ -16,7 +16,6 @@
 

 import org.apache.juneau.*;

 import org.apache.juneau.jena.annotation.*;

-import org.apache.juneau.reflect.*;

 import org.apache.juneau.xml.*;

 

 /**

@@ -37,15 +36,14 @@
 	 */

 	public RdfClassMeta(ClassMeta<?> cm, RdfMetaProvider mp) {

 		super(cm);

-		ClassInfo ci = cm.getInfo();

-		this.rdf = mp.getAnnotation(Rdf.class, cm.getInnerClass());

+		this.rdf = cm.getAnnotation(Rdf.class, mp);

 		if (rdf != null) {

 			collectionFormat = rdf.collectionFormat();

 		} else {

 			collectionFormat = RdfCollectionFormat.DEFAULT;

 		}

-		List<Rdf> rdfs = ci.getAnnotations(Rdf.class, mp);

-		List<RdfSchema> schemas = ci.getAnnotations(RdfSchema.class, mp);

+		List<Rdf> rdfs = cm.getAnnotations(Rdf.class, mp);

+		List<RdfSchema> schemas = cm.getAnnotations(RdfSchema.class, mp);

 		this.namespace = RdfUtils.findNamespace(rdfs, schemas);

 	}

 

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index 3b83da0..0f01aab 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -173,14 +173,14 @@
 				List<Class<?>> bdClasses = new ArrayList<>();

 				if (beanFilter != null && beanFilter.getBeanDictionary() != null)

 					bdClasses.addAll(Arrays.asList(beanFilter.getBeanDictionary()));

-				Bean bean = classMeta.innerClass.getAnnotation(Bean.class);

+				Bean bean = classMeta.getAnnotation(Bean.class);

 				if (bean != null) {

 					if (! bean.typeName().isEmpty())

 						bdClasses.add(classMeta.innerClass);

 				}

 				this.beanRegistry = new BeanRegistry(ctx, null, bdClasses.toArray(new Class<?>[bdClasses.size()]));

 

-				for (Bean b : classMeta.getInfo().getAnnotationsParentFirst(Bean.class))

+				for (Bean b : classMeta.getAnnotationsParentFirst(Bean.class))

 					if (! b.typePropertyName().isEmpty())

 						typePropertyName = b.typePropertyName();

 				if (typePropertyName == null)

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
index 37cb982..b643d3a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
@@ -89,7 +89,7 @@
 						addToMap(typeName, val);
 					}
 				} else {
-					Bean b = c.getAnnotation(Bean.class);
+					Bean b = ci.getAnnotation(Bean.class);
 					if (b == null || b.typeName().isEmpty())
 						throw new BeanRuntimeException("Class ''{0}'' was passed to BeanRegistry but it doesn't have a @Bean(typeName) annotation defined.", c.getName());
 					addToMap(b.typeName(), beanContext.getClassMeta(c));
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index c78437b..8fcd087 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -2043,7 +2043,88 @@
 	 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.

 	 */

 	public <A extends Annotation> A getAnnotation(Class<A> a) {

-		return this.innerClass.getAnnotation(a);

+		return info.getAnnotation(a);

+	}

+

+	/**

+	 * Returns the annotation defined on this class using the specified meta-provider for lookup.

+	 *

+	 * @param a The annotation to retrieve.

+	 * @param mp The meta-provider to use for lookup of annotations.

+	 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.

+	 */

+	public <A extends Annotation> A getAnnotation(Class<A> a, MetaProvider mp) {

+		return info.getAnnotation(a, mp);

+	}

+

+	/**

+	 * Returns the declared annotation defined on this class.

+	 *

+	 * @param a The annotation to retrieve.

+	 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.

+	 */

+	public <A extends Annotation> A getDeclaredAnnotation(Class<A> a) {

+		return info.getDeclaredAnnotation(a);

+	}

+

+	/**

+	 * Returns the declared annotation defined on this class using the specified meta-provider for lookup.

+	 *

+	 * @param a The annotation to retrieve.

+	 * @param mp The meta-provider to use for lookup of annotations.

+	 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation.

+	 */

+	public <A extends Annotation> A getDeclaredAnnotation(Class<A> a, MetaProvider mp) {

+		return info.getDeclaredAnnotation(a);

+	}

+

+	/**

+	 * Returns all annotations of the specified type defined on the specified class or parent classes/interfaces.

+	 *

+	 * @param a

+	 * 	The annotation to search for.

+	 * @return

+	 * 	A list of all matching annotations found in child-to-parent order, or an empty list if none found.

+	 */

+	public <A extends Annotation> List<A> getAnnotations(Class<A> a) {

+		return info.getAnnotations(a);

+	}

+

+	/**

+	 * Returns all annotations of the specified type defined on the specified class or parent classes/interfaces.

+	 *

+	 * @param a The annotation to search for.

+	 * @param mp The metadata provider for finding annotations.

+	 * @return

+	 * 	A list of all matching annotations found in child-to-parent order, or an empty list if none found.

+	 */

+	public <A extends Annotation> List<A> getAnnotations(Class<A> a, MetaProvider mp) {

+		return info.getAnnotations(a, mp);

+	}

+

+	/**

+	 * Identical to {@link #getAnnotations(Class)} but optionally returns the list in reverse (parent-to-child) order.

+	 *

+	 * @param a

+	 * 	The annotation to search for.

+	 * @return

+	 * 	A list of all matching annotations found or an empty list if none found.

+	 */

+	public <A extends Annotation> List<A> getAnnotationsParentFirst(Class<A> a) {

+		return info.getAnnotationsParentFirst(a);

+	}

+

+	/**

+	 * Identical to {@link #getAnnotations(Class,MetaProvider)} but optionally returns the list in reverse (parent-to-child) order.

+	 *

+	 * @param a

+	 * 	The annotation to search for.

+	 * @param mp The metadata provider for finding annotations.

+	 * @return

+	 * 	A list of all matching annotations found or an empty list if none found.

+	 */

+	public <A extends Annotation> List<A> getAnnotationsParentFirst(Class<A> a, MetaProvider mp) {

+		return info.getAnnotationsParentFirst(a, mp);

 	}

 

 	@Override /* Object */

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
index afbd32e..42594e9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
@@ -606,31 +606,31 @@
 	@SuppressWarnings("unchecked")
 	@Override /* MetaProvider */
 	public <A extends Annotation> A getAnnotation(Class<A> a, Class<?> c) {
-		return (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
+		return a == null || c == null ? null : (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override /* MetaProvider */
 	public <A extends Annotation> A getDeclaredAnnotation(Class<A> a, Class<?> c) {
-		return (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
+		return a == null || c == null ? null : (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override /* MetaProvider */
 	public <A extends Annotation> A getAnnotation(Class<A> a, Method m) {
-		return (A)annotations.findFirst(m, a).orElse(m.getAnnotation(a));
+		return a == null || m == null ? null : (A)annotations.findFirst(m, a).orElse(m.getAnnotation(a));
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override /* MetaProvider */
 	public <A extends Annotation> A getAnnotation(Class<A> a, Field f) {
-		return (A)annotations.findFirst(f, a).orElse(f.getAnnotation(a));
+		return a == null || f == null ? null : (A)annotations.findFirst(f, a).orElse(f.getAnnotation(a));
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override /* MetaProvider */
 	public <A extends Annotation> A getAnnotation(Class<A> a, Constructor<?> c) {
-		return (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
+		return a == null || c == null ? null : (A)annotations.findFirst(c, a).orElse(c.getAnnotation(a));
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
index 1791e63..8454b2a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
@@ -27,27 +27,27 @@
 
 		@Override /* MetaProvider */
 		public <A extends Annotation> A getAnnotation(Class<A> a, Class<?> c) {
-			return c.getAnnotation(a);
+			return a == null || c == null ? null : c.getAnnotation(a);
 		}
 
 		@Override /* MetaProvider */
 		public <A extends Annotation> A getDeclaredAnnotation(Class<A> a, Class<?> c) {
-			return c.getDeclaredAnnotation(a);
+			return a == null || c == null ? null : c.getDeclaredAnnotation(a);
 		}
 
 		@Override /* MetaProvider */
 		public <A extends Annotation> A getAnnotation(Class<A> a, Method m) {
-			return m.getAnnotation(a);
+			return a == null || m == null ? null : m.getAnnotation(a);
 		}
 
 		@Override /* MetaProvider */
 		public <A extends Annotation> A getAnnotation(Class<A> a, Field f) {
-			return f.getAnnotation(a);
+			return a == null || f == null ? null : f.getAnnotation(a);
 		}
 
 		@Override /* MetaProvider */
 		public <A extends Annotation> A getAnnotation(Class<A> a, Constructor<?> c) {
-			return c.getAnnotation(a);
+			return a == null || c == null ? null : c.getAnnotation(a);
 		}
 	};
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvClassMeta.java
index 279a500..ac61566 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public CsvClassMeta(ClassMeta<?> cm, CsvMetaProvider mp) {

 		super(cm);

-		this.csv = mp.getAnnotation(Csv.class, cm.getInnerClass());

+		this.csv = cm.getAnnotation(Csv.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
index 5f9ce95..e9586de 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
@@ -36,7 +36,7 @@
 	 */

 	public HtmlClassMeta(ClassMeta<?> cm, HtmlMetaProvider mp) {

 		super(cm);

-		this.html = mp.getAnnotation(Html.class, cm.getInnerClass());

+		this.html = cm.getAnnotation(Html.class, mp);

 		if (html != null) {

 			format = html.format();

 			noTables = html.noTables();

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoClassMeta.java
index 7227a2b..fafc76d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public JsoClassMeta(ClassMeta<?> cm, JsoMetaProvider mp) {

 		super(cm);

-		this.jso = mp.getAnnotation(Jso.class, cm.getInnerClass());

+		this.jso = cm.getAnnotation(Jso.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonClassMeta.java
index 0179b62..55dbb35 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonClassMeta.java
@@ -34,7 +34,7 @@
 	 */

 	public JsonClassMeta(ClassMeta<?> cm, JsonMetaProvider mp) {

 		super(cm);

-		this.json = mp.getAnnotation(Json.class, cm.getInnerClass());

+		this.json = cm.getAnnotation(Json.class, mp);

 		if (json != null) {

 			wrapperAttr = nullIfEmpty(json.wrapperAttr());

 		} else {

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaClassMeta.java
index 8caa931..2945099 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaClassMeta.java
@@ -33,7 +33,7 @@
 	public JsonSchemaClassMeta(ClassMeta<?> cm, JsonSchemaMetaProvider mp) {

 		super(cm);

 		try {

-			Schema s = mp.getAnnotation(Schema.class, cm.getInnerClass());

+			Schema s = cm.getAnnotation(Schema.class, mp);

 			schema = s == null ? ObjectMap.EMPTY_MAP : SchemaUtils.asMap(s);

 		} catch (ParseException e) {

 			throw new RuntimeException(e);

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackClassMeta.java
index 88b0f86..10bca2d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public MsgPackClassMeta(ClassMeta<?> cm, MsgPackMetaProvider mp) {

 		super(cm);

-		this.msgPack = mp.getAnnotation(MsgPack.class, cm.getInnerClass());

+		this.msgPack = cm.getAnnotation(MsgPack.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiClassMeta.java
index f786453..7b79561 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public OpenApiClassMeta(ClassMeta<?> cm, OpenApiMetaProvider mp) {

 		super(cm);

-		this.openApi = mp.getAnnotation(OpenApi.class, cm.getInnerClass());

+		this.openApi = cm.getAnnotation(OpenApi.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextClassMeta.java
index 11234e3..489fff1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public PlainTextClassMeta(ClassMeta<?> cm, PlainTextMetaProvider mp) {

 		super(cm);

-		this.plainText = mp.getAnnotation(PlainText.class, cm.getInnerClass());

+		this.plainText = cm.getAnnotation(PlainText.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index b7e0963..1c9d706 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -64,7 +64,6 @@
 	private List<MethodInfo> publicMethods, declaredMethods, allMethods, allMethodsParentFirst;
 	private List<ConstructorInfo> publicConstructors, declaredConstructors;
 	private List<FieldInfo> publicFields, declaredFields, allFields, allFieldsParentFirst;
-	private Map<Class<?>,Optional<Annotation>> annotationMap, declaredAnnotationMap;
 	private int dim = -1;
 	private ClassInfo componentType;
 
@@ -934,16 +933,26 @@
 	 * @return
 	 * 	The annotation if found, or <jk>null</jk> if not.
 	 */
-	@SuppressWarnings("unchecked")
 	public <T extends Annotation> T getAnnotation(Class<T> a) {
-		if (a == null)
-			return null;
-		Optional<Annotation> o = annotationMap().get(a);
-		if (o == null) {
-			o = Optional.ofNullable(findAnnotation(a));
-			annotationMap().put(a, o);
-		}
-		return o.isPresent() ? (T)o.get() : null;
+		return getAnnotation(a, MetaProvider.DEFAULT);
+	}
+
+	/**
+	 * Finds the annotation of the specified type defined on this class or parent class/interface.
+	 *
+	 * <p>
+	 * If the annotation cannot be found on the immediate class, searches methods with the same
+	 * signature on the parent classes or interfaces.
+	 * <br>The search is performed in child-to-parent order.
+	 *
+	 * @param a
+	 * 	The annotation to search for.
+	 * @param mp The metadata provider for finding annotations on classes and methods.
+	 * @return
+	 * 	The annotation if found, or <jk>null</jk> if not.
+	 */
+	public <T extends Annotation> T getAnnotation(Class<T> a, MetaProvider mp) {
+		return findAnnotation(a, mp);
 	}
 
 	/**
@@ -969,16 +978,24 @@
 	 * @param a The annotation class.
 	 * @return The annotation, or <jk>null</jk> if not found.
 	 */
-	@SuppressWarnings("unchecked")
 	public <T extends Annotation> T getDeclaredAnnotation(Class<T> a) {
-		if (a == null)
-			return null;
-		Optional<Annotation> o = declaredAnnotationMap().get(a);
-		if (o == null) {
-			o = Optional.ofNullable(findDeclaredAnnotation(a));
-			declaredAnnotationMap().put(a, o);
-		}
-		return o.isPresent() ? (T)o.get() : null;
+		return a == null ? null : c.getDeclaredAnnotation(a);
+	}
+
+	/**
+	 * Returns the specified annotation only if it's been declared on this class.
+	 *
+	 * <p>
+	 * More efficient than calling {@link Class#getAnnotation(Class)} since it doesn't recursively look for the class
+	 * up the parent chain.
+	 *
+	 * @param <T> The annotation class type.
+	 * @param a The annotation class.
+	 * @param mp The metadata provider for finding annotations on classes and methods.
+	 * @return The annotation, or <jk>null</jk> if not found.
+	 */
+	public <T extends Annotation> T getDeclaredAnnotation(Class<T> a, MetaProvider mp) {
+		return mp.getDeclaredAnnotation(a, c);
 	}
 
 	/**
@@ -1053,6 +1070,19 @@
 	}
 
 	/**
+	 * Identical to {@link #getAnnotations(Class,MetaProvider)} but optionally returns the list in reverse (parent-to-child) order.
+	 *
+	 * @param a
+	 * 	The annotation to search for.
+	 * @param mp The metadata provider for finding annotations.
+	 * @return
+	 * 	A list of all matching annotations found or an empty list if none found.
+	 */
+	public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, MetaProvider mp) {
+		return appendAnnotationsParentFirst(new ArrayList<>(), a, mp);
+	}
+
+	/**
 	 * Same as getAnnotations(Class) except returns the annotations with the accompanying class.
 	 *
 	 * <p>
@@ -1189,11 +1219,33 @@
 	 * @return The same list.
 	 */
 	public <T extends Annotation> List<T> appendAnnotationsParentFirst(List<T> l, Class<T> a) {
+		return appendAnnotationsParentFirst(l, a, MetaProvider.DEFAULT);
+	}
+
+	/**
+	 * Finds and appends the specified annotation on the specified class and superclasses/interfaces to the specified
+	 * list.
+	 *
+	 * <p>
+	 * Annotations are appended in the following orders:
+	 * <ol>
+	 * 	<li>On the package of this class.
+	 * 	<li>On interfaces ordered child-to-parent.
+	 * 	<li>On parent classes ordered child-to-parent.
+	 * 	<li>On this class.
+	 * </ol>
+	 *
+	 * @param l The list of annotations.
+	 * @param a The annotation to search for.
+	 * @param mp The metadata provider for finding annotations on classes and methods.
+	 * @return The same list.
+	 */
+	public <T extends Annotation> List<T> appendAnnotationsParentFirst(List<T> l, Class<T> a, MetaProvider mp) {
 		addIfNotNull(l, getPackageAnnotation(a));
 		for (ClassInfo ci : getInterfacesParentFirst())
-			addIfNotNull(l, ci.getDeclaredAnnotation(a));
+			addIfNotNull(l, mp.getDeclaredAnnotation(a, ci.inner()));
 		for (ClassInfo ci : getParentsParentFirst())
-			addIfNotNull(l, ci.getDeclaredAnnotation(a));
+			addIfNotNull(l, mp.getDeclaredAnnotation(a, ci.inner()));
 		return l;
 	}
 
@@ -1277,20 +1329,23 @@
 		return m;
 	}
 
-	<T extends Annotation> T findAnnotation(Class<T> a) {
-		T t2 = getDeclaredAnnotation(a);
+	<T extends Annotation> T findAnnotation(Class<T> a, MetaProvider mp) {
+		if (a == null)
+			return null;
+
+		T t2 = mp.getDeclaredAnnotation(a, c);
 		if (t2 != null)
 			return t2;
 
 		ClassInfo sci = getParent();
 		if (sci != null) {
-			t2 = sci.getAnnotation(a);
+			t2 = sci.getAnnotation(a, mp);
 			if (t2 != null)
 				return t2;
 		}
 
 		for (ClassInfo c2 : getInterfaces()) {
-			t2 = c2.getAnnotation(a);
+			t2 = c2.getAnnotation(a, mp);
 			if (t2 != null)
 				return t2;
 		}
@@ -1298,26 +1353,6 @@
 		return null;
 	}
 
-	@SuppressWarnings("unchecked")
-	private <T extends Annotation> T findDeclaredAnnotation(Class<T> a) {
-		for (Annotation a2 : c.getDeclaredAnnotations())
-			if (a2.annotationType() == a)
-				return (T)a2;
-		return null;
-	}
-
-	private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() {
-		if (annotationMap == null)
-			annotationMap = new ConcurrentHashMap<>();
-		return annotationMap;
-	}
-
-	private synchronized Map<Class<?>,Optional<Annotation>> declaredAnnotationMap() {
-		if (declaredAnnotationMap == null)
-			declaredAnnotationMap = new ConcurrentHashMap<>();
-		return declaredAnnotationMap;
-	}
-
 	//-----------------------------------------------------------------------------------------------------------------
 	// Characteristics
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlClassMeta.java
index 0d38b50..7d67287 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public SoapXmlClassMeta(ClassMeta<?> cm, SoapXmlMetaProvider mp) {

 		super(cm);

-		this.soapXml = mp.getAnnotation(SoapXml.class, cm.getInnerClass());

+		this.soapXml = cm.getAnnotation(SoapXml.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonClassMeta.java
index 48267b6..482b9e9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public UonClassMeta(ClassMeta<?> cm, UonMetaProvider mp) {

 		super(cm);

-		this.uon = mp.getAnnotation(Uon.class, cm.getInnerClass());

+		this.uon = cm.getAnnotation(Uon.class, mp);

 	}

 

 	/**

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingClassMeta.java
index aeefe69..41e5ecf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingClassMeta.java
@@ -31,7 +31,7 @@
 	 */

 	public UrlEncodingClassMeta(ClassMeta<?> cm, UrlEncodingMetaProvider mp) {

 		super(cm);

-		this.urlEncoding = mp.getAnnotation(UrlEncoding.class, cm.getInnerClass());

+		this.urlEncoding = cm.getAnnotation(UrlEncoding.class, mp);

 		if (urlEncoding != null) {

 			expandedParams = urlEncoding.expandedParams();

 		} else {

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlClassMeta.java
index 9cf999d..160a9ef 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlClassMeta.java
@@ -17,7 +17,6 @@
 import java.util.*;

 

 import org.apache.juneau.*;

-import org.apache.juneau.reflect.*;

 import org.apache.juneau.xml.annotation.*;

 

 /**

@@ -40,7 +39,7 @@
 	public XmlClassMeta(ClassMeta<?> cm, XmlMetaProvider mp) {

 		super(cm);

 		this.namespace = findNamespace(cm, mp);

-		this.xml = mp.getAnnotation(Xml.class, cm.getInnerClass());

+		this.xml = cm.getAnnotation(Xml.class, mp);

 		if (xml != null) {

 			this.format = xml.format();

 			this.childName = nullIfEmpty(xml.childName());

@@ -102,9 +101,8 @@
 	private static Namespace findNamespace(ClassMeta<?> cm, MetaProvider mp) {

 		if (cm == null)

 			return null;

-		ClassInfo ci = cm.getInfo();

-		List<Xml> xmls = ci.getAnnotations(Xml.class, mp);

-		List<XmlSchema> schemas = ci.getAnnotations(XmlSchema.class, mp);

+		List<Xml> xmls = cm.getAnnotations(Xml.class, mp);

+		List<XmlSchema> schemas = cm.getAnnotations(XmlSchema.class, mp);

 		return XmlUtils.findNamespace(xmls, schemas);

 	}

 }