You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2019/03/16 18:31:12 UTC
[juneau] branch master updated: ClassUtils reorg.
This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new f91af4f ClassUtils reorg.
f91af4f is described below
commit f91af4ff24fbbf2f39a2549a13c3e18d473c7bdc
Author: JamesBognar <ja...@apache.org>
AuthorDate: Sat Mar 16 14:30:50 2019 -0400
ClassUtils reorg.
---
.../juneau/httppart/HttpPartSchemaTest_Body.java | 7 +-
.../httppart/HttpPartSchemaTest_FormData.java | 7 +-
.../juneau/httppart/HttpPartSchemaTest_Header.java | 7 +-
.../juneau/httppart/HttpPartSchemaTest_Path.java | 7 +-
.../juneau/httppart/HttpPartSchemaTest_Query.java | 7 +-
.../HttpPartSchemaTest_ResponseHeader.java | 7 +-
.../org/apache/juneau/utils/ClassUtilsTest.java | 17 +-
.../java/org/apache/juneau/jena/RdfClassMeta.java | 9 +-
.../src/main/java/org/apache/juneau/BeanMeta.java | 8 +-
.../java/org/apache/juneau/BeanPropertyMeta.java | 22 +-
.../src/main/java/org/apache/juneau/ClassInfo.java | 266 +++++++++++++++
.../src/main/java/org/apache/juneau/ClassMeta.java | 12 +
.../main/java/org/apache/juneau/MethodInfo.java | 268 +++++++++++++++
.../java/org/apache/juneau/MethodParamInfo.java | 224 ++++++++++++
.../java/org/apache/juneau/html/HtmlClassMeta.java | 3 +-
.../org/apache/juneau/httppart/HttpPartSchema.java | 9 +-
.../juneau/httppart/HttpPartSchemaBuilder.java | 10 +-
.../juneau/httppart/bean/RequestBeanMeta.java | 33 +-
.../httppart/bean/RequestBeanPropertyMeta.java | 2 +-
.../juneau/httppart/bean/ResponseBeanMeta.java | 31 +-
.../org/apache/juneau/httppart/bean/Utils.java | 10 -
.../org/apache/juneau/internal/ClassUtils.java | 380 +--------------------
.../java/org/apache/juneau/json/JsonClassMeta.java | 3 +-
.../juneau/jsonschema/JsonSchemaClassMeta.java | 3 +-
.../apache/juneau/remote/RemoteInterfaceMeta.java | 5 +-
.../juneau/urlencoding/UrlEncodingClassMeta.java | 3 +-
.../java/org/apache/juneau/xml/XmlClassMeta.java | 17 +-
.../juneau/rest/client/remote/RemoteMethodArg.java | 28 +-
.../rest/client/remote/RemoteMethodMeta.java | 15 +-
.../rest/client/remote/RemoteMethodReturn.java | 5 +-
.../rest/client/remote/RemoteResourceMeta.java | 5 +-
.../apache/juneau/rest/BasicRestInfoProvider.java | 10 +-
.../apache/juneau/rest/ClientVersionMatcher.java | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 49 +--
.../org/apache/juneau/rest/RestJavaMethod.java | 4 +-
.../org/apache/juneau/rest/RestMethodParam.java | 38 ++-
.../org/apache/juneau/rest/RestParamDefaults.java | 112 +++---
.../java/org/apache/juneau/rest/RestServlet.java | 5 +-
.../org/apache/juneau/rest/SwaggerGenerator.java | 50 +--
39 files changed, 1066 insertions(+), 634 deletions(-)
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
index 957afa5..c369562 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Body.java
@@ -16,6 +16,7 @@ import static org.junit.Assert.*;
import static org.apache.juneau.testutils.TestUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import org.apache.juneau.*;
import org.apache.juneau.http.annotation.*;
@@ -72,7 +73,8 @@ public class HttpPartSchemaTest_Body {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Body.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Body.class, mpi).noValidate().build();
assertTrue(s.isRequired());
}
@@ -92,7 +94,8 @@ public class HttpPartSchemaTest_Body {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Body.class, A04.class.getMethod("a", A02.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A02.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Body.class, mpi).noValidate().build();
assertTrue(s.isRequired());
}
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
index da5f888..f87d709 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_FormData.java
@@ -16,6 +16,7 @@ import static org.junit.Assert.*;
import static org.apache.juneau.testutils.TestUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import org.apache.juneau.*;
import org.apache.juneau.http.annotation.*;
@@ -134,7 +135,8 @@ public class HttpPartSchemaTest_FormData {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(FormData.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(FormData.class, mpi).noValidate().build();
assertEquals("x", s.getName());
assertEquals(HttpPartSchema.Type.NUMBER, s.getType());
assertEquals(HttpPartSchema.Format.INT32, s.getFormat());
@@ -190,7 +192,8 @@ public class HttpPartSchemaTest_FormData {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(FormData.class, A04.class.getMethod("a", A01.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A01.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(FormData.class, mpi).noValidate().build();
assertEquals("y", s.getName());
assertEquals(HttpPartSchema.Type.INTEGER, s.getType());
assertEquals(HttpPartSchema.Format.INT64, s.getFormat());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
index c09e087..e769351 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Header.java
@@ -15,6 +15,7 @@ package org.apache.juneau.httppart;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.apache.juneau.testutils.TestUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import org.apache.juneau.*;
@@ -134,7 +135,8 @@ public class HttpPartSchemaTest_Header {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Header.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Header.class, mpi).noValidate().build();
assertEquals("x", s.getName());
assertEquals(HttpPartSchema.Type.NUMBER, s.getType());
assertEquals(HttpPartSchema.Format.INT32, s.getFormat());
@@ -190,7 +192,8 @@ public class HttpPartSchemaTest_Header {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Header.class, A04.class.getMethod("a", A01.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A01.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Header.class, mpi).noValidate().build();
assertEquals("y", s.getName());
assertEquals(HttpPartSchema.Type.INTEGER, s.getType());
assertEquals(HttpPartSchema.Format.INT64, s.getFormat());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
index 97c4e9d..abc7105 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Path.java
@@ -15,6 +15,7 @@ package org.apache.juneau.httppart;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.apache.juneau.testutils.TestUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import org.apache.juneau.*;
@@ -116,7 +117,8 @@ public class HttpPartSchemaTest_Path {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Path.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Path.class, mpi).noValidate().build();
assertEquals("x", s.getName());
assertEquals(HttpPartSchema.Type.NUMBER, s.getType());
assertEquals(HttpPartSchema.Format.INT32, s.getFormat());
@@ -160,7 +162,8 @@ public class HttpPartSchemaTest_Path {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Path.class, A04.class.getMethod("a", A01.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A01.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Path.class, mpi).noValidate().build();
assertEquals("y", s.getName());
assertEquals(HttpPartSchema.Type.INTEGER, s.getType());
assertEquals(HttpPartSchema.Format.INT64, s.getFormat());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
index e66ba38..e403bc6 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_Query.java
@@ -15,6 +15,7 @@ package org.apache.juneau.httppart;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.apache.juneau.testutils.TestUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import org.apache.juneau.*;
@@ -134,7 +135,8 @@ public class HttpPartSchemaTest_Query {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Query.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Query.class, mpi).noValidate().build();
assertEquals("x", s.getName());
assertEquals(HttpPartSchema.Type.NUMBER, s.getType());
assertEquals(HttpPartSchema.Format.INT32, s.getFormat());
@@ -190,7 +192,8 @@ public class HttpPartSchemaTest_Query {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(Query.class, A04.class.getMethod("a", A01.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A01.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(Query.class, mpi).noValidate().build();
assertEquals("y", s.getName());
assertEquals(HttpPartSchema.Type.INTEGER, s.getType());
assertEquals(HttpPartSchema.Format.INT64, s.getFormat());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
index 8787e83..4e87a58 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/httppart/HttpPartSchemaTest_ResponseHeader.java
@@ -12,6 +12,7 @@
// ***************************************************************************************************************************
package org.apache.juneau.httppart;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.testutils.TestUtils.*;
import static org.junit.Assert.*;
@@ -128,7 +129,8 @@ public class HttpPartSchemaTest_ResponseHeader {
@Test
public void a03_basic_onParameter() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(ResponseHeader.class, A03.class.getMethod("a", String.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A03.class.getMethod("a", String.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(ResponseHeader.class, mpi).noValidate().build();
assertEquals("x", s.getName());
assertEquals(HttpPartSchema.Type.NUMBER, s.getType());
assertEquals(HttpPartSchema.Format.INT32, s.getFormat());
@@ -180,7 +182,8 @@ public class HttpPartSchemaTest_ResponseHeader {
@Test
public void a04_basic_onParameterAndClass() throws Exception {
- HttpPartSchema s = HttpPartSchema.create().apply(ResponseHeader.class, A04.class.getMethod("a", A01.class), 0).noValidate().build();
+ MethodParamInfo mpi = getMethodInfo(A04.class.getMethod("a", A01.class)).getParam(0);
+ HttpPartSchema s = HttpPartSchema.create().apply(ResponseHeader.class, mpi).noValidate().build();
assertEquals("y", s.getName());
assertEquals(HttpPartSchema.Type.INTEGER, s.getType());
assertEquals(HttpPartSchema.Format.INT64, s.getFormat());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
index 703a78a..9b75d28 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/ClassUtilsTest.java
@@ -164,10 +164,10 @@ public class ClassUtilsTest {
//====================================================================================================
@Test
public void getMethodAnnotations() throws Exception {
- assertEquals("a1", getAnnotation(TestAnnotation.class, CI3.class.getMethod("a1")).value());
- assertEquals("a2b", getAnnotation(TestAnnotation.class, CI3.class.getMethod("a2")).value());
- assertEquals("a3", getAnnotation(TestAnnotation.class, CI3.class.getMethod("a3", CharSequence.class)).value());
- assertEquals("a4", getAnnotation(TestAnnotation.class, CI3.class.getMethod("a4")).value());
+ assertEquals("a1", getMethodInfo(CI3.class.getMethod("a1")).getAnnotation(TestAnnotation.class).value());
+ assertEquals("a2b", getMethodInfo(CI3.class.getMethod("a2")).getAnnotation(TestAnnotation.class).value());
+ assertEquals("a3", getMethodInfo(CI3.class.getMethod("a3", CharSequence.class)).getAnnotation(TestAnnotation.class).value());
+ assertEquals("a4", getMethodInfo(CI3.class.getMethod("a4")).getAnnotation(TestAnnotation.class).value());
}
public static interface CI1 {
@@ -417,7 +417,8 @@ public class ClassUtilsTest {
@Test
public void getAnnotationsOnParameter() throws Exception {
ObjectList l = new ObjectList();
- for (HI1 ia : getAnnotations(HI1.class, HA.class.getMethod("doX", HA01.class), 0)) {
+ MethodParamInfo mpi = getMethodInfo(HA.class.getMethod("doX", HA01.class)).getParam(0);
+ for (HI1 ia : mpi.getAnnotations(HI1.class)) {
l.add(ia.value());
}
assertEquals("['0','1','2','3','4']", l.toString());
@@ -442,7 +443,8 @@ public class ClassUtilsTest {
@Test
public void getAnnotationsOnParameterInherited() throws Exception {
ObjectList l = new ObjectList();
- for (HI2 ib : getAnnotations(HI2.class, HB.class.getMethod("doX", HB01.class), 0)) {
+ MethodParamInfo mpi = getMethodInfo(HB.class.getMethod("doX", HB01.class)).getParam(0);
+ for (HI2 ib : mpi.getAnnotations(HI2.class)) {
l.add(ib.value());
}
assertEquals("['0','1','2','3','4']", l.toString());
@@ -474,7 +476,8 @@ public class ClassUtilsTest {
@Test
public void findMatchingMethods() throws Exception {
- assertObjectEquals("['public int org.apache.juneau.utils.ClassUtilsTest$I3.foo(int)','public int org.apache.juneau.utils.ClassUtilsTest$I2.foo(int)','public abstract int org.apache.juneau.utils.ClassUtilsTest$I1.foo(int)']", ClassUtils.findMatchingMethods(I3.class.getMethod("foo", int.class)));
+ MethodInfo mi = getMethodInfo(I3.class.getMethod("foo", int.class));
+ assertObjectEquals("['public int org.apache.juneau.utils.ClassUtilsTest$I3.foo(int)','public int org.apache.juneau.utils.ClassUtilsTest$I2.foo(int)','public abstract int org.apache.juneau.utils.ClassUtilsTest$I1.foo(int)']", mi.getMatching());
}
}
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 dff9256..9c06be1 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
@@ -15,7 +15,6 @@ package org.apache.juneau.jena;
import java.util.*;
import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.jena.annotation.*;
import org.apache.juneau.xml.*;
@@ -36,15 +35,15 @@ public class RdfClassMeta extends ClassMetaExtended {
*/
public RdfClassMeta(ClassMeta<?> cm) {
super(cm);
- Class<?> c = getInnerClass();
- this.rdf = ClassUtils.getAnnotation(Rdf.class, c);
+ ClassInfo ci = cm.getClassInfo();
+ this.rdf = ci.getAnnotation(Rdf.class);
if (rdf != null) {
collectionFormat = rdf.collectionFormat();
} else {
collectionFormat = RdfCollectionFormat.DEFAULT;
}
- List<Rdf> rdfs = ClassUtils.getAnnotations(Rdf.class, c);
- List<RdfSchema> schemas = ClassUtils.getAnnotations(RdfSchema.class, c);
+ List<Rdf> rdfs = ci.getAnnotations(Rdf.class);
+ List<RdfSchema> schemas = ci.getAnnotations(RdfSchema.class);
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 d2b9683..b6c1e3e 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
@@ -184,7 +184,7 @@ public class BeanMeta<T> {
}
this.beanRegistry = new BeanRegistry(ctx, null, bdClasses.toArray(new Class<?>[bdClasses.size()]));
- for (Bean b : getAnnotationsParentFirst(Bean.class, classMeta.innerClass))
+ for (Bean b : classMeta.getClassInfo().getAnnotationsParentFirst(Bean.class))
if (! b.typePropertyName().isEmpty())
typePropertyName = b.typePropertyName();
if (typePropertyName == null)
@@ -607,11 +607,13 @@ public class BeanMeta<T> {
if (m.isBridge()) // This eliminates methods with covariant return types from parent classes on child classes.
continue;
- BeanIgnore bi = getAnnotation(BeanIgnore.class, m);
+ MethodInfo mi = getMethodInfo(m);
+
+ BeanIgnore bi = mi.getAnnotation(BeanIgnore.class);
if (bi != null)
continue;
- BeanProperty bp = getAnnotation(BeanProperty.class, m);
+ BeanProperty bp = mi.getAnnotation(BeanProperty.class);
if (! (v.isVisible(m) || bp != null))
continue;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 236904f..444944a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -52,6 +52,7 @@ public final class BeanPropertyMeta {
private final Field field; // The bean property field (if it has one).
private final Field innerField; // The bean property field (if it has one).
private final Method getter, setter, extraKeys; // The bean property getter and setter.
+ private final MethodInfo getterInfo, setterInfo, extraKeysInfo; // The bean property getter and setter.
private final boolean isUri; // True if this is a URL/URI or annotated with @URI.
private final boolean isDyna, isDynaGetterMap; // This is a dyna property (i.e. name="*")
@@ -194,7 +195,7 @@ public final class BeanPropertyMeta {
}
if (getter != null) {
- BeanProperty p = ClassUtils.getAnnotation(BeanProperty.class, getter);
+ BeanProperty p = getMethodInfo(getter).getAnnotation(BeanProperty.class);
if (rawTypeMeta == null)
rawTypeMeta = f.resolveClassMeta(p, getter.getGenericReturnType(), typeVarImpls);
isUri |= (rawTypeMeta.isUri() || getter.isAnnotationPresent(org.apache.juneau.annotation.URI.class));
@@ -210,7 +211,7 @@ public final class BeanPropertyMeta {
}
if (setter != null) {
- BeanProperty p = ClassUtils.getAnnotation(BeanProperty.class, setter);
+ BeanProperty p = getMethodInfo(setter).getAnnotation(BeanProperty.class);
if (rawTypeMeta == null)
rawTypeMeta = f.resolveClassMeta(p, setter.getGenericParameterTypes()[0], typeVarImpls);
isUri |= (rawTypeMeta.isUri() || setter.isAnnotationPresent(org.apache.juneau.annotation.URI.class));
@@ -370,8 +371,11 @@ public final class BeanPropertyMeta {
this.field = b.field;
this.innerField = b.innerField;
this.getter = b.getter;
+ this.getterInfo = getMethodInfo(b.getter);
this.setter = b.setter;
+ this.setterInfo = getMethodInfo(b.setter);
this.extraKeys = b.extraKeys;
+ this.extraKeysInfo = getMethodInfo(b.extraKeys);
this.isUri = b.isUri;
this.beanMeta = b.beanMeta;
this.beanContext = b.beanContext;
@@ -1064,15 +1068,15 @@ public final class BeanPropertyMeta {
appendAnnotations(a, field.getType(), l);
}
if (getter != null) {
- addIfNotNull(l, ClassUtils.getAnnotation(a, getter));
+ addIfNotNull(l, ClassUtils.getMethodInfo(getter).getAnnotation(a));
appendAnnotations(a, getter.getReturnType(), l);
}
if (setter != null) {
- addIfNotNull(l, ClassUtils.getAnnotation(a, setter));
+ addIfNotNull(l, ClassUtils.getMethodInfo(setter).getAnnotation(a));
appendAnnotations(a, setter.getReturnType(), l);
}
if (extraKeys != null) {
- addIfNotNull(l, ClassUtils.getAnnotation(a, extraKeys));
+ addIfNotNull(l, ClassUtils.getMethodInfo(extraKeys).getAnnotation(a));
appendAnnotations(a, extraKeys.getReturnType(), l);
}
@@ -1095,13 +1099,13 @@ public final class BeanPropertyMeta {
if (field != null)
t = field.getAnnotation(a);
if (t == null && getter != null)
- t = ClassUtils.getAnnotation(a, getter);
+ t = getterInfo.getAnnotation(a);
if (t == null && setter != null)
- t = ClassUtils.getAnnotation(a, setter);
+ t = setterInfo.getAnnotation(a);
if (t == null && extraKeys != null)
- t = ClassUtils.getAnnotation(a, extraKeys);
+ t = extraKeysInfo.getAnnotation(a);
if (t == null)
- t = ClassUtils.getAnnotation(a, typeMeta.getInnerClass());
+ t = typeMeta.getClassInfo().getAnnotation(a);
return t;
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassInfo.java
new file mode 100644
index 0000000..2508988
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassInfo.java
@@ -0,0 +1,266 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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 org.apache.juneau;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Utility class for introspecting information about a class.
+ */
+public class ClassInfo {
+
+ private final Type type;
+ private final Class<?> c;
+ private Map<Class<?>,Optional<Annotation>> annotationMap;
+ private Map<Class<?>,List<?>> annotationsMap;
+ private Map<Class<?>,List<?>> annotationsPfMap;
+ private Optional<ClassInfo> parent;
+ private ClassInfo[] interfaces;
+
+ private static final Map<Type,ClassInfo> CACHE = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor.
+ *
+ * @param t The class type.
+ */
+ public ClassInfo(Type t) {
+ this.type = t;
+ this.c = ClassUtils.toClass(t);
+ }
+
+ /**
+ * Same as using the constructor, but returns <jk>null</jk> if the type is <jk>null</jk>.
+ *
+ * @param t The class type.
+ * @return The constructed class info.
+ */
+ public static ClassInfo create(Type t) {
+ if (t == null)
+ return null;
+ return new ClassInfo(t);
+ }
+
+ /**
+ * Returns the cached instance of the specified type.
+ *
+ * @param t The class type.
+ * @return The cached class info, or <jk>null</jk> if the type is <jk>null</jk>.
+ */
+ public synchronized static ClassInfo lookup(Type t) {
+ if (t == null)
+ return null;
+ ClassInfo ci = CACHE.get(t);
+ if (ci == null) {
+ ci = create(t);
+ CACHE.put(t, ci);
+ }
+ return ci;
+ }
+
+ /**
+ * Returns the wrapped class.
+ *
+ * @return The wrapped class.
+ */
+ public Type getInner() {
+ return type;
+ }
+
+ /**
+ * Returns the wrapped class.
+ *
+ * @return The wrapped class or <jk>null</jk> if it's not a class.
+ */
+ public Class<?> getInnerClass() {
+ return c;
+ }
+
+ /**
+ * Returns the parent class info.
+ *
+ * @return The parent class info, or <jk>null</jk> if the class has no parent.
+ */
+ public synchronized ClassInfo getParent() {
+ if (parent == null)
+ parent = Optional.ofNullable(c == null ? null : create(c.getSuperclass()));
+ return parent.isPresent() ? parent.get() : null;
+ }
+
+ /**
+ * Returns the interfaces info.
+ *
+ * @return The implemented interfaces info, or an empty array if the class has no interfaces.
+ */
+ public synchronized ClassInfo[] getInterfaces() {
+ if (interfaces == null) {
+ interfaces = new ClassInfo[c == null ? 0 : c.getInterfaces().length];
+ for (int i = 0; i < interfaces.length; i++)
+ interfaces[i] = ClassInfo.create(c.getInterfaces()[i]);
+ }
+ return interfaces;
+ }
+
+ /**
+ * Finds the annotation of the specified type defined on this method.
+ *
+ * <p>
+ * If the annotation cannot be found on the immediate method, searches methods with the same
+ * signature on the parent classes or interfaces.
+ * <br>The search is performed in child-to-parent order.
+ *
+ * <p>
+ * If still not found, searches for the annotation on the return type of the method.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The annotation if found, or <jk>null</jk> if not.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> a) {
+ 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;
+ }
+
+ /**
+ * Returns <jk>true</jk> if this method has the specified annotation.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The <jk>true</jk> if annotation if found.
+ */
+ public boolean hasAnnotation(Class<? extends Annotation> a) {
+ return getAnnotation(a) != null;
+ }
+
+ private <T extends Annotation> T findAnnotation(Class<T> a) {
+ if (c != null) {
+ T t2 = getDeclaredAnnotation(a);
+ if (t2 != null)
+ return t2;
+
+ ClassInfo sci = getParent();
+ if (sci != null) {
+ t2 = sci.getAnnotation(a);
+ if (t2 != null)
+ return t2;
+ }
+
+ for (ClassInfo c2 : getInterfaces()) {
+ t2 = c2.getAnnotation(a);
+ if (t2 != null)
+ return t2;
+ }
+ }
+ return null;
+
+ }
+
+ /**
+ * Returns all annotations of the specified type defined on the specified method.
+ *
+ * <p>
+ * Searches all methods with the same signature on the parent classes or interfaces
+ * and the return type on the method.
+ *
+ * @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.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotations(Class<T> a) {
+ List<T> l = (List<T>)annotationsMap().get(a);
+ if (l == null) {
+ l = Collections.unmodifiableList(findAnnotations(a));
+ annotationsMap().put(a, l);
+ }
+ return l;
+ }
+
+ /**
+ * Identical to {@link #getAnnotations(Class)} but returns the list in reverse (parent-to-child) order.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * A list of all matching annotations found in parent-to-child order, or an empty list if none found.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a) {
+ List<T> l = (List<T>)annotationsPfMap().get(a);
+ if (l == null) {
+ l = new ArrayList<>(getAnnotations(a));
+ Collections.reverse(l);
+ l = Collections.unmodifiableList(l);
+ annotationsPfMap().put(a, l);
+ }
+ return l;
+ }
+
+ private <T extends Annotation> List<T> findAnnotations(Class<T> a) {
+ List<T> l = new LinkedList<>();
+ ClassUtils.appendAnnotations(a, type, l);
+ return l;
+ }
+
+ private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() {
+ if (annotationMap == null)
+ annotationMap = new ConcurrentHashMap<>();
+ return annotationMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsMap() {
+ if (annotationsMap == null)
+ annotationsMap = new ConcurrentHashMap<>();
+ return annotationsMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsPfMap() {
+ if (annotationsPfMap == null)
+ annotationsPfMap = new ConcurrentHashMap<>();
+ return annotationsPfMap;
+ }
+
+
+ /**
+ * Returns the specified annotation only if it's been declared on the specified 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.
+ * @return The annotation, or <jk>null</jk> if not found.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getDeclaredAnnotation(Class<T> a) {
+ if (c != null)
+ for (Annotation a2 : c.getDeclaredAnnotations())
+ if (a2.annotationType() == a)
+ return (T)a2;
+ return null;
+ }
+}
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 571b9ff..56f1503 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
@@ -65,6 +65,7 @@ public final class ClassMeta<T> implements Type {
}
final Class<T> innerClass; // The class being wrapped.
+ final ClassInfo info;
private final Class<? extends T> implClass; // The implementation class to use if this is an interface.
private final ClassCategory cc; // The class category.
@@ -151,6 +152,7 @@ public final class ClassMeta<T> implements Type {
@SuppressWarnings({ "rawtypes", "unchecked" })
ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] pojoSwaps, PojoSwap<?,?>[] childPojoSwaps, Object example) {
this.innerClass = innerClass;
+ this.info = ClassInfo.lookup(innerClass);
this.beanContext = beanContext;
this.extMeta = new MetadataMap();
String notABeanReason = null;
@@ -229,6 +231,7 @@ public final class ClassMeta<T> implements Type {
*/
ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) {
this.innerClass = mainType.innerClass;
+ this.info = ClassInfo.lookup(innerClass);
this.implClass = mainType.implClass;
this.childPojoSwaps = mainType.childPojoSwaps;
this.childSwapMap = mainType.childSwapMap;
@@ -280,6 +283,7 @@ public final class ClassMeta<T> implements Type {
@SuppressWarnings("unchecked")
ClassMeta(ClassMeta<?>[] args) {
this.innerClass = (Class<T>) Object[].class;
+ this.info = ClassInfo.lookup(innerClass);
this.extMeta = new MetadataMap();
this.args = args;
this.implClass = null;
@@ -817,6 +821,14 @@ public final class ClassMeta<T> implements Type {
}
}
+ /**
+ * Returns the {@link ClassInfo} wrapper for the underlying class.
+ *
+ * @return The {@link ClassInfo} wrapper for the underlying class, never <jk>null</jk>.
+ */
+ public ClassInfo getClassInfo() {
+ return info;
+ }
/**
* Returns the type property name associated with this class and subclasses.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodInfo.java
new file mode 100644
index 0000000..51a4d25
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodInfo.java
@@ -0,0 +1,268 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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 org.apache.juneau;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Utility class for introspecting information about a method.
+ */
+public class MethodInfo {
+
+ private final Method method;
+ private final MethodParamInfo[] params;
+ private List<Method> matching;
+ private Map<Class<?>,Optional<Annotation>> annotationMap;
+ private Map<Class<?>,List<?>> annotationsMap;
+ private Map<Class<?>,List<?>> annotationsPfMap;
+ private ClassInfo returnTypeInfo;
+ private ClassInfo[] exceptionInfos;
+
+ /**
+ * Constructor.
+ *
+ * @param m The method being wrapped.
+ */
+ public MethodInfo(Method m) {
+ this.method = m;
+ params = new MethodParamInfo[m.getParameterCount()];
+ for (int i = 0; i < m.getParameterCount(); i++)
+ params[i] = new MethodParamInfo(this, i);
+ }
+
+ /**
+ * Returns the wrapped method.
+ *
+ * @return The wrapped method.
+ */
+ public Method getInner() {
+ return method;
+ }
+
+ /**
+ * Returns the parameters defined on this method.
+ *
+ * @return An array of parameter information, never <jk>null</jk>.
+ */
+ public MethodParamInfo[] getParams() {
+ return params;
+ }
+
+ /**
+ * Returns parameter information at the specified index.
+ *
+ * @param index The parameter index.
+ * @return The parameter information, never <jk>null</jk>.
+ */
+ public MethodParamInfo getParam(int index) {
+ return params[index];
+ }
+
+ /**
+ * Finds all declared methods with the same name and arguments on all superclasses and interfaces.
+ *
+ * @return
+ * All matching methods including this method itself.
+ * <br>Methods are ordered from child-to-parent order.
+ */
+ public List<Method> getMatching() {
+ if (matching == null)
+ matching = Collections.unmodifiableList(findMatching(new ArrayList<>(), method, method.getDeclaringClass()));
+ return matching;
+ }
+
+ private static List<Method> findMatching(List<Method> l, Method m, Class<?> c) {
+ for (Method m2 : c.getDeclaredMethods())
+ if (m.getName().equals(m2.getName()) && Arrays.equals(m.getParameterTypes(), m2.getParameterTypes()))
+ l.add(m2);
+ Class<?> pc = c.getSuperclass();
+ if (pc != null)
+ findMatching(l, m, pc);
+ for (Class<?> ic : c.getInterfaces())
+ findMatching(l, m, ic);
+ return l;
+ }
+
+ /**
+ * Returns the {@link ClassInfo} object associated with the return type on this method.
+ *
+ * @return The {@link ClassInfo} object associated with the return type on this method.
+ */
+ public synchronized ClassInfo getReturnTypeInfo() {
+ if (returnTypeInfo == null)
+ returnTypeInfo = ClassInfo.lookup(method.getReturnType());
+ return returnTypeInfo;
+ }
+
+ /**
+ * Returns the {@link ClassInfo} objects associated with the exception types on this method.
+ *
+ * @return The {@link ClassInfo} objects associated with the exception types on this method.
+ */
+ public synchronized ClassInfo[] getExceptionInfos() {
+ if (exceptionInfos == null) {
+ Class<?>[] exceptionTypes = method.getExceptionTypes();
+ exceptionInfos = new ClassInfo[exceptionTypes.length];
+ for (int i = 0; i < exceptionTypes.length; i++)
+ exceptionInfos[i] = ClassInfo.lookup(exceptionTypes[i]);
+ }
+ return exceptionInfos;
+ }
+
+ /**
+ * Finds the annotation of the specified type defined on this method.
+ *
+ * <p>
+ * If the annotation cannot be found on the immediate method, searches methods with the same
+ * signature on the parent classes or interfaces.
+ * <br>The search is performed in child-to-parent order.
+ *
+ * <p>
+ * If still not found, searches for the annotation on the return type of the method.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The annotation if found, or <jk>null</jk> if not.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> a) {
+ 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;
+ }
+
+ /**
+ * Returns <jk>true</jk> if this method has the specified annotation.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The <jk>true</jk> if annotation if found.
+ */
+ public boolean hasAnnotation(Class<? extends Annotation> a) {
+ return getAnnotation(a) != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Annotation> T findAnnotation(Class<T> a) {
+ List<Method> methods = getMatching();
+ for (Method m2 : methods)
+ for (Annotation a2 : m2.getAnnotations())
+ if (a.isInstance(a2))
+ return (T)a2;
+ Type t = method.getGenericReturnType();
+ if (Value.isType(t))
+ return ClassInfo.lookup(Value.getParameterType(t)).getAnnotation(a);
+ return ClassInfo.lookup(t).getAnnotation(a);
+ }
+
+ /**
+ * Returns all annotations of the specified type defined on the specified method.
+ *
+ * <p>
+ * Searches all methods with the same signature on the parent classes or interfaces
+ * and the return type on the method.
+ *
+ * @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.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotations(Class<T> a) {
+ List<T> l = (List<T>)annotationsMap().get(a);
+ if (l == null) {
+ l = Collections.unmodifiableList(findAnnotations(a));
+ annotationsMap().put(a, l);
+ }
+ return l;
+ }
+
+ /**
+ * Identical to {@link #getAnnotations(Class)} but returns the list in reverse (parent-to-child) order.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * A list of all matching annotations found in parent-to-child order, or an empty list if none found.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a) {
+ List<T> l = (List<T>)annotationsPfMap().get(a);
+ if (l == null) {
+ l = new ArrayList<>(getAnnotations(a));
+ Collections.reverse(l);
+ l = Collections.unmodifiableList(l);
+ annotationsPfMap().put(a, l);
+ }
+ return l;
+ }
+
+ /**
+ * Asserts that the specified method that's annotated with the specified annotation cannot also be annotated with other annotations.
+ *
+ * @param a The annotation known to exist on the method.
+ * @param c The annotations that cannot be present on the method.
+ * @throws InvalidAnnotationException
+ */
+ @SafeVarargs
+ public final void assertNoAnnotations(Class<? extends Annotation> a, Class<? extends Annotation>...c) throws InvalidAnnotationException {
+ for (Class<? extends Annotation> cc : c)
+ if (hasAnnotation(cc))
+ throw new InvalidAnnotationException("@{0} annotation cannot be used in a @{1} bean. Method=''{2}''", cc.getSimpleName(), a.getSimpleName(), method);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Annotation> List<T> findAnnotations(Class<T> a) {
+ List<T> l = new ArrayList<>();
+ List<Method> methods = getMatching();
+ for (Method m2 : methods)
+ for (Annotation a2 : m2.getAnnotations())
+ if (a.isInstance(a2))
+ l.add((T)a2);
+ Type t = method.getGenericReturnType();
+ if (Value.isType(t))
+ ClassUtils.appendAnnotations(a, Value.getParameterType(t), l);
+ else
+ ClassUtils.appendAnnotations(a, t, l);
+ return l;
+ }
+
+ private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() {
+ if (annotationMap == null)
+ annotationMap = new ConcurrentHashMap<>();
+ return annotationMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsMap() {
+ if (annotationsMap == null)
+ annotationsMap = new ConcurrentHashMap<>();
+ return annotationsMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsPfMap() {
+ if (annotationsPfMap == null)
+ annotationsPfMap = new ConcurrentHashMap<>();
+ return annotationsPfMap;
+ }
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodParamInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodParamInfo.java
new file mode 100644
index 0000000..1805439
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MethodParamInfo.java
@@ -0,0 +1,224 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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 org.apache.juneau;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Utility class for introspecting information about a method parameter.
+ */
+public class MethodParamInfo {
+
+ private MethodInfo methodInfo;
+ private int index;
+ private Map<Class<?>,Optional<Annotation>> annotationMap = new ConcurrentHashMap<>();
+ private Map<Class<?>,List<?>> annotationsMap = new ConcurrentHashMap<>();
+ private Map<Class<?>,List<?>> annotationsPfMap = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor.
+ *
+ * @param methodInfo The method wrapper.
+ * @param index The parameter index.
+ */
+ protected MethodParamInfo(MethodInfo methodInfo, int index) {
+ this.methodInfo = methodInfo;
+ this.index = index;
+ }
+
+ /**
+ * Returns the index position of this parameter.
+ *
+ * @return The index position of this parameter.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the method that this parameter belongs to.
+ *
+ * @return The method that this parameter belongs to.
+ */
+ public Method getMethod() {
+ return methodInfo.getInner();
+ }
+
+ /**
+ * Returns the class type of this parameter.
+ *
+ * @return The class type of this parameter.
+ */
+ public Class<?> getParameterType() {
+ return getMethod().getParameterTypes()[index];
+ }
+
+ /**
+ * Returns the generic class type of this parameter.
+ *
+ * @return The generic class type of htis parameter.
+ */
+ public Type getGenericParameterType() {
+ return methodInfo.getInner().getGenericParameterTypes()[index];
+ }
+
+ /**
+ * Returns the parameter annotations defined on this parameter.
+ *
+ * @return The parameter annotations defined on this parameter.
+ */
+ public Annotation[] getParameterAnnotations() {
+ return methodInfo.getInner().getParameterAnnotations()[index];
+ }
+
+ /**
+ * Finds the annotation of the specified type defined on this method parameter.
+ *
+ * <p>
+ * If the annotation cannot be found on the immediate method, searches methods with the same
+ * signature on the parent classes or interfaces.
+ * <br>The search is performed in child-to-parent order.
+ *
+ * <p>
+ * If still not found, searches for the annotation on the return type of the method.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The annotation if found, or <jk>null</jk> if not.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> a) {
+ 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;
+ }
+
+ /**
+ * Returns <jk>true</jk> if this parameter has the specified annotation.
+ *
+ * @param a
+ * The annotation to search for.
+ * @return
+ * The <jk>true</jk> if annotation if found.
+ */
+ public boolean hasAnnotation(Class<? extends Annotation> a) {
+ return getAnnotation(a) != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Annotation> T findAnnotation(Class<T> a) {
+ List<Method> methods = methodInfo.getMatching();
+ for (Method m2 : methods)
+ for (Annotation a2 : m2.getParameterAnnotations()[index])
+ if (a.isInstance(a2))
+ return (T)a2;
+ Type t = methodInfo.getInner().getGenericParameterTypes()[index];
+ if (Value.isType(t))
+ return ClassInfo.lookup(Value.getParameterType(t)).getAnnotation(a);
+ return ClassInfo.lookup(t).getAnnotation(a);
+ }
+
+ /**
+ * Returns all annotations of the specified type defined on the specified method.
+ *
+ * <p>
+ * Searches all methods with the same signature on the parent classes or interfaces
+ * and the return type on the method.
+ *
+ * @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.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotations(Class<T> a) {
+ List<T> l = (List<T>)annotationsMap().get(a);
+ if (l == null) {
+ l = Collections.unmodifiableList(findAnnotations(a));
+ annotationsMap().put(a, l);
+ }
+ return l;
+ }
+
+ /**
+ * Returns all annotations of the specified type defined on the specified method.
+ *
+ * <p>
+ * Searches all methods with the same signature on the parent classes or interfaces
+ * and the return type on the method.
+ *
+ * @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.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a) {
+ List<T> l = (List<T>)annotationsPfMap().get(a);
+ if (l == null) {
+ l = new ArrayList<>(getAnnotations(a));
+ Collections.reverse(l);
+ l = Collections.unmodifiableList(l);
+ annotationsPfMap().put(a, l);
+ }
+ return l;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends Annotation> List<T> findAnnotations(Class<T> a) {
+ List<T> l = new ArrayList<>();
+ List<Method> methods = methodInfo.getMatching();
+ for (Method m2 : methods)
+ for (Annotation a2 : m2.getParameterAnnotations()[index])
+ if (a.isInstance(a2))
+ l.add((T)a2);
+ Type t = methodInfo.getInner().getGenericParameterTypes()[index];
+ if (Value.isType(t))
+ ClassUtils.appendAnnotations(a, Value.getParameterType(t), l);
+ else
+ ClassUtils.appendAnnotations(a, t, l);
+ return l;
+ }
+
+ private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() {
+ if (annotationMap == null)
+ annotationMap = new ConcurrentHashMap<>();
+ return annotationMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsMap() {
+ if (annotationsMap == null)
+ annotationsMap = new ConcurrentHashMap<>();
+ return annotationsMap;
+ }
+
+ private synchronized Map<Class<?>,List<?>> annotationsPfMap() {
+ if (annotationsPfMap == null)
+ annotationsPfMap = new ConcurrentHashMap<>();
+ return annotationsPfMap;
+ }
+
+ @Override
+ public String toString() {
+ return getMethod().getName() + "[" + index + "]";
+ }
+}
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 7edb103..a6fa303 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
@@ -14,7 +14,6 @@ package org.apache.juneau.html;
import org.apache.juneau.*;
import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.internal.*;
/**
* Metadata on classes specific to the HTML serializers and parsers pulled from the {@link Html @Html} annotation on
@@ -34,7 +33,7 @@ public class HtmlClassMeta extends ClassMetaExtended {
*/
public HtmlClassMeta(ClassMeta<?> cm) {
super(cm);
- this.html = ClassUtils.getAnnotation(Html.class, getInnerClass());
+ this.html = cm.getClassInfo().getAnnotation(Html.class);
if (html != null) {
format = html.format();
noTables = html.noTables();
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index ac54950..425a551 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -109,14 +109,11 @@ public class HttpPartSchema {
* <li>{@link HasQuery}
* <li>{@link HasFormData}
* </ul>
- * @param m
- * The Java method containing the parameter.
- * @param mi
- * The index of the parameter on the method.
+ * @param mpi The Java method parameter.
* @return The schema information about the parameter.
*/
- public static HttpPartSchema create(Class<? extends Annotation> c, Method m, int mi) {
- return create().apply(c, m, mi).build();
+ public static HttpPartSchema create(Class<? extends Annotation> c, MethodParamInfo mpi) {
+ return create().apply(c, mpi).build();
}
/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
index cb414b2..9d136f3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java
@@ -26,7 +26,6 @@ import org.apache.juneau.jsonschema.annotation.Items;
import org.apache.juneau.jsonschema.annotation.SubItems;
import org.apache.juneau.httppart.HttpPartSchema.*;
import org.apache.juneau.httppart.HttpPartSchema.Type;
-import org.apache.juneau.internal.*;
import org.apache.juneau.utils.*;
/**
@@ -64,9 +63,9 @@ public class HttpPartSchemaBuilder {
return new HttpPartSchema(this);
}
- HttpPartSchemaBuilder apply(Class<? extends Annotation> c, Method m, int index) {
- apply(c, m.getGenericParameterTypes()[index]);
- for (Annotation a : m.getParameterAnnotations()[index])
+ HttpPartSchemaBuilder apply(Class<? extends Annotation> c, MethodParamInfo mpi) {
+ apply(c, mpi.getGenericParameterType());
+ for (Annotation a : mpi.getParameterAnnotations())
if (c.isInstance(a))
apply(a);
return this;
@@ -83,7 +82,8 @@ public class HttpPartSchemaBuilder {
HttpPartSchemaBuilder apply(Class<? extends Annotation> c, java.lang.reflect.Type t) {
if (t instanceof Class<?>) {
Class<?> tc = (Class<?>)t;
- for (Annotation a : ClassUtils.getAnnotationsParentFirst(c, tc))
+ ClassInfo ci = ClassInfo.lookup(tc);
+ for (Annotation a : ci.getAnnotationsParentFirst(c))
apply(a);
} else if (Value.isType(t)) {
apply(c, Value.getParameterType(t));
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
index 7d3ef9d..5d055fc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
@@ -32,17 +32,16 @@ public class RequestBeanMeta {
/**
* Create metadata from specified parameter.
*
- * @param m The method containing the parameter or parameter type annotated with {@link Request}.
- * @param i The parameter index.
+ * @param mpi The method parameter.
* @param ps
* Configuration information used to instantiate part serializers and part parsers.
* <br>Can be <jk>null</jk>.
* @return Metadata about the parameter, or <jk>null</jk> if parameter or parameter type not annotated with {@link Request}.
*/
- public static RequestBeanMeta create(Method m, int i, PropertyStore ps) {
- if (! hasAnnotation(Request.class, m, i))
+ public static RequestBeanMeta create(MethodParamInfo mpi, PropertyStore ps) {
+ if (! mpi.hasAnnotation(Request.class))
return null;
- return new RequestBeanMeta.Builder(ps).apply(m, i).build();
+ return new RequestBeanMeta.Builder(ps).apply(mpi).build();
}
/**
@@ -55,7 +54,8 @@ public class RequestBeanMeta {
* @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link Request}.
*/
public static RequestBeanMeta create(Class<?> c, PropertyStore ps) {
- if (! hasAnnotation(Request.class, c))
+ ClassInfo ci = ClassInfo.lookup(c);
+ if (! ci.hasAnnotation(Request.class))
return null;
return new RequestBeanMeta.Builder(ps).apply(c).build();
}
@@ -90,34 +90,37 @@ public class RequestBeanMeta {
this.ps = ps;
}
- Builder apply(Method m, int i) {
- return apply(m.getParameterTypes()[i]).apply(getAnnotation(Request.class, m, i));
+ Builder apply(MethodParamInfo mpi) {
+ return apply(mpi.getParameterType()).apply(mpi.getAnnotation(Request.class));
}
Builder apply(Class<?> c) {
- apply(getAnnotation(Request.class, c));
+ ClassInfo ci = ClassInfo.lookup(c);
+ apply(ci.getAnnotation(Request.class));
this.cm = BeanContext.DEFAULT.getClassMeta(c);
for (Method m : ClassUtils.getAllMethods(c, false)) {
+
if (isPublic(m)) {
- assertNoAnnotations(m, Request.class, ResponseHeader.class, ResponseBody.class, ResponseStatus.class);
+ MethodInfo mi = getMethodInfo(m);
+ mi.assertNoAnnotations(Request.class, ResponseHeader.class, ResponseBody.class, ResponseStatus.class);
String n = m.getName();
- if (hasAnnotation(Body.class, m)) {
+ if (mi.hasAnnotation(Body.class)) {
assertNoArgs(m, Body.class);
assertReturnNotVoid(m, Body.class);
properties.put(n, RequestBeanPropertyMeta.create(BODY, Body.class, m));
- } else if (hasAnnotation(Header.class, m)) {
+ } else if (mi.hasAnnotation(Header.class)) {
assertNoArgs(m, Header.class);
assertReturnNotVoid(m, Header.class);
properties.put(n, RequestBeanPropertyMeta.create(HEADER, Header.class, m));
- } else if (hasAnnotation(Query.class, m)) {
+ } else if (mi.hasAnnotation(Query.class)) {
assertNoArgs(m, Query.class);
assertReturnNotVoid(m, Query.class);
properties.put(n, RequestBeanPropertyMeta.create(QUERY, Query.class, m));
- } else if (hasAnnotation(FormData.class, m)) {
+ } else if (mi.hasAnnotation(FormData.class)) {
assertNoArgs(m, FormData.class);
assertReturnNotVoid(m, FormData.class);
properties.put(n, RequestBeanPropertyMeta.create(FORMDATA, FormData.class, m));
- } else if (hasAnnotation(Path.class, m)) {
+ } else if (mi.hasAnnotation(Path.class)) {
assertNoArgs(m, Path.class);
assertReturnNotVoid(m, Path.class);
properties.put(n, RequestBeanPropertyMeta.create(PATH, Path.class, m));
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
index ca0d2c5..f72a349 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
@@ -30,7 +30,7 @@ public class RequestBeanPropertyMeta {
static RequestBeanPropertyMeta.Builder create(HttpPartType partType, Class<? extends Annotation> c, Method m) {
HttpPartSchemaBuilder sb = HttpPartSchema.create().name(getPropertyName(m));
- for (Annotation a : getAnnotationsParentFirst(c, m))
+ for (Annotation a : getMethodInfo(m).getAnnotationsParentFirst(c))
sb.apply(a);
return new Builder().partType(partType).schema(sb.build()).getter(m);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
index eab256f..fe5d453 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java
@@ -45,14 +45,15 @@ public class ResponseBeanMeta {
* @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link Response}.
*/
public static ResponseBeanMeta create(Type t, PropertyStore ps) {
- if (! hasAnnotation(Response.class, t))
+ ClassInfo ci = ClassInfo.create(t);
+ if (! ci.hasAnnotation(Response.class))
return null;
Builder b = new Builder(ps);
if (Value.isType(t))
b.apply(Value.getParameterType(t));
else
b.apply(t);
- for (Response r : getAnnotationsParentFirst(Response.class, t))
+ for (Response r : ci.getAnnotationsParentFirst(Response.class))
b.apply(r);
return b.build();
}
@@ -67,7 +68,7 @@ public class ResponseBeanMeta {
* @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link Response}.
*/
public static ResponseBeanMeta create(Method m, PropertyStore ps) {
- if (! hasAnnotation(Response.class, m))
+ if (! getMethodInfo(m).hasAnnotation(Response.class))
return null;
Builder b = new Builder(ps);
Type t = m.getGenericReturnType();
@@ -75,7 +76,7 @@ public class ResponseBeanMeta {
b.apply(Value.getParameterType(t));
else
b.apply(t);
- for (Response r : getAnnotationsParentFirst(Response.class, m))
+ for (Response r : getMethodInfo(m).getAnnotationsParentFirst(Response.class))
b.apply(r);
return b.build();
}
@@ -83,23 +84,22 @@ public class ResponseBeanMeta {
/**
* Create metadata from specified method parameter.
*
- * @param m The method containing the parameter annotated with {@link Response}.
- * @param i The parameter index.
+ * @param mpi The method parameter.
* @param ps
* Configuration information used to instantiate part serializers and part parsers.
* <br>Can be <jk>null</jk>.
* @return Metadata about the class, or <jk>null</jk> if class not annotated with {@link Response}.
*/
- public static ResponseBeanMeta create(Method m, int i, PropertyStore ps) {
- if (! hasAnnotation(Response.class, m, i))
+ public static ResponseBeanMeta create(MethodParamInfo mpi, PropertyStore ps) {
+ if (! mpi.hasAnnotation(Response.class))
return null;
Builder b = new Builder(ps);
- Type t = m.getGenericParameterTypes()[i];
+ Type t = mpi.getGenericParameterType();
if (Value.isType(t))
b.apply(Value.getParameterType(t));
else
b.apply(t);
- for (Response r : getAnnotationsParentFirst(Response.class, m, i))
+ for (Response r : mpi.getAnnotationsParentFirst(Response.class))
b.apply(r);
return b.build();
}
@@ -166,17 +166,18 @@ public class ResponseBeanMeta {
this.cm = BeanContext.DEFAULT.getClassMeta(c);
for (Method m : ClassUtils.getAllMethods(c, false)) {
if (isPublic(m)) {
- assertNoAnnotations(m, Response.class, Body.class, Header.class, Query.class, FormData.class, Path.class);
- if (hasAnnotation(ResponseHeader.class, m)) {
+ MethodInfo mi = getMethodInfo(m);
+ mi.assertNoAnnotations(Response.class, Body.class, Header.class, Query.class, FormData.class, Path.class);
+ if (mi.hasAnnotation(ResponseHeader.class)) {
assertNoArgs(m, ResponseHeader.class);
assertReturnNotVoid(m, ResponseHeader.class);
- HttpPartSchema s = HttpPartSchema.create(getAnnotation(ResponseHeader.class, m), getPropertyName(m));
+ HttpPartSchema s = HttpPartSchema.create(getMethodInfo(m).getAnnotation(ResponseHeader.class), getPropertyName(m));
headerMethods.put(s.getName(), ResponseBeanPropertyMeta.create(RESPONSE_HEADER, s, m));
- } else if (hasAnnotation(ResponseStatus.class, m)) {
+ } else if (mi.hasAnnotation(ResponseStatus.class)) {
assertNoArgs(m, ResponseHeader.class);
assertReturnType(m, ResponseHeader.class, int.class, Integer.class);
statusMethod = ResponseBeanPropertyMeta.create(RESPONSE_STATUS, m);
- } else if (hasAnnotation(ResponseBody.class, m)) {
+ } else if (mi.hasAnnotation(ResponseBody.class)) {
Class<?>[] pt = m.getParameterTypes();
if (pt.length == 0)
assertReturnNotVoid(m, ResponseHeader.class);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/Utils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/Utils.java
index f227465..ea737fd 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/Utils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/Utils.java
@@ -12,8 +12,6 @@
// ***************************************************************************************************************************
package org.apache.juneau.httppart.bean;
-import static org.apache.juneau.internal.ClassUtils.*;
-
import java.beans.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
@@ -25,14 +23,6 @@ import org.apache.juneau.annotation.*;
*/
class Utils {
- @SafeVarargs
- static final void assertNoAnnotations(Method m, Class<? extends Annotation> a, Class<? extends Annotation>...c) throws InvalidAnnotationException {
- for (Class<? extends Annotation> cc : c) {
- if (hasAnnotation(cc, m))
- throw new InvalidAnnotationException("@{0} annotation cannot be used in a @{1} bean. Method=''{2}''", cc.getSimpleName(), a.getSimpleName(), m);
- }
- }
-
static void assertNoArgs(Method m, Class<?> a) throws InvalidAnnotationException {
if (m.getParameterTypes().length != 0)
throw new InvalidAnnotationException("Method with @{0} annotation cannot have arguments. Method=''{1}''", a.getSimpleName(), m);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 937a103..c281387 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -1113,256 +1113,6 @@ public final class ClassUtils {
return isParentClass(c, m.getReturnType());
}
- //-----------------------------------------------------------------------------------------------------------------
- // Method annotations.
- //-----------------------------------------------------------------------------------------------------------------
-
- /**
- * Returns all annotations of the specified type defined on the specified method.
- *
- * @param a
- * The annotation to search for.
- * @param m
- * The method to find the annotation on.
- * @param searchParentMethods
- * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces.
- * @param searchReturnType
- * If <jk>true</jk>, searches the return type on the method for the specified annotation.
- * @param parentFirst
- * If <jk>true</jk>, returns the results in parent-to-child order.
- * @return
- * A list of all matching annotations found, or an empty list if none found.
- */
- @SuppressWarnings("unchecked")
- public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, boolean searchParentMethods, boolean searchReturnType, boolean parentFirst) {
- List<T> l = new ArrayList<>();
- List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m);
- for (Method m2 : methods)
- for (Annotation a2 : m2.getAnnotations())
- if (a.isInstance(a2))
- l.add((T)a2);
- if (searchReturnType) {
- Type t = m.getGenericReturnType();
- if (Value.isType(t))
- appendAnnotations(a, Value.getParameterType(t), l);
- else
- appendAnnotations(a, t, l);
- }
- if (parentFirst)
- Collections.reverse(l);
- return l;
- }
-
- /**
- * Shortcut for calling <code>getAnnotations(a,m,<jk>true</jk>,<jk>true</jk>,<jk>false</jk>)</code>
- *
- * <p>
- * Annotations are ordered method first, then return class, then return superclasses.
- *
- * @param a The annotation to look for.
- * @param m The method being inspected.
- * @return All instances of the annotation with the
- */
- public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m) {
- return getAnnotations(a, m, true, true, false);
- }
-
- /**
- * Shortcut for calling <code>getAnnotations(a,m,<jk>true</jk>,<jk>true</jk>,<jk>true</jk>)</code>
- *
- * @param a The annotation to look for.
- * @param m The method being inspected.
- * @return All instances of the annotation with the
- */
- public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m) {
- return getAnnotations(a, m, true, true, true);
- }
-
- /**
- * Finds the annotation of the specified type defined on the specified method.
- *
- * @param a
- * The annotation to search for.
- * @param m
- * The method to find the annotation on.
- * @param searchParentMethods
- * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces.
- * <br>The search is performed in child-to-parent order.
- * @param searchReturnType
- * If <jk>true</jk>, searches the return type on the method for the specified annotation.
- * @return
- * The annotation if found, or <jk>null</jk> if not.
- */
- @SuppressWarnings("unchecked")
- public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, boolean searchParentMethods, boolean searchReturnType) {
- List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m);
- for (Method m2 : methods)
- for (Annotation a2 : m2.getAnnotations())
- if (a.isInstance(a2))
- return (T)a2;
- if (searchReturnType) {
- Type t = m.getGenericReturnType();
- if (Value.isType(t))
- return getAnnotation(a, Value.getParameterType(t));
- return getAnnotation(a, t);
- }
- return null;
- }
-
- /**
- * Shortcut for calling <code>getAnnotation(a,m,<jk>true</jk>,<jk>true</jk>)</code>
- *
- * @param a
- * The annotation to search for.
- * @param m
- * The method to find the annotation on.
- * @return
- * The annotation if found, or <jk>null</jk> if not.
- */
- public static <T extends Annotation> T getAnnotation(Class<T> a, Method m) {
- return getAnnotation(a, m, true, true);
- }
-
- //-----------------------------------------------------------------------------------------------------------------
- // Method argument annotations.
- //-----------------------------------------------------------------------------------------------------------------
-
- /**
- * Returns all annotations of the specified type defined on the specified method argument.
- *
- * @param a
- * The annotation to search for.
- * @param m
- * The method containing the argument to find the annotation on.
- * @param index
- * The argument index position.
- * @param searchParentMethods
- * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces.
- * @param searchArgType
- * If <jk>true</jk>, searches the argument type for the specified annotation.
- * @param parentFirst
- * If <jk>true</jk>, returns the results in parent-to-child order.
- * @return
- * A list of all matching annotations found, or an empty list if none found.
- */
- @SuppressWarnings("unchecked")
- public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index, boolean searchParentMethods, boolean searchArgType, boolean parentFirst) {
- List<T> l = new ArrayList<>();
- List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m);
- for (Method m2 : methods)
- for (Annotation a2 : m2.getParameterAnnotations()[index])
- if (a.isInstance(a2))
- l.add((T)a2);
- if (searchArgType) {
- Type t = m.getGenericParameterTypes()[index];
- if (Value.isType(t))
- appendAnnotations(a, Value.getParameterType(t), l);
- else
- appendAnnotations(a, t, l);
- }
- if (parentFirst)
- Collections.reverse(l);
- return l;
- }
-
- /**
- * Finds the annotation of the specified type defined on the specified method argument.
- *
- * @param a
- * The annotation to search for.
- * @param m
- * The method containing the argument to find the annotation on.
- * @param index
- * The argument index position.
- * @param searchParentMethods
- * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces.
- * <br>The search is performed in child-to-parent order.
- * @param searchArgType
- * If <jk>true</jk>, searches the argument type for the specified annotation.
- * @return
- * The annotation if found, or <jk>null</jk> if not.
- */
- @SuppressWarnings("unchecked")
- public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index, boolean searchParentMethods, boolean searchArgType) {
- List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m);
- for (Method m2 : methods)
- for (Annotation a2 : m2.getParameterAnnotations()[index])
- if (a.isInstance(a2))
- return (T)a2;
- if (searchArgType) {
- Type t = m.getGenericParameterTypes()[index];
- if (Value.isType(t))
- return getAnnotation(a, Value.getParameterType(t));
- return getAnnotation(a, t);
- }
- return null;
- }
-
- /**
- * Shortcut for calling <code>getAnnotation(a,m,index,<jk>true</jk>,<jk>true</jk>)</code>
- *
- * @param a The annotation to check for.
- * @param m The method containing the parameter to check.
- * @param index The parameter index.
- * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
- */
- public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index) {
- return getAnnotation(a, m, index, true, true);
- }
-
- /**
- * Shortcut for calling <code>getAnnotations(a, m, index, <jk>true</jk>, <jk>true</jk>, <jk>false</jk>);</code>
- *
- * @param a The annotation to look for.
- * @param m The method containing the parameter.
- * @param index The parameter index.
- * @return All instances of the annotation with the
- */
- public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index) {
- return getAnnotations(a, m, index, true, true, false);
- }
-
- /**
- * Shortcut for calling <code>getAnnotations(a, m, index, <jk>true</jk>, <jk>true</jk>, <jk>true</jk>);</code>
- *
- * @param a The annotation to look for.
- * @param m The method containing the parameter.
- * @param index The parameter index.
- * @return All instances of the annotation with the
- */
- public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m, int index) {
- return getAnnotations(a, m, index, true, true, true);
- }
-
- /**
- * Given a specific method, finds all declared methods with the same name and arguments on all
- * superclasses and interfaces.
- *
- * @param m The method to find matches against.
- * @return
- * All matching methods including the input method itself.
- * Methods are ordered from child-to-parent order.
- */
- public static List<Method> findMatchingMethods(Method m) {
- return findMatchingMethods(new ArrayList<Method>(), m, m.getDeclaringClass());
- }
-
- private static List<Method> findMatchingMethods(List<Method> l, Method m, Class<?> c) {
- for (Method m2 : c.getDeclaredMethods())
- if (isSameMethod(m, m2))
- l.add(m2);
- Class<?> pc = c.getSuperclass();
- if (pc != null)
- findMatchingMethods(l, m, pc);
- for (Class<?> ic : c.getInterfaces())
- findMatchingMethods(l, m, ic);
- return l;
- }
-
- private static boolean isSameMethod(Method m1, Method m2) {
- return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
- }
-
/**
* Locates the no-arg constructor for the specified class.
*
@@ -1739,43 +1489,12 @@ public final class ClassUtils {
* @return The bean with information about the method.
*/
public static MethodInfo getMethodInfo(Method m) {
+ if (m == null)
+ return null;
return new MethodInfo(m);
}
/**
- * Returns {@link MethodInfo} beans that describe the specified methods.
- *
- * @param m The methods to describe.
- * @return The beans with information about the methods.
- */
- public static MethodInfo[] getMethodInfo(Collection<Method> m) {
- MethodInfo[] mi = new MethodInfo[m.size()];
- int i = 0;
- for (Method mm : m)
- mi[i++] = getMethodInfo(mm);
- return mi;
- }
-
- /**
- * Simple bean that shows the name, parameter types, and return type of a method.
- */
- @SuppressWarnings("javadoc")
- public static class MethodInfo {
- public final String methodName;
- public final String[] parameterTypes;
- public final String returnType;
-
- MethodInfo(Method m) {
- methodName = m.getName();
- Type[] pt = m.getGenericParameterTypes();
- parameterTypes = new String[pt.length];
- for (int i = 0; i < pt.length; i++)
- parameterTypes[i] = BeanContext.DEFAULT.getClassMeta(pt[i]).toString();
- returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString();
- }
- }
-
- /**
* Creates an instance of the specified class.
*
* @param c
@@ -2366,68 +2085,6 @@ public final class ClassUtils {
}
/**
- * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
- *
- * @param a The annotation to check for.
- * @param m The method containing the parameter to check.
- * @param index The parameter index.
- * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value.
- */
- public static boolean hasAnnotation(Class<? extends Annotation> a, Method m, int index) {
- return getAnnotation(a, m, index) != null;
- }
-
- /**
- * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value.
- *
- * @param a The annotation to check for.
- * @param m The method to check.
- * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value.
- */
- public static boolean hasAnnotation(Class<? extends Annotation> a, Method m) {
- return getAnnotation(a, m) != null;
- }
-
- /**
- * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value.
- *
- * @param a The annotation to check for.
- * @param t The class to check.
- * @return <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value.
- */
- public static boolean hasAnnotation(Class<? extends Annotation> a, Type t) {
- return getAnnotation(a, t) != null;
- }
-
- /**
- * Similar to {@link Class#getAnnotation(Class)} except also searches annotations on interfaces.
- *
- * @param <T> The annotation class type.
- * @param a The annotation class.
- * @param t The annotated class.
- * @return The annotation, or <jk>null</jk> if not found.
- */
- public static <T extends Annotation> T getAnnotation(Class<T> a, Type t) {
- Class<?> c = toClass(t);
- if (c != null) {
- T t2 = getDeclaredAnnotation(a, c);
- if (t2 != null)
- return t2;
-
- t2 = getAnnotation(a, c.getSuperclass());
- if (t2 != null)
- return t2;
-
- for (Class<?> c2 : c.getInterfaces()) {
- t2 = getAnnotation(a, c2);
- if (t2 != null)
- return t2;
- }
- }
- return null;
- }
-
- /**
* Returns the specified annotation only if it's been declared on the specified class.
*
* <p>
@@ -2450,38 +2107,7 @@ public final class ClassUtils {
}
/**
- * Returns all instances of the specified annotation on the specified class.
- *
- * <p>
- * Searches all superclasses and superinterfaces.
- * Results are ordered child-to-parent.
- *
- * @param <T> The annotation class type.
- * @param a The annotation class type.
- * @param t The class being searched.
- * @return The found matches, or an empty array if annotation was not found.
- */
- public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Type t) {
- List<T> l = new LinkedList<>();
- appendAnnotations(a, t, l);
- return l;
- }
-
- /**
- * Same as {@link #getAnnotations(Class, Type)} but returns the list in parent-to-child order.
- *
- * @param a The annotation class type.
- * @param t The class being searched.
- * @return The found matches, or an empty array if annotation was not found.
- */
- public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Type t) {
- List<T> l = getAnnotations(a, t);
- Collections.reverse(l);
- return l;
- }
-
- /**
- * Same as {@link #getAnnotations(Class, Type)} except returns the annotations as a map with the keys being the
+ * Same as getAnnotations(Class, Type) except returns the annotations as a map with the keys being the
* class on which the annotation was found.
*
* <p>
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 007cd05..5b85c19 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
@@ -15,7 +15,6 @@ package org.apache.juneau.json;
import static org.apache.juneau.internal.StringUtils.*;
import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.json.annotation.*;
/**
@@ -34,7 +33,7 @@ public class JsonClassMeta extends ClassMetaExtended {
*/
public JsonClassMeta(ClassMeta<?> cm) {
super(cm);
- this.json = ClassUtils.getAnnotation(Json.class, getInnerClass());
+ this.json = cm.getClassInfo().getAnnotation(Json.class);
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 8b131f8..a51d095 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
@@ -13,7 +13,6 @@
package org.apache.juneau.jsonschema;
import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.jsonschema.annotation.*;
/**
@@ -32,7 +31,7 @@ public class JsonSchemaClassMeta extends ClassMetaExtended {
*/
public JsonSchemaClassMeta(ClassMeta<?> cm) throws Exception {
super(cm);
- Schema s = ClassUtils.getAnnotation(Schema.class, getInnerClass());
+ Schema s = cm.getClassInfo().getAnnotation(Schema.class);
schema = s == null ? ObjectMap.EMPTY_MAP : SchemaUtils.asMap(s);
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
index f45f7ce..eff0704 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/remote/RemoteInterfaceMeta.java
@@ -19,6 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
import java.lang.reflect.*;
import java.util.*;
+import org.apache.juneau.*;
+
/**
* Contains the meta-data about a remote proxy REST interface.
*
@@ -50,7 +52,8 @@ public class RemoteInterfaceMeta {
public RemoteInterfaceMeta(Class<?> c, String uri) {
this.c = c;
String path = "";
- List<RemoteInterface> rr = getAnnotationsParentFirst(RemoteInterface.class, c);
+ ClassInfo ci = ClassInfo.lookup(c);
+ List<RemoteInterface> rr = ci.getAnnotationsParentFirst(RemoteInterface.class);
for (RemoteInterface r : rr)
if (! r.path().isEmpty())
path = trimSlashes(r.path());
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 a60501a..660d259 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
@@ -13,7 +13,6 @@
package org.apache.juneau.urlencoding;
import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.urlencoding.annotation.*;
/**
@@ -31,7 +30,7 @@ public class UrlEncodingClassMeta extends ClassMetaExtended {
*/
public UrlEncodingClassMeta(ClassMeta<?> cm) {
super(cm);
- this.urlEncoding = ClassUtils.getAnnotation(UrlEncoding.class, getInnerClass());
+ this.urlEncoding = cm.getClassInfo().getAnnotation(UrlEncoding.class);
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 cffe7ab..1ac0e21 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
@@ -12,13 +12,11 @@
// ***************************************************************************************************************************
package org.apache.juneau.xml;
-import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import java.util.*;
import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
import org.apache.juneau.xml.annotation.*;
/**
@@ -39,9 +37,8 @@ public class XmlClassMeta extends ClassMetaExtended {
*/
public XmlClassMeta(ClassMeta<?> cm) {
super(cm);
- Class<?> c = getInnerClass();
- this.namespace = findNamespace(c);
- this.xml = ClassUtils.getAnnotation(Xml.class, c);
+ this.namespace = findNamespace(cm);
+ this.xml = cm.getClassInfo().getAnnotation(Xml.class);
if (xml != null) {
this.format = xml.format();
this.childName = nullIfEmpty(xml.childName());
@@ -100,12 +97,12 @@ public class XmlClassMeta extends ClassMetaExtended {
return namespace;
}
- private static Namespace findNamespace(Class<?> c) {
- if (c == null)
+ private static Namespace findNamespace(ClassMeta<?> cm) {
+ if (cm == null)
return null;
-
- List<Xml> xmls = getAnnotations(Xml.class, c);
- List<XmlSchema> schemas = getAnnotations(XmlSchema.class, c);
+ ClassInfo ci = cm.getClassInfo();
+ List<Xml> xmls = ci.getAnnotations(Xml.class);
+ List<XmlSchema> schemas = ci.getAnnotations(XmlSchema.class);
return XmlUtils.findNamespace(xmls, schemas);
}
}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodArg.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodArg.java
index d71d703..46b0576 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodArg.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodArg.java
@@ -13,9 +13,10 @@
package org.apache.juneau.rest.client.remote;
import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.httppart.HttpPartType.*;
-import java.lang.reflect.*;
+import org.apache.juneau.*;
+
+import static org.apache.juneau.httppart.HttpPartType.*;
import org.apache.juneau.http.annotation.*;
import org.apache.juneau.httppart.*;
@@ -107,17 +108,18 @@ public final class RemoteMethodArg {
return schema;
}
- static RemoteMethodArg create(Method m, int i) {
- if (hasAnnotation(Header.class, m, i)) {
- return new RemoteMethodArg(i, HEADER, HttpPartSchema.create(Header.class, m, i));
- } else if (hasAnnotation(Query.class, m, i)) {
- return new RemoteMethodArg(i, QUERY, HttpPartSchema.create(Query.class, m, i));
- } else if (hasAnnotation(FormData.class, m, i)) {
- return new RemoteMethodArg(i, FORMDATA, HttpPartSchema.create(FormData.class, m, i));
- } else if (hasAnnotation(Path.class, m, i)) {
- return new RemoteMethodArg(i, PATH, HttpPartSchema.create(Path.class, m, i));
- } else if (hasAnnotation(Body.class, m, i)) {
- return new RemoteMethodArg(i, BODY, HttpPartSchema.create(Body.class, m, i));
+ static RemoteMethodArg create(MethodParamInfo mpi) {
+ int i = mpi.getIndex();
+ if (mpi.hasAnnotation(Header.class)) {
+ return new RemoteMethodArg(i, HEADER, HttpPartSchema.create(Header.class, mpi));
+ } else if (mpi.hasAnnotation(Query.class)) {
+ return new RemoteMethodArg(i, QUERY, HttpPartSchema.create(Query.class, mpi));
+ } else if (mpi.hasAnnotation(FormData.class)) {
+ return new RemoteMethodArg(i, FORMDATA, HttpPartSchema.create(FormData.class, mpi));
+ } else if (mpi.hasAnnotation(Path.class)) {
+ return new RemoteMethodArg(i, PATH, HttpPartSchema.create(Path.class, mpi));
+ } else if (mpi.hasAnnotation(Body.class)) {
+ return new RemoteMethodArg(i, BODY, HttpPartSchema.create(Body.class, mpi));
}
return null;
}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodMeta.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodMeta.java
index 97f088e..87303f6 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodMeta.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodMeta.java
@@ -13,6 +13,7 @@
package org.apache.juneau.rest.client.remote;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.httppart.HttpPartType.*;
import java.lang.reflect.*;
@@ -86,7 +87,9 @@ public class RemoteMethodMeta {
Builder(String parentPath, Method m, boolean useMethodSignatures, String defaultMethod) {
- RemoteMethod rm = m.getAnnotation(RemoteMethod.class);
+ MethodInfo mi = getMethodInfo(m);
+
+ RemoteMethod rm = mi.getAnnotation(RemoteMethod.class);
httpMethod = rm == null ? "" : rm.method();
path = rm == null ? "" : rm.path();
@@ -109,8 +112,8 @@ public class RemoteMethodMeta {
fullPath = path.indexOf("://") != -1 ? path : (parentPath.isEmpty() ? urlEncodePath(path) : (trimSlashes(parentPath) + '/' + urlEncodePath(path)));
- for (int i = 0; i < m.getParameterTypes().length; i++) {
- RemoteMethodArg rma = RemoteMethodArg.create(m, i);
+ for (MethodParamInfo mpi : mi.getParams()) {
+ RemoteMethodArg rma = RemoteMethodArg.create(mpi);
boolean annotated = false;
if (rma != null) {
annotated = true;
@@ -128,13 +131,13 @@ public class RemoteMethodMeta {
else
annotated = false;
}
- RequestBeanMeta rmba = RequestBeanMeta.create(m, i, PropertyStore.DEFAULT);
+ RequestBeanMeta rmba = RequestBeanMeta.create(mpi, PropertyStore.DEFAULT);
if (rmba != null) {
annotated = true;
- requestArgs.add(new RemoteMethodBeanArg(i, null, rmba));
+ requestArgs.add(new RemoteMethodBeanArg(mpi.getIndex(), null, rmba));
}
if (! annotated) {
- otherArgs.add(new RemoteMethodArg(i, BODY, null));
+ otherArgs.add(new RemoteMethodArg(mpi.getIndex(), BODY, null));
}
}
}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodReturn.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodReturn.java
index eb985a9..7b9aa0d 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodReturn.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMethodReturn.java
@@ -12,8 +12,6 @@
// ***************************************************************************************************************************
package org.apache.juneau.rest.client.remote;
-import static org.apache.juneau.internal.ClassUtils.*;
-
import java.lang.reflect.*;
import org.apache.juneau.*;
@@ -38,7 +36,8 @@ public final class RemoteMethodReturn {
RemoteMethod rm = m.getAnnotation(RemoteMethod.class);
Class<?> rt = m.getReturnType();
RemoteReturn rv = rt == void.class ? RemoteReturn.NONE : rm == null ? RemoteReturn.BODY : rm.returns();
- if (hasAnnotation(Response.class, rt) && rt.isInterface()) {
+ ClassInfo rti = ClassInfo.lookup(rt);
+ if (rti.hasAnnotation(Response.class) && rt.isInterface()) {
this.meta = ResponseBeanMeta.create(m, PropertyStore.DEFAULT);
rv = RemoteReturn.BEAN;
} else {
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteResourceMeta.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteResourceMeta.java
index 9c786cd..f4afcd3 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteResourceMeta.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteResourceMeta.java
@@ -19,6 +19,8 @@ import static org.apache.juneau.internal.StringUtils.*;
import java.lang.reflect.*;
import java.util.*;
+import org.apache.juneau.*;
+
/**
* Contains the meta-data about a REST proxy class.
*
@@ -44,7 +46,8 @@ public class RemoteResourceMeta {
public RemoteResourceMeta(Class<?> c) {
String path = "";
- for (RemoteResource r : getAnnotationsParentFirst(RemoteResource.class, c))
+ ClassInfo ci = ClassInfo.lookup(c);
+ for (RemoteResource r : ci.getAnnotationsParentFirst(RemoteResource.class))
if (! r.path().isEmpty())
path = trimSlashes(r.path());
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
index e7ec31f..ad6d000 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
+import org.apache.juneau.*;
import org.apache.juneau.dto.swagger.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.rest.annotation.*;
@@ -67,7 +68,8 @@ public class BasicRestInfoProvider implements RestInfoProvider {
description;
Builder(RestContext context) {
- for (RestResource r : getAnnotationsParentFirst(RestResource.class, context.getResource().getClass())) {
+ ClassInfo ci = ClassInfo.lookup(context.getResource().getClass());
+ for (RestResource r : ci.getAnnotationsParentFirst(RestResource.class)) {
if (! r.siteName().isEmpty())
siteName = r.siteName();
if (r.title().length > 0)
@@ -164,7 +166,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
public String getMethodSummary(Method method, RestRequest req) throws Exception {
VarResolverSession vr = req.getVarResolverSession();
- String s = getAnnotation(RestMethod.class, method).summary();
+ String s = getMethodInfo(method).getAnnotation(RestMethod.class).summary();
if (s.isEmpty()) {
Operation o = getSwaggerOperation(method, req);
if (o != null)
@@ -220,7 +222,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
public String getMethodDescription(Method method, RestRequest req) throws Exception {
VarResolverSession vr = req.getVarResolverSession();
- String s = joinnl(getAnnotation(RestMethod.class, method).description());
+ String s = joinnl(getMethodInfo(method).getAnnotation(RestMethod.class).description());
if (s.isEmpty()) {
Operation o = getSwaggerOperation(method, req);
if (o != null)
@@ -398,7 +400,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
if (s != null) {
Map<String,OperationMap> sp = s.getPaths();
if (sp != null) {
- Map<String,Operation> spp = sp.get(fixMethodPath(getAnnotation(RestMethod.class, method).path()));
+ Map<String,Operation> spp = sp.get(fixMethodPath(getMethodInfo(method).getAnnotation(RestMethod.class).path()));
if (spp != null)
return spp.get(req.getMethod());
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
index bbad35b..9d3a7aa 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
@@ -41,7 +41,7 @@ public class ClientVersionMatcher extends RestMatcher {
*/
protected ClientVersionMatcher(String clientVersionHeader, java.lang.reflect.Method javaMethod) {
this.clientVersionHeader = isEmpty(clientVersionHeader) ? "X-Client-Version" : clientVersionHeader;
- RestMethod m = getAnnotation(RestMethod.class, javaMethod);
+ RestMethod m = getMethodInfo(javaMethod).getAnnotation(RestMethod.class);
range = new VersionRange(m.clientVersion());
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 66703de..50c20a3 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3228,7 +3228,7 @@ public final class RestContext extends BeanContext {
_destroyMethodParams = new ArrayList<>();
for (java.lang.reflect.Method method : resourceClass.getMethods()) {
- RestMethod a = ClassUtils.getAnnotation(RestMethod.class, method);
+ RestMethod a = ClassUtils.getMethodInfo(method).getAnnotation(RestMethod.class);
if (a != null) {
methodsFound.add(method.getName() + "," + emptyIfNull(firstNonEmpty(a.name(), a.method())) + "," + fixMethodPath(a.path()));
try {
@@ -4572,6 +4572,7 @@ public final class RestContext extends BeanContext {
Type[] pt = method.getGenericParameterTypes();
RestMethodParam[] rp = new RestMethodParam[pt.length];
PropertyStore ps = getPropertyStore();
+ MethodInfo mi = getMethodInfo(method);
for (int i = 0; i < pt.length; i++) {
@@ -4583,29 +4584,31 @@ public final class RestContext extends BeanContext {
rp[i] = RestParamDefaults.STANDARD_RESOLVERS.get(c);
}
- if (hasAnnotation(Header.class, method, i)) {
- rp[i] = new RestParamDefaults.HeaderObject(method, i, ps);
- } else if (hasAnnotation(Query.class, method, i)) {
- rp[i] = new RestParamDefaults.QueryObject(method, i, ps);
- } else if (hasAnnotation(FormData.class, method, i)) {
- rp[i] = new RestParamDefaults.FormDataObject(method, i, ps);
- } else if (hasAnnotation(Path.class, method, i)) {
- rp[i] = new RestParamDefaults.PathObject(method, i, ps, pathPattern);
- } else if (hasAnnotation(Body.class, method, i)) {
- rp[i] = new RestParamDefaults.BodyObject(method, i, ps);
- } else if (hasAnnotation(Request.class, method, i)) {
- rp[i] = new RestParamDefaults.RequestObject(method, i, ps);
- } else if (hasAnnotation(Response.class, method, i)) {
- rp[i] = new RestParamDefaults.ResponseObject(method, i, ps);
- } else if (hasAnnotation(ResponseHeader.class, method, i)) {
- rp[i] = new RestParamDefaults.ResponseHeaderObject(method, i, ps);
- } else if (hasAnnotation(ResponseStatus.class, method, i)) {
+ MethodParamInfo mpi = mi.getParam(i);
+
+ if (mpi.hasAnnotation(Header.class)) {
+ rp[i] = new RestParamDefaults.HeaderObject(mpi, ps);
+ } else if (mpi.hasAnnotation(Query.class)) {
+ rp[i] = new RestParamDefaults.QueryObject(mpi, ps);
+ } else if (mpi.hasAnnotation(FormData.class)) {
+ rp[i] = new RestParamDefaults.FormDataObject(mpi, ps);
+ } else if (mpi.hasAnnotation(Path.class)) {
+ rp[i] = new RestParamDefaults.PathObject(mpi, ps, pathPattern);
+ } else if (mpi.hasAnnotation(Body.class)) {
+ rp[i] = new RestParamDefaults.BodyObject(mpi, ps);
+ } else if (mpi.hasAnnotation(Request.class)) {
+ rp[i] = new RestParamDefaults.RequestObject(mpi, ps);
+ } else if (mpi.hasAnnotation(Response.class)) {
+ rp[i] = new RestParamDefaults.ResponseObject(mpi, ps);
+ } else if (mpi.hasAnnotation(ResponseHeader.class)) {
+ rp[i] = new RestParamDefaults.ResponseHeaderObject(mpi, ps);
+ } else if (mpi.hasAnnotation(ResponseStatus.class)) {
rp[i] = new RestParamDefaults.ResponseStatusObject(method, t);
- } else if (hasAnnotation(HasFormData.class, method, i)) {
- rp[i] = new RestParamDefaults.HasFormDataObject(method, i);
- } else if (hasAnnotation(HasQuery.class, method, i)) {
- rp[i] = new RestParamDefaults.HasQueryObject(method, i);
- } else if (hasAnnotation(org.apache.juneau.rest.annotation.Method.class, method, i)) {
+ } else if (mpi.hasAnnotation(HasFormData.class)) {
+ rp[i] = new RestParamDefaults.HasFormDataObject(mpi);
+ } else if (mpi.hasAnnotation(HasQuery.class)) {
+ rp[i] = new RestParamDefaults.HasQueryObject(mpi);
+ } else if (mpi.hasAnnotation(org.apache.juneau.rest.annotation.Method.class)) {
rp[i] = new RestParamDefaults.MethodObject(method, t);
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index a31ca75..95f19d6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -146,7 +146,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod> {
try {
- RestMethod m = getAnnotation(RestMethod.class, method);
+ RestMethod m = getMethodInfo(method).getAnnotation(RestMethod.class);
if (m == null)
throw new RestServletException("@RestMethod annotation not found on method ''{0}''", sig);
@@ -394,7 +394,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod> {
methodParams = context.findParams(method, false, pathPattern);
- if (hasAnnotation(Response.class, method))
+ if (getMethodInfo(method).hasAnnotation(Response.class))
responseMeta = ResponseBeanMeta.create(method, serializers.getPropertyStore());
// Need this to access methods in anonymous inner classes.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java
index a41b674..b81f9a3 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestMethodParam.java
@@ -114,8 +114,7 @@ import org.apache.juneau.utils.*;
public abstract class RestMethodParam {
final RestParamType paramType;
- final Method method;
- final int index;
+ final MethodParamInfo mpi;
final String name;
final Type type;
final Class<?> c;
@@ -124,17 +123,15 @@ public abstract class RestMethodParam {
* Constructor.
*
* @param paramType The Swagger parameter type.
- * @param method The method on which the parameter resides.
- * @param index The method parameter index.
+ * @param mpi The method parameter.
* @param name
* The parameter name.
* Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
* @param type The object type to convert the parameter to.
*/
- protected RestMethodParam(RestParamType paramType, Method method, int index, String name, Type type) {
+ protected RestMethodParam(RestParamType paramType, MethodParamInfo mpi, String name, Type type) {
this.paramType = paramType;
- this.method = method;
- this.index = index;
+ this.mpi = mpi;
this.name = name;
this.type = type;
this.c = type instanceof Class ? (Class<?>)type : type instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType() : null;
@@ -144,25 +141,23 @@ public abstract class RestMethodParam {
* Constructor.
*
* @param paramType The Swagger parameter type.
- * @param method The method on which the parameter resides.
- * @param index The method parameter index.
+ * @param mpi The method parameter.
* @param name
* The parameter name.
* Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
*/
- protected RestMethodParam(RestParamType paramType, Method method, int index, String name) {
- this(paramType, method, index, name, method.getGenericParameterTypes()[index]);
+ protected RestMethodParam(RestParamType paramType, MethodParamInfo mpi, String name) {
+ this(paramType, mpi, name, mpi.getGenericParameterType());
}
/**
* Constructor.
*
* @param paramType The Swagger parameter type.
- * @param method The method on which the parameter resides.
- * @param index The method parameter index.
+ * @param mpi The method parameter.
*/
- protected RestMethodParam(RestParamType paramType, Method method, int index) {
- this(paramType, method, index, null, method.getGenericParameterTypes()[index]);
+ protected RestMethodParam(RestParamType paramType, MethodParamInfo mpi) {
+ this(paramType, mpi, null, mpi.getGenericParameterType());
}
/**
@@ -172,7 +167,7 @@ public abstract class RestMethodParam {
* @param type The object type to convert the parameter to.
*/
protected RestMethodParam(RestParamType paramType, Type type) {
- this(paramType, null, -1, null, type);
+ this(paramType, null, null, type);
}
/**
@@ -185,7 +180,7 @@ public abstract class RestMethodParam {
* @param type The object type to convert the parameter to.
*/
protected RestMethodParam(RestParamType paramType, String name, Type type) {
- this(paramType, null, -1, name, type);
+ this(paramType, null, name, type);
}
/**
@@ -219,6 +214,15 @@ public abstract class RestMethodParam {
}
/**
+ * Returns the parameter info.
+ *
+ * @return The parameter info.
+ */
+ public MethodParamInfo getMethodParamInfo() {
+ return mpi;
+ }
+
+ /**
* Returns the parameter name for this parameter as shown in the Swagger doc.
*
* @return the parameter name for this parameter.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index 7e632aa..8dbc40c 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -195,14 +195,14 @@ class RestParamDefaults {
private final HttpPartParser partParser;
private final HttpPartSchema schema;
- protected PathObject(Method m, int i, PropertyStore ps, UrlPathPattern pathPattern) {
- super(PATH, m, i, getName(m, i, pathPattern));
- this.schema = HttpPartSchema.create(Path.class, m, i);
+ protected PathObject(MethodParamInfo mpi, PropertyStore ps, UrlPathPattern pathPattern) {
+ super(PATH, mpi, getName(mpi, pathPattern));
+ this.schema = HttpPartSchema.create(Path.class, mpi);
this.partParser = createPartParser(schema.getParser(), ps);
}
- private static String getName(Method m, int i, UrlPathPattern pathPattern) {
- for (Path h : getAnnotations(Path.class, m, i)) {
+ private static String getName(MethodParamInfo mpi, UrlPathPattern pathPattern) {
+ for (Path h : mpi.getAnnotations(Path.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
@@ -210,9 +210,11 @@ class RestParamDefaults {
}
if (pathPattern != null) {
int idx = 0;
+ int i = mpi.getIndex();
+ Method m = mpi.getMethod();
for (int j = 0; j < i; j++)
- if (getAnnotation(Path.class, m, i) != null)
+ if (getMethodInfo(m).getParam(i).getAnnotation(Path.class) != null)
idx++;
String[] vars = pathPattern.getVars();
@@ -227,7 +229,7 @@ class RestParamDefaults {
return pathPattern.getVars()[idx];
}
- throw new InternalServerError("@Path used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@Path used without name or value on method parameter ''{0}''.", mpi);
}
@Override /* RestMethodParam */
@@ -239,9 +241,9 @@ class RestParamDefaults {
static final class BodyObject extends RestMethodParam {
private final HttpPartSchema schema;
- protected BodyObject(Method m, int i, PropertyStore ps) {
- super(BODY, m, i);
- this.schema = HttpPartSchema.create(Body.class, m, i);
+ protected BodyObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(BODY, mpi);
+ this.schema = HttpPartSchema.create(Body.class, mpi);
}
@Override /* RestMethodParam */
@@ -254,20 +256,20 @@ class RestParamDefaults {
private final HttpPartParser partParser;
private final HttpPartSchema schema;
- protected HeaderObject(Method m, int i, PropertyStore ps) {
- super(HEADER, m, i, getName(m, i));
- this.schema = HttpPartSchema.create(Header.class, m, i);
+ protected HeaderObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(HEADER, mpi, getName(mpi));
+ this.schema = HttpPartSchema.create(Header.class, mpi);
this.partParser = createPartParser(schema.getParser(), ps);
}
- private static String getName(Method m, int i) {
- for (Header h : getAnnotations(Header.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (Header h : mpi.getAnnotations(Header.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@Header used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@Header used without name or value on method parameter ''{0}''.", mpi);
}
@Override /* RestMethodParam */
@@ -279,9 +281,9 @@ class RestParamDefaults {
static final class RequestObject extends RestMethodParam {
private final RequestBeanMeta meta;
- protected RequestObject(Method m, int i, PropertyStore ps) {
- super(RESPONSE_BODY, m, i);
- this.meta = RequestBeanMeta.create(method, i, ps);
+ protected RequestObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(RESPONSE_BODY, mpi);
+ this.meta = RequestBeanMeta.create(mpi, ps);
}
@Override /* RestMethodParam */
@@ -293,23 +295,23 @@ class RestParamDefaults {
static final class ResponseHeaderObject extends RestMethodParam {
final ResponsePartMeta meta;
- protected ResponseHeaderObject(Method m, int i, PropertyStore ps) {
- super(RESPONSE_HEADER, m, i, getName(m, i));
- HttpPartSchema schema = HttpPartSchema.create(ResponseHeader.class, method, i);
+ protected ResponseHeaderObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(RESPONSE_HEADER, mpi, getName(mpi));
+ HttpPartSchema schema = HttpPartSchema.create(ResponseHeader.class, mpi);
this.meta = new ResponsePartMeta(HttpPartType.HEADER, schema, createPartSerializer(schema.getSerializer(), ps));
if (getTypeClass() != Value.class)
throw new InternalServerError("Invalid type {0} specified with @ResponseHeader annotation. It must be Value.", type);
}
- private static String getName(Method m, int i) {
- for (ResponseHeader h : getAnnotations(ResponseHeader.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (ResponseHeader h : mpi.getAnnotations(ResponseHeader.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@ResponseHeader used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@ResponseHeader used without name or value on method parameter ''{0}''.", mpi);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -336,9 +338,9 @@ class RestParamDefaults {
static final class ResponseObject extends RestMethodParam {
final ResponseBeanMeta meta;
- protected ResponseObject(Method m, int i, PropertyStore ps) {
- super(RESPONSE, m, i);
- this.meta = ResponseBeanMeta.create(m, i, ps);
+ protected ResponseObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(RESPONSE, mpi);
+ this.meta = ResponseBeanMeta.create(mpi, ps);
if (getTypeClass() != Value.class)
throw new InternalServerError("Invalid type {0} specified with @Response annotation. It must be Value.", type);
}
@@ -386,7 +388,7 @@ class RestParamDefaults {
static final class MethodObject extends RestMethodParam {
protected MethodObject(Method m, Type t) throws ServletException {
- super(OTHER, null, null);
+ super(OTHER, (MethodParamInfo)null);
if (t != String.class)
throw new RestServletException("Use of @Method annotation on parameter that is not a String on method ''{0}''", m);
}
@@ -402,24 +404,24 @@ class RestParamDefaults {
private final HttpPartParser partParser;
private final HttpPartSchema schema;
- protected FormDataObject(Method m, int i, PropertyStore ps) {
- super(FORM_DATA, m, i, getName(m, i));
- this.schema = HttpPartSchema.create(FormData.class, m, i);
+ protected FormDataObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(FORM_DATA, mpi, getName(mpi));
+ this.schema = HttpPartSchema.create(FormData.class, mpi);
this.partParser = createPartParser(schema.getParser(), ps);
this.multiPart = schema.getCollectionFormat() == HttpPartSchema.CollectionFormat.MULTI;
if (multiPart && ! isCollection(type))
- throw new InternalServerError("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", method);
+ throw new InternalServerError("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", mpi.getMethod());
}
- private static String getName(Method m, int i) {
- for (FormData h : getAnnotations(FormData.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (FormData h : mpi.getAnnotations(FormData.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@FormData used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@FormData used without name or value on method parameter ''{0}''.", mpi);
}
@Override /* RestMethodParam */
@@ -435,24 +437,24 @@ class RestParamDefaults {
private final HttpPartParser partParser;
private final HttpPartSchema schema;
- protected QueryObject(Method m, int i, PropertyStore ps) {
- super(QUERY, m, i, getName(m, i));
- this.schema = HttpPartSchema.create(Query.class, m, i);
+ protected QueryObject(MethodParamInfo mpi, PropertyStore ps) {
+ super(QUERY, mpi, getName(mpi));
+ this.schema = HttpPartSchema.create(Query.class, mpi);
this.partParser = createPartParser(schema.getParser(), ps);
this.multiPart = schema.getCollectionFormat() == HttpPartSchema.CollectionFormat.MULTI;
if (multiPart && ! isCollection(type))
- throw new InternalServerError("Use of multipart flag on @Query parameter that's not an array or Collection on method ''{0}''", method);
+ throw new InternalServerError("Use of multipart flag on @Query parameter that's not an array or Collection on method ''{0}''", mpi.getMethod());
}
- private static String getName(Method m, int i) {
- for (Query h : getAnnotations(Query.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (Query h : mpi.getAnnotations(Query.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@Query used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@Query used without name or value on method param ''{0}''.", mpi);
}
@Override /* RestMethodParam */
@@ -465,20 +467,20 @@ class RestParamDefaults {
static final class HasFormDataObject extends RestMethodParam {
- protected HasFormDataObject(Method m, int i) throws ServletException {
- super(FORM_DATA, m, i, getName(m, i));
+ protected HasFormDataObject(MethodParamInfo mpi) throws ServletException {
+ super(FORM_DATA, mpi, getName(mpi));
if (getType() != Boolean.class && getType() != boolean.class)
- throw new RestServletException("Use of @HasForm annotation on parameter that is not a boolean on method ''{0}''", m);
+ throw new RestServletException("Use of @HasForm annotation on parameter that is not a boolean on method ''{0}''", mpi.getMethod());
}
- private static String getName(Method m, int i) {
- for (HasFormData h : getAnnotations(HasFormData.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (HasFormData h : mpi.getAnnotations(HasFormData.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@HasFormData used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@HasFormData used without name or value on method parameter ''{o}''.", mpi);
}
@Override /* RestMethodParam */
@@ -490,20 +492,20 @@ class RestParamDefaults {
static final class HasQueryObject extends RestMethodParam {
- protected HasQueryObject(Method m, int i) throws ServletException {
- super(QUERY, m, i, getName(m, i));
+ protected HasQueryObject(MethodParamInfo mpi) throws ServletException {
+ super(QUERY, mpi, getName(mpi));
if (getType() != Boolean.class && getType() != boolean.class)
- throw new RestServletException("Use of @HasQuery annotation on parameter that is not a boolean on method ''{0}''", m);
+ throw new RestServletException("Use of @HasQuery annotation on parameter that is not a boolean on method ''{0}''", mpi.getMethod());
}
- private static String getName(Method m, int i) {
- for (HasQuery h : getAnnotations(HasQuery.class, m, i)) {
+ private static String getName(MethodParamInfo mpi) {
+ for (HasQuery h : mpi.getAnnotations(HasQuery.class)) {
if (! h.name().isEmpty())
return h.name();
if (! h.value().isEmpty())
return h.value();
}
- throw new InternalServerError("@HasQuery used without name or value on method ''{0}'' parameter ''{1}''.", m, i);
+ throw new InternalServerError("@HasQuery used without name or value on method parameter ''{0}''.", mpi);
}
@Override /* RestMethodParam */
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
index d49236e..a01e6de 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServlet.java
@@ -23,7 +23,7 @@ import java.util.logging.*;
import javax.servlet.*;
import javax.servlet.http.*;
-import org.apache.juneau.internal.*;
+import org.apache.juneau.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.exception.*;
@@ -121,7 +121,8 @@ public abstract class RestServlet extends HttpServlet {
public synchronized String getPath() {
if (context != null)
return context.getPath();
- for (RestResource rr : ClassUtils.getAnnotations(RestResource.class, this.getClass()))
+ ClassInfo ci = ClassInfo.lookup(getClass());
+ for (RestResource rr : ci.getAnnotations(RestResource.class))
if (! rr.path().isEmpty())
return trimSlashes(rr.path());
return "";
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index 9786207..bbf7fb4 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -226,7 +226,8 @@ final class SwaggerGenerator {
continue;
Method m = sm.method;
- RestMethod rm = getAnnotation(RestMethod.class, m);
+ MethodInfo mi = getMethodInfo(m);
+ RestMethod rm = mi.getAnnotation(RestMethod.class);
String mn = m.getName();
// Get the operation from the existing swagger so far.
@@ -323,7 +324,7 @@ final class SwaggerGenerator {
for (RestMethodParam mp : context.getRestMethodParams(m)) {
RestParamType in = mp.getParamType();
- int index = mp.index;
+ MethodParamInfo mpi = mp.getMethodParamInfo();
if (in.isAny(BODY, QUERY, FORM_DATA, HEADER, PATH)) {
@@ -337,26 +338,26 @@ final class SwaggerGenerator {
param.append("name", mp.name);
try {
- if (mp.method != null) {
+ if (mpi != null) {
if (in == BODY) {
- for (Body a : getAnnotationsParentFirst(Body.class, mp.method, mp.index))
+ for (Body a : mpi.getAnnotationsParentFirst(Body.class))
merge(param, a);
} else if (in == QUERY) {
- for (Query a : getAnnotationsParentFirst(Query.class, mp.method, mp.index))
+ for (Query a : mpi.getAnnotationsParentFirst(Query.class))
merge(param, a);
} else if (in == FORM_DATA) {
- for (FormData a : getAnnotationsParentFirst(FormData.class, mp.method, mp.index))
+ for (FormData a : mpi.getAnnotationsParentFirst(FormData.class))
merge(param, a);
} else if (in == HEADER) {
- for (Header a : getAnnotationsParentFirst(Header.class, mp.method, mp.index))
+ for (Header a : mpi.getAnnotationsParentFirst(Header.class))
merge(param, a);
} else if (in == PATH) {
- for (Path a : getAnnotationsParentFirst(Path.class, mp.method, mp.index))
+ for (Path a : mpi.getAnnotationsParentFirst(Path.class))
merge(param, a);
}
}
} catch (ParseException e) {
- throw new SwaggerException(e, "Malformed swagger JSON object encountered in {0} class {1} method {2} parameter {3}", in, c, m, index);
+ throw new SwaggerException(e, "Malformed swagger JSON object encountered in {0} class {1} method parameter {2}", in, c, mpi);
}
@@ -378,21 +379,22 @@ final class SwaggerGenerator {
ObjectMap responses = op.getObjectMap("responses", true);
- for (Class<?> ec : m.getExceptionTypes()) {
- if (hasAnnotation(Response.class, ec)) {
- List<Response> la = getAnnotationsParentFirst(Response.class, ec);
+ for (ClassInfo eci : mi.getExceptionInfos()) {
+ if (eci.hasAnnotation(Response.class)) {
+ List<Response> la = eci.getAnnotationsParentFirst(Response.class);
Set<Integer> codes = getCodes(la, 500);
for (Response a : la) {
for (Integer code : codes) {
ObjectMap om = responses.getObjectMap(String.valueOf(code), true);
merge(om, a);
if (! om.containsKey("schema"))
- om.appendSkipEmpty("schema", getSchema(om.getObjectMap("schema"), ec));
+ om.appendSkipEmpty("schema", getSchema(om.getObjectMap("schema"), eci.getInnerClass()));
}
}
- for (Method ecm : getAllMethods(ec, true)) {
- if (hasAnnotation(ResponseHeader.class, ecm)) {
- ResponseHeader a = ecm.getAnnotation(ResponseHeader.class);
+ for (Method ecm : getAllMethods(eci.getInnerClass(), true)) {
+ MethodInfo ecmi = getMethodInfo(ecm);
+ if (ecmi.hasAnnotation(ResponseHeader.class)) {
+ ResponseHeader a = ecmi.getAnnotation(ResponseHeader.class);
String ha = a.name();
for (Integer code : codes) {
ObjectMap header = responses.getObjectMap(String.valueOf(code), true).getObjectMap("headers", true).getObjectMap(ha, true);
@@ -404,8 +406,8 @@ final class SwaggerGenerator {
}
}
- if (hasAnnotation(Response.class, m)) {
- List<Response> la = getAnnotationsParentFirst(Response.class, m);
+ if (mi.hasAnnotation(Response.class)) {
+ List<Response> la = mi.getAnnotationsParentFirst(Response.class);
Set<Integer> codes = getCodes(la, 200);
for (Response a : la) {
for (Integer code : codes) {
@@ -416,10 +418,11 @@ final class SwaggerGenerator {
addBodyExamples(sm, om, true, m.getGenericReturnType());
}
}
- if (hasAnnotation(Response.class, m.getReturnType())) {
+ if (mi.getReturnTypeInfo().hasAnnotation(Response.class)) {
for (Method ecm : getAllMethods(m.getReturnType(), true)) {
- if (hasAnnotation(ResponseHeader.class, ecm)) {
- ResponseHeader a = ecm.getAnnotation(ResponseHeader.class);
+ MethodInfo ecmi = getMethodInfo(ecm);
+ if (ecmi.hasAnnotation(ResponseHeader.class)) {
+ ResponseHeader a = ecmi.getAnnotation(ResponseHeader.class);
String ha = a.name();
for (Integer code : codes) {
ObjectMap header = responses.getObjectMap(String.valueOf(code), true).getObjectMap("headers", true).getObjectMap(ha, true);
@@ -440,9 +443,10 @@ final class SwaggerGenerator {
for (RestMethodParam mp : context.getRestMethodParams(m)) {
RestParamType in = mp.getParamType();
+ MethodParamInfo mpi = mp.getMethodParamInfo();
if (in == RESPONSE_HEADER) {
- List<ResponseHeader> la = getAnnotationsParentFirst(ResponseHeader.class, mp.method, mp.index);
+ List<ResponseHeader> la = mpi.getAnnotationsParentFirst(ResponseHeader.class);
Set<Integer> codes = getCodes2(la, 200);
for (ResponseHeader a : la) {
for (Integer code : codes) {
@@ -453,7 +457,7 @@ final class SwaggerGenerator {
}
} else if (in == RESPONSE) {
- List<Response> la = getAnnotationsParentFirst(Response.class, mp.method, mp.index);
+ List<Response> la = mpi.getAnnotationsParentFirst(Response.class);
Set<Integer> codes = getCodes(la, 200);
for (Response a : la) {
for (Integer code : codes) {