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 b15e810 Tests
b15e810 is described below
commit b15e810fd1862cdbadf2aad38f238f54314c0f79
Author: JamesBognar <[email protected]>
AuthorDate: Wed May 9 18:49:19 2018 -0400
Tests
---
.../apache/juneau/utils/TransformCacheTest.java | 170 ++++++++++++
.../org/apache/juneau/internal/ClassUtils.java | 98 ++-----
.../java/org/apache/juneau/internal/Transform.java | 30 +++
.../org/apache/juneau/internal/TransformCache.java | 186 +++++++++++++
.../apache/juneau/rest/test/NoParserInputTest.java | 13 +-
.../org/apache/juneau/rest/RestMethodParam.java | 52 +++-
.../org/apache/juneau/rest/RestParamDefaults.java | 300 ++++++++++-----------
.../org/apache/juneau/rest/annotation/Body.java | 6 +-
.../juneau/rest/BasicRestInfoProviderTest.java | 17 +-
.../apache/juneau/rest/annotation/BodyTest.java | 157 +++++++++--
10 files changed, 740 insertions(+), 289 deletions(-)
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/TransformCacheTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/TransformCacheTest.java
new file mode 100644
index 0000000..49c16ed
--- /dev/null
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/TransformCacheTest.java
@@ -0,0 +1,170 @@
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.internal.TransformCache.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class TransformCacheTest {
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // Constructors.
+
//-----------------------------------------------------------------------------------------------------------------
+
+ public static class A {
+ private String f;
+ public A(String f) {
+ this.f = f;
+ }
+ public A(int f) {
+ this.f = String.valueOf(f);
+ }
+ public A(Integer f) {
+ this.f = String.valueOf(f);
+ }
+ }
+ @Test
+ public void stringConstructor() {
+ assertEquals("foo", get(String.class,
A.class).transform("foo").f);
+ }
+ @Test
+ public void intConstructor() {
+ assertEquals("1", get(int.class, A.class).transform(1).f);
+ }
+ @Test
+ public void integerConstructor() {
+ assertEquals("2", get(Integer.class, A.class).transform(2).f);
+ }
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // fromString methods.
+
//-----------------------------------------------------------------------------------------------------------------
+
+ public static class D1 {
+ private String f;
+ public static D1 create(String f) {
+ D1 d = new D1(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_create() {
+ assertEquals("foo", get(String.class,
D1.class).transform("foo").f);
+ }
+
+ public static class D2 {
+ private String f;
+ public static D2 fromString(String f) {
+ D2 d = new D2(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_fromString() {
+ assertEquals("foo", get(String.class,
D2.class).transform("foo").f);
+ }
+
+ public static class D3 {
+ private String f;
+ public static D3 fromValue(String f) {
+ D3 d = new D3(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_fromValue() {
+ assertEquals("foo", get(String.class,
D3.class).transform("foo").f);
+ }
+
+ public static class D4 {
+ private String f;
+ public static D4 valueOf(String f) {
+ D4 d = new D4(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_valueOf() {
+ assertEquals("foo", get(String.class,
D4.class).transform("foo").f);
+ }
+
+ public static class D5 {
+ private String f;
+ public static D5 parse(String f) {
+ D5 d = new D5(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_parse() {
+ assertEquals("foo", get(String.class,
D5.class).transform("foo").f);
+ }
+
+ public static class D6 {
+ private String f;
+ public static D6 parseString(String f) {
+ D6 d = new D6(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_parseString() {
+ assertEquals("foo", get(String.class,
D6.class).transform("foo").f);
+ }
+
+ public static class D7 {
+ private String f;
+ public static D7 forName(String f) {
+ D7 d = new D7(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_forName() {
+ assertEquals("foo", get(String.class,
D7.class).transform("foo").f);
+ }
+
+ public static class D8 {
+ private String f;
+ public static D8 forString(String f) {
+ D8 d = new D8(); d.f = f; return d;
+ }
+ }
+ @Test
+ public void fromString_forString() {
+ assertEquals("foo", get(String.class,
D8.class).transform("foo").f);
+ }
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // fromX methods.
+
//-----------------------------------------------------------------------------------------------------------------
+
+ public static class X {}
+
+ public static class E1 {
+ private String f;
+ public static E1 create(X x) {
+ E1 e = new E1(); e.f = "ok"; return e;
+ }
+ }
+ @Test
+ public void fromX_create() {
+ assertEquals("ok", get(X.class, E1.class).transform(new X()).f);
+ }
+
+ public static class E2 {
+ private String f;
+ public static E2 fromX(X x) {
+ E2 e = new E2(); e.f = "ok"; return e;
+ }
+ }
+ @Test
+ public void fromX_fromX() {
+ assertEquals("ok", get(X.class, E2.class).transform(new X()).f);
+ }
+}
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 7ebbe94..da6c49b 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
@@ -28,31 +28,6 @@ import org.apache.juneau.utils.*;
public final class ClassUtils {
private static final Map<Class<?>,ConstructorCacheEntry>
CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();
- private static final Map<Class<?>,Stringify<?>> STRINGIFY_CACHE = new
ConcurrentHashMap<>();
-
- // Special cases.
- static {
-
- // TimeZone doesn't follow any standard conventions.
- STRINGIFY_CACHE.put(TimeZone.class, new
Stringify<TimeZone>(TimeZone.class){
- @Override
- public TimeZone fromString(String s) {
- return TimeZone.getTimeZone(s);
- }
- @Override
- public String toString(TimeZone tz) {
- return tz.getID();
- }
- });
-
- // Locale(String) doesn't work on strings like "ja_JP".
- STRINGIFY_CACHE.put(Locale.class, new
Stringify<Locale>(Locale.class){
- @Override
- public Locale fromString(String s) {
- return Locale.forLanguageTag(s.replace('_',
'-'));
- }
- });
- }
/**
* Given the specified list of objects, return readable names for the
class types of the objects.
@@ -1897,6 +1872,21 @@ public final class ClassUtils {
}
/**
+ * Find the public static creator method on the specified class.
+ *
+ * @param oc The created type.
+ * @param ic The argument type.
+ * @param name The method name.
+ * @return The static method, or <jk>null</jk> if it couldn't be found.
+ */
+ public static Method findPublicStaticCreateMethod(Class<?> oc, Class<?>
ic, String name) {
+ for (Method m : oc.getMethods())
+ if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) &&
hasName(m, name) && hasReturnType(m, oc) && hasArgs(m, ic))
+ return m;
+ return null;
+ }
+
+ /**
* Constructs a new instance of the specified class from the specified
string.
*
* <p>
@@ -1912,9 +1902,9 @@ public final class ClassUtils {
* @param s The string to create the instance from.
* @return A new object instance, or <jk>null</jk> if a method for
converting the string to an object could not be found.
*/
- @SuppressWarnings({ "unchecked" })
public static <T> T fromString(Class<T> c, String s) {
- return (T)getStringify(c).fromString(s);
+ Transform<String,T> t = TransformCache.get(String.class, c);
+ return t == null ? null : t.transform(s);
}
/**
@@ -1932,7 +1922,8 @@ public final class ClassUtils {
public static String toString(Object o) {
if (o == null)
return null;
- return getStringify(o.getClass()).toString(o);
+ Transform<Object,String> t =
(Transform<Object,String>)TransformCache.get(o.getClass(), String.class);
+ return t == null ? o.toString() : t.transform(o);
}
/**
@@ -1992,57 +1983,6 @@ public final class ClassUtils {
}
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static Stringify getStringify(Class c) {
- Stringify fs = STRINGIFY_CACHE.get(c);
- if (fs == null) {
- for (Iterator<Class<?>> i = getParentClasses(c, false,
true); i.hasNext(); ) {
- Class c2 = i.next();
- fs = STRINGIFY_CACHE.get(c2);
- if (fs != null) {
- STRINGIFY_CACHE.put(c, fs);
- break;
- }
- }
- if (fs == null) {
- fs = new Stringify(c);
- STRINGIFY_CACHE.put(c, fs);
- }
- }
- return fs;
- }
-
- @SuppressWarnings({"unchecked","rawtypes"})
- private static class Stringify<T> {
- final Constructor<?> constructor;
- final Method fromStringMethod;
- final Class<? extends Enum> enumClass;
-
- Stringify(Class<?> c) {
- enumClass = c.isEnum() ? (Class<? extends Enum>)c :
null;
- fromStringMethod = enumClass != null ? null :
findPublicFromStringMethod(c);
- constructor = enumClass != null || fromStringMethod !=
null ? null : findPublicConstructor(c, String.class);
- }
-
- public T fromString(String s) {
- try {
- if (fromStringMethod != null)
- return (T)fromStringMethod.invoke(null,
s);
- if (constructor != null)
- return (T)constructor.newInstance(s);
- if (enumClass != null)
- return (T)Enum.valueOf(enumClass, s);
- return null;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public String toString(T t) {
- return t.toString();
- }
- }
-
/**
* Returns the simple name of a class.
*
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java
new file mode 100644
index 0000000..9d673aa
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Transform.java
@@ -0,0 +1,30 @@
+//
***************************************************************************************************************************
+// * 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.internal;
+
+/**
+ * An interface for creating objects from other objects such as a
<code>String</code> or <code>Reader</code>.
+ *
+ * @param <I> Input type.
+ * @param <O> Output type.
+ */
+public interface Transform<I,O> {
+
+ /**
+ * Method for instantiating an object from another object.
+ *
+ * @param in The input object.
+ * @return The output object.
+ */
+ public O transform(I in);
+}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java
new file mode 100644
index 0000000..0869e05
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/TransformCache.java
@@ -0,0 +1,186 @@
+//
***************************************************************************************************************************
+// * 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.internal;
+
+import java.util.concurrent.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Cache of object that convert POJOs to and from common types such as
strings, readers, and input streams.
+ */
+public class TransformCache {
+ private static final
ConcurrentHashMap<Class<?>,Map<Class<?>,Transform<?,?>>> CACHE = new
ConcurrentHashMap<>();
+
+ /**
+ * Represents a non-existent transform.
+ */
+ public static final Transform<Object,Object> NULL = new
Transform<Object,Object>() {
+ @Override
+ public Object transform(Object in) {
+ return null;
+ }
+ };
+
+ // Special cases.
+ static {
+
+ // TimeZone doesn't follow any standard conventions.
+ add(String.class, TimeZone.class,
+ new Transform<String,TimeZone>() {
+ @Override public TimeZone transform(String in) {
+ return TimeZone.getTimeZone(in);
+ }
+ }
+ );
+ add(TimeZone.class, String.class,
+ new Transform<TimeZone,String>() {
+ @Override public String transform(TimeZone in) {
+ return in.getID();
+ }
+ }
+ );
+
+ // Locale(String) doesn't work on strings like "ja_JP".
+ add(String.class, Locale.class,
+ new Transform<String,Locale>() {
+ @Override
+ public Locale transform(String in) {
+ return
Locale.forLanguageTag(in.replace('_', '-'));
+ }
+ }
+ );
+ }
+
+ /**
+ * Adds a transform for the specified input/output types.
+ *
+ * @param ic The input type.
+ * @param oc The output type.
+ * @param t The transform for converting the input to the output.
+ */
+ public static synchronized void add(Class<?> ic, Class<?> oc,
Transform<?,?> t) {
+ Map<Class<?>,Transform<?,?>> m = CACHE.get(oc);
+ if (m == null) {
+ m = new ConcurrentHashMap<>();
+ CACHE.put(oc, m);
+ }
+ m.put(ic, t);
+ }
+
+ /**
+ * Returns the transform for converting the specified input type to the
specified output type.
+ *
+ * @param ic The input type.
+ * @param oc The output type.
+ * @return The transform for performing the conversion, or
<jk>null</jk> if the conversion cannot be made.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <I,O> Transform<I,O> get(final Class<I> ic, final
Class<O> oc) {
+
+ if (ic == null || oc == null)
+ return null;
+
+ Map<Class<?>,Transform<?,?>> m = CACHE.get(oc);
+ if (m == null) {
+ m = new ConcurrentHashMap<>();
+ CACHE.putIfAbsent(oc, m);
+ m = CACHE.get(oc);
+ }
+
+ Transform t = m.get(ic);
+ if (t != null)
+ return t == NULL ? null : t;
+
+ for (Iterator<Class<?>> i = ClassUtils.getParentClasses(ic,
false, true); i.hasNext(); ) {
+ Class pic = i.next();
+ t = m.get(pic);
+ if (t != null) {
+ m.put(pic, t);
+ return t == NULL ? null : t;
+ }
+ }
+
+ if (ic == oc) {
+ t = new Transform<I,O>() {
+ @Override public O transform(I in) {
+ return (O)in;
+ }
+ };
+ } else if (ic == String.class) {
+ if (oc.isEnum()) {
+ t = new Transform<String,O>() {
+ @Override
+ public O transform(String in) {
+ return (O)Enum.valueOf((Class<?
extends Enum>)oc, in);
+ }
+ };
+ } else {
+ final Method fromStringMethod =
ClassUtils.findPublicFromStringMethod(oc);
+ if (fromStringMethod != null) {
+ t = new Transform<String,O>() {
+ @Override
+ public O transform(String in) {
+ try {
+ return
(O)fromStringMethod.invoke(null, in);
+ } catch (Exception e) {
+ throw new
RuntimeException(e);
+ }
+ }
+ };
+ }
+ }
+ }
+
+ if (t == null) {
+ Method createMethod =
ClassUtils.findPublicStaticCreateMethod(oc, ic, "create");
+ if (createMethod == null)
+ createMethod =
ClassUtils.findPublicStaticCreateMethod(oc, ic, "from" + ic.getSimpleName());
+ if (createMethod != null) {
+ final Method cm = createMethod;
+ t = new Transform<I,O>() {
+ @Override
+ public O transform(I in) {
+ try {
+ return
(O)cm.invoke(null, in);
+ } catch (Exception e) {
+ throw new
RuntimeException(e);
+ }
+ }
+ };
+ } else {
+ final Constructor<?> c =
ClassUtils.findPublicConstructor(oc, ic);
+ if (c != null && ! ClassUtils.isDeprecated(c)) {
+ t = new Transform<I,O>() {
+ @Override
+ public O transform(I in) {
+ try {
+ return
(O)c.newInstance(in);
+ } catch (Exception e) {
+ throw new
RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ }
+ }
+
+ if (t == null)
+ t = NULL;
+
+ m.put(ic, t);
+
+ return t == NULL ? null : t;
+ }
+}
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/NoParserInputTest.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/NoParserInputTest.java
index 0c9b2a3..fa0ce0a 100644
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/NoParserInputTest.java
+++
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/NoParserInputTest.java
@@ -12,8 +12,6 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest.test;
-import static javax.servlet.http.HttpServletResponse.*;
-import static org.apache.juneau.rest.test.TestUtils.*;
import static org.junit.Assert.*;
import org.apache.juneau.rest.client.*;
@@ -45,17 +43,10 @@ public class NoParserInputTest extends RestTestcase {
//====================================================================================================
// @Body annotated PushbackReader.
- // This should always fail since the servlet reader is not a pushback
reader.
//====================================================================================================
@Test
public void testPushbackReader() throws Exception {
- try {
- plainTextClient.doPut(URL +
"/testPushbackReader?noTrace=true", "foo").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_BAD_REQUEST,
- "Invalid argument type passed to the following
method:",
- "'public java.lang.String
org.apache.juneau.rest.test.NoParserInputResource.testPushbackReader(java.io.PushbackReader)
throws java.lang.Exception'");
- }
+ String r = plainTextClient.doPut(URL + "/testPushbackReader",
"foo").getResponseAsString();
+ assertEquals("foo", r);
}
}
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 ebaf289..31692dc 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
@@ -115,38 +115,67 @@ import org.apache.juneau.utils.*;
public abstract class RestMethodParam {
final RestParamType paramType;
+ final Method method;
final String name;
final Type type;
+ final Class<?> c;
final ObjectMap metaData;
/**
* Constructor.
*
* @param paramType The Swagger parameter type.
+ * @param method The method on which the parameter resides.
+ * @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.
+ * @param metaData Swagger metadata.
+ */
+ protected RestMethodParam(RestParamType paramType, Method method,
String name, Type type, ObjectMap metaData) {
+ this.paramType = paramType;
+ this.method = method;
+ this.name = name;
+ this.type = type;
+ this.c = type instanceof Class ? (Class<?>)type : type
instanceof ParameterizedType ? (Class<?>)((ParameterizedType)type).getRawType()
: null;
+ this.metaData = metaData;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param paramType The Swagger parameter type.
+ * @param type The object type to convert the parameter to.
+ */
+ protected RestMethodParam(RestParamType paramType, Type type) {
+ this(paramType, null, null, type, ObjectMap.EMPTY_MAP);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param paramType The Swagger parameter type.
* @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, String name, Type
type) {
- this(paramType, name, type, ObjectMap.EMPTY_MAP);
+ this(paramType, null, name, type, ObjectMap.EMPTY_MAP);
}
/**
* Constructor.
*
* @param paramType The Swagger parameter type.
+ * @param method The method on which the parameter resides.
* @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.
- * @param metaData Swagger metadata.
*/
- protected RestMethodParam(RestParamType paramType, String name, Type
type, ObjectMap metaData) {
- this.paramType = paramType;
- this.name = name;
- this.type = type;
- this.metaData = metaData;
+ protected RestMethodParam(RestParamType paramType, Method method,
String name, Type type) {
+ this(paramType, method, name, type, ObjectMap.EMPTY_MAP);
}
/**
@@ -207,6 +236,15 @@ public abstract class RestMethodParam {
}
/**
+ * Returns the parameter class type.
+ *
+ * @return the parameter class type.
+ */
+ public Class<?> getTypeClass() {
+ return c;
+ }
+
+ /**
* Performs validation on the parameter.
*
* @throws InternalServerError
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 aef5e5b..a0a33c0 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
@@ -145,7 +145,7 @@ class RestParamDefaults {
static final class HttpServletRequestObject extends RestMethodParam {
protected HttpServletRequestObject() {
- super(OTHER, null, HttpServletRequest.class);
+ super(OTHER, HttpServletRequest.class);
}
@Override /* RestMethodParam */
@@ -157,7 +157,7 @@ class RestParamDefaults {
static final class HttpServletResponseObject extends RestMethodParam {
protected HttpServletResponseObject() {
- super(OTHER, null, HttpServletResponse.class);
+ super(OTHER, HttpServletResponse.class);
}
@Override /* RestMethodParam */
@@ -169,7 +169,7 @@ class RestParamDefaults {
static final class RestRequestObject extends RestMethodParam {
protected RestRequestObject() {
- super(OTHER, null, RestRequest.class);
+ super(OTHER, RestRequest.class);
}
@Override /* RestMethodParam */
@@ -181,7 +181,7 @@ class RestParamDefaults {
static final class RestResponseObject extends RestMethodParam {
protected RestResponseObject() {
- super(OTHER, null, RestResponse.class);
+ super(OTHER, RestResponse.class);
}
@Override /* RestMethodParam */
@@ -547,11 +547,15 @@ class RestParamDefaults {
//-------------------------------------------------------------------------------------------------------------------
static final class PathObject extends RestMethodParam {
- private final Method method;
protected PathObject(Method method, Path a, Type type,
PropertyStore ps, RestMethodParam existing) {
- super(PATH, firstNonEmpty(a.name(), a.value(), existing
== null ? null : existing.name), type, getMetaData(a, castOrNull(existing,
PathObject.class)));
- this.method = method;
+ super(PATH, method, firstNonEmpty(a.name(), a.value(),
existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, PathObject.class)));
+ }
+
+ @Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (isEmpty(name))
+ throw new InternalServerError("@Path used
without name or value on method ''{0}''.", method);
}
@Override /* RestMethodParam */
@@ -581,22 +585,25 @@ class RestParamDefaults {
.appendSkipEmpty("example", joinnl(a.example()))
;
}
-
- @Override /* RestMethodParqm */
- public void validate() throws InternalServerError {
- if (isEmpty(name))
- throw new InternalServerError("@Path used
without name or value on method ''{0}''.", method);
- }
}
static final class BodyObject extends RestMethodParam {
+
+ private final Transform<Reader,?> readerTransform;
+ private final Transform<InputStream,?> inputStreamTransform;
protected BodyObject(Method method, Body a, Type type,
RestMethodParam existing) {
- super(BODY, null, type, getMetaData(a,
castOrNull(existing, BodyObject.class)));
+ super(BODY, method, null, type, getMetaData(a,
castOrNull(existing, BodyObject.class)));
+ readerTransform = TransformCache.get(Reader.class,
getTypeClass());
+ inputStreamTransform =
TransformCache.get(InputStream.class, getTypeClass());
}
@Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
+ if (readerTransform != null)
+ return
readerTransform.transform(req.getReader()); // Also passes Reader through.
+ if (inputStreamTransform != null)
+ return
inputStreamTransform.transform(req.getInputStream()); // Also passes
InputStream through.
return req.getBody().asType(type);
}
@@ -633,16 +640,20 @@ class RestParamDefaults {
}
static final class HeaderObject extends RestMethodParam {
- private final Method method;
private final HttpPartParser partParser;
protected HeaderObject(Method method, Header a, Type type,
PropertyStore ps, RestMethodParam existing) {
- super(HEADER, firstNonEmpty(a.name(), a.value(),
existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, HeaderObject.class)));
- this.method = method;
+ super(HEADER, method, firstNonEmpty(a.name(),
a.value(), existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, HeaderObject.class)));
this.partParser = a.parser() ==
HttpPartParser.Null.class ? null : ClassUtils.newInstance(HttpPartParser.class,
a.parser(), true, ps);
}
@Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (isEmpty(name))
+ throw new InternalServerError("@Header used
without name or value on method ''{0}''.", method);
+ }
+
+ @Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
return req.getHeaders().get(partParser, name, type);
}
@@ -676,51 +687,42 @@ class RestParamDefaults {
.appendSkipEmpty("example", joinnl(a.example()))
;
}
-
- @Override /* RestMethodParqm */
- public void validate() throws InternalServerError {
- if (isEmpty(name))
- throw new InternalServerError("@Header used
without name or value on method ''{0}''.", method);
- }
}
static final class ResponseHeaderObject extends RestMethodParam {
- private final Method method;
final HttpPartSerializer partSerializer;
protected ResponseHeaderObject(Method method, ResponseHeader a,
Type type, PropertyStore ps, RestMethodParam existing) {
- super(RESPONSE_HEADER, firstNonEmpty(a.name(),
a.value(), existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, ResponseHeaderObject.class)));
- this.method = method;
+ super(RESPONSE_HEADER, method, firstNonEmpty(a.name(),
a.value(), existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, ResponseHeaderObject.class)));
this.partSerializer = a.serializer() ==
HttpPartSerializer.Null.class ? null :
ClassUtils.newInstance(HttpPartSerializer.class, a.serializer(), true, ps);
}
+ @Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (isEmpty(name))
+ throw new InternalServerError("@ResponseHeader
used without name or value on method ''{0}''.", method);
+ if (getTypeClass() == null)
+ throw new InternalServerError("Invalid type {0}
specified with @ResponseHeader annotation. It must be a subclass of Value.",
type);
+ if (ClassUtils.findNoArgConstructor(getTypeClass(),
Visibility.PUBLIC) == null)
+ throw new InternalServerError("Invalid type {0}
specified with @ResponseHeader annotation. It must have a public no-arg
constructor.", type);
+ }
+
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override /* RestMethodParam */
public Object resolve(RestRequest req, final RestResponse res)
throws Exception {
- if (type instanceof Class) {
- Class<?> c = (Class<?>)type;
- if (ClassUtils.isParentClass(Value.class, c)) {
- try {
- Value<Object> v =
(Value<Object>)c.newInstance();
- v.listener(new ValueListener() {
- @Override
- public void
onSet(Object newValue) {
-
res.setHeader(name, partSerializer.serialize(HttpPartType.HEADER, newValue));
- }
- });
- String def =
getMetaData().getString("default");
- if (def != null) {
- Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
-
v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
- }
-
- return v;
- } catch (Exception e) {
- throw new RestException(500,
"Invalid type {0} specified with @ResponseHeader annotation. It must have a
public no-arg constructor.", type);
- }
+ Value<Object> v =
(Value<Object>)getTypeClass().newInstance();
+ v.listener(new ValueListener() {
+ @Override
+ public void onSet(Object newValue) {
+ res.setHeader(name,
partSerializer.serialize(HttpPartType.HEADER, newValue));
}
+ });
+ String def = getMetaData().getString("default");
+ if (def != null) {
+ Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
+ v.set(JsonParser.DEFAULT.parse(def,
req.getBeanSession().getClassMeta(pc)));
}
- throw new RestException(500, "Invalid type {0}
specified with @ResponseHeader annotation. It must be a subclass of Value.",
type);
+ return v;
}
public HttpPartSerializer getPartSerializer() {
@@ -763,47 +765,38 @@ class RestParamDefaults {
}
return om;
}
-
- @Override /* RestMethodParqm */
- public void validate() throws InternalServerError {
- if (isEmpty(name))
- throw new InternalServerError("@ResponseHeader
used without name or value on method ''{0}''.", method);
- }
}
static final class ResponseObject extends RestMethodParam {
protected ResponseObject(Method method, Response a, Type type,
PropertyStore ps, RestMethodParam existing) {
- super(RESPONSE, "body", type, getMetaData(a,
castOrNull(existing, ResponseObject.class)));
+ super(RESPONSE, method, "body", type, getMetaData(a,
castOrNull(existing, ResponseObject.class)));
+ }
+
+ @Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (getTypeClass() == null)
+ throw new InternalServerError("Invalid type {0}
specified with @Response annotation. It must be a subclass of Value.", type);
+ if (ClassUtils.findNoArgConstructor(getTypeClass(),
Visibility.PUBLIC) == null)
+ throw new InternalServerError("Invalid type {0}
specified with @Response annotation. It must have a public no-arg
constructor.", type);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override /* RestMethodParam */
public Object resolve(RestRequest req, final RestResponse res)
throws Exception {
- if (type instanceof Class) {
- Class<?> c = (Class<?>)type;
- if (ClassUtils.isParentClass(Value.class, c)) {
- try {
- Value<Object> v =
(Value<Object>)c.newInstance();
- v.listener(new ValueListener() {
- @Override
- public void
onSet(Object newValue) {
-
res.setOutput(newValue);
- }
- });
- String def =
getMetaData().getString("default");
- if (def != null) {
- Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
-
v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
- }
-
- return v;
- } catch (Exception e) {
- throw new RestException(500,
"Invalid type {0} specified with @ResponseHeader annotation. It must have a
public no-arg constructor.", type);
- }
+ Value<Object> v = (Value<Object>)c.newInstance();
+ v.listener(new ValueListener() {
+ @Override
+ public void onSet(Object newValue) {
+ res.setOutput(newValue);
}
+ });
+ String def = getMetaData().getString("default");
+ if (def != null) {
+ Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
+ v.set(JsonParser.DEFAULT.parse(def,
req.getBeanSession().getClassMeta(pc)));
}
- throw new RestException(500, "Invalid type {0}
specified with @ResponseHeader annotation. It must be a subclass of Value.",
type);
+ return v;
}
private static ObjectMap getMetaData(Response a, ResponseObject
existing) {
@@ -826,36 +819,33 @@ class RestParamDefaults {
static final class ResponseStatusObject extends RestMethodParam {
protected ResponseStatusObject(Method method, Status a, Type
type, PropertyStore ps, RestMethodParam existing) {
- super(RESPONSE_STATUS, "", type, getMetaData(a,
castOrNull(existing, ResponseStatusObject.class)));
+ super(RESPONSE_STATUS, method, "", type, getMetaData(a,
castOrNull(existing, ResponseStatusObject.class)));
+ }
+
+ @Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (getTypeClass() == null)
+ throw new InternalServerError("Invalid type {0}
specified with @ResponseStatus annotation. It must be a subclass of Value.",
type);
+ if (ClassUtils.findNoArgConstructor(getTypeClass(),
Visibility.PUBLIC) == null)
+ throw new InternalServerError("Invalid type {0}
specified with @ResponseStatus annotation. It must have a public no-arg
constructor.", type);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override /* RestMethodParam */
public Object resolve(RestRequest req, final RestResponse res)
throws Exception {
- if (type instanceof Class) {
- Class<?> c = (Class<?>)type;
- if (ClassUtils.isParentClass(Value.class, c)) {
- try {
- Value<Object> v =
(Value<Object>)c.newInstance();
- v.listener(new ValueListener() {
- @Override
- public void
onSet(Object newValue) {
-
res.setStatus(Integer.parseInt(newValue.toString()));
- }
- });
- String def =
getMetaData().getString("default");
- if (def != null) {
- Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
-
v.set(JsonParser.DEFAULT.parse(def, req.getBeanSession().getClassMeta(pc)));
- }
-
- return v;
- } catch (Exception e) {
- throw new RestException(500,
"Invalid type {0} specified with @Status annotation. It must have a public
no-arg constructor.", type);
- }
+ Value<Object> v = (Value<Object>)c.newInstance();
+ v.listener(new ValueListener() {
+ @Override
+ public void onSet(Object newValue) {
+
res.setStatus(Integer.parseInt(newValue.toString()));
}
+ });
+ String def = getMetaData().getString("default");
+ if (def != null) {
+ Class<?> pc =
ClassUtils.resolveParameterType(Value.class, 0, c);
+ v.set(JsonParser.DEFAULT.parse(def,
req.getBeanSession().getClassMeta(pc)));
}
- throw new RestException(500, "Invalid type {0}
specified with @Status annotation. It must be a subclass of Value.", type);
+ return v;
}
private static ObjectMap getMetaData(Status a,
ResponseStatusObject existing) {
@@ -886,18 +876,22 @@ class RestParamDefaults {
}
static final class FormDataObject extends RestMethodParam {
- private final Method method;
private final boolean multiPart;
private final HttpPartParser partParser;
- private final Type type;
protected FormDataObject(Method method, FormData a, Type type,
PropertyStore ps, RestMethodParam existing) {
- super(FORM_DATA, firstNonEmpty(a.name(), a.value(),
existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, FormDataObject.class)));
- this.method = method;
- this.type = type;
+ super(FORM_DATA, method, firstNonEmpty(a.name(),
a.value(), existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, FormDataObject.class)));
this.multiPart = a.multipart();
this.partParser = a.parser() ==
HttpPartParser.Null.class ? null : ClassUtils.newInstance(HttpPartParser.class,
a.parser(), true, ps);
}
+
+ @Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (isEmpty(name))
+ throw new InternalServerError("@FormData used
without name or value on method ''{0}''.", method);
+ 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);
+ }
@Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
@@ -935,31 +929,27 @@ class RestParamDefaults {
.appendSkipEmpty("example", joinnl(a.example()))
;
}
-
- @Override /* RestMethodParqm */
- public void validate() throws InternalServerError {
- if (isEmpty(name))
- throw new InternalServerError("@FormData used
without name or value on method ''{0}''.", method);
- 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);
- }
}
static final class QueryObject extends RestMethodParam {
private final boolean multiPart;
- private final Type type;
- private final Method method;
private final HttpPartParser partParser;
protected QueryObject(Method method, Query a, Type type,
PropertyStore ps, RestMethodParam existing) {
- super(QUERY, firstNonEmpty(a.name(), a.value(),
existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, QueryObject.class)));
- this.type = type;
- this.method = method;
+ super(QUERY, method, firstNonEmpty(a.name(), a.value(),
existing == null ? null : existing.name), type, getMetaData(a,
castOrNull(existing, QueryObject.class)));
this.multiPart = a.multipart();
this.partParser = a.parser() ==
HttpPartParser.Null.class ? null : ClassUtils.newInstance(HttpPartParser.class,
a.parser(), true, ps);
}
@Override /* RestMethodParam */
+ public void validate() throws InternalServerError {
+ if (isEmpty(name))
+ throw new InternalServerError("@Query used
without name or value on method ''{0}''.", method);
+ 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);
+ }
+
+ @Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
if (multiPart)
return req.getQuery().getAll(partParser, name,
type);
@@ -995,20 +985,12 @@ class RestParamDefaults {
.appendSkipEmpty("example", joinnl(a.example()))
;
}
-
- @Override /* RestMethodParqm */
- public void validate() throws InternalServerError {
- if (isEmpty(name))
- throw new InternalServerError("@Query used
without name or value on method ''{0}''.", method);
- 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);
- }
}
static final class HasFormDataObject extends RestMethodParam {
protected HasFormDataObject(Method method, HasFormData a, Type
type) throws ServletException {
- super(FORM_DATA, firstNonEmpty(a.name(), a.value()),
type);
+ super(FORM_DATA, method, firstNonEmpty(a.name(),
a.value()), type);
if (type != Boolean.class && type != boolean.class)
throw new RestServletException("Use of @HasForm
annotation on parameter that is not a boolean on method ''{0}''", method);
}
@@ -1023,7 +1005,7 @@ class RestParamDefaults {
static final class HasQueryObject extends RestMethodParam {
protected HasQueryObject(Method method, HasQuery a, Type type)
throws ServletException {
- super(QUERY, firstNonEmpty(a.name(), a.value()), type);
+ super(QUERY, method, firstNonEmpty(a.name(),
a.value()), type);
if (type != Boolean.class && type != boolean.class)
throw new RestServletException("Use of
@HasQuery annotation on parameter that is not a boolean on method ''{0}''",
method);
}
@@ -1036,23 +1018,21 @@ class RestParamDefaults {
}
static final class PathRemainderObject extends RestMethodParam {
-
- protected PathRemainderObject(Method method, Type type) throws
ServletException {
- super(OTHER, null, null);
- if (type != String.class)
- throw new RestServletException("Use of
@PathRemainder annotation on parameter that is not a String on method ''{0}''",
method);
+
+ protected PathRemainderObject(Method method, Type type) {
+ super(OTHER, method, null, type);
}
-
+
@Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
- return req.getPathMatch().getRemainder();
+ return ClassUtils.fromString(getTypeClass(),
req.getPathMatch().getRemainder());
}
}
static final class RestRequestPropertiesObject extends RestMethodParam {
protected RestRequestPropertiesObject() {
- super(OTHER, null, RequestProperties.class);
+ super(OTHER, RequestProperties.class);
}
@Override /* RestMethodParam */
@@ -1068,7 +1048,7 @@ class RestParamDefaults {
static final class ResourceBundleObject extends RestMethodParam {
protected ResourceBundleObject() {
- super(OTHER, null, ResourceBundle.class);
+ super(OTHER, ResourceBundle.class);
}
@Override /* RestMethodParam */
@@ -1080,7 +1060,7 @@ class RestParamDefaults {
static final class MessageBundleObject extends RestMethodParam {
protected MessageBundleObject() {
- super(OTHER, null, MessageBundle.class);
+ super(OTHER, MessageBundle.class);
}
@Override /* RestMethodParam */
@@ -1092,7 +1072,7 @@ class RestParamDefaults {
static final class InputStreamObject extends RestMethodParam {
protected InputStreamObject() {
- super(OTHER, null, InputStream.class);
+ super(OTHER, InputStream.class);
}
@Override /* RestMethodParam */
@@ -1104,7 +1084,7 @@ class RestParamDefaults {
static final class ServletInputStreamObject extends RestMethodParam {
protected ServletInputStreamObject() {
- super(OTHER, null, ServletInputStream.class);
+ super(OTHER, ServletInputStream.class);
}
@Override /* RestMethodParam */
@@ -1116,7 +1096,7 @@ class RestParamDefaults {
static final class ReaderObject extends RestMethodParam {
protected ReaderObject() {
- super(OTHER, null, Reader.class);
+ super(OTHER, Reader.class);
}
@Override /* RestMethodParam */
@@ -1128,7 +1108,7 @@ class RestParamDefaults {
static final class OutputStreamObject extends RestMethodParam {
protected OutputStreamObject() {
- super(OTHER, null, OutputStream.class);
+ super(OTHER, OutputStream.class);
}
@Override /* RestMethodParam */
@@ -1140,7 +1120,7 @@ class RestParamDefaults {
static final class ServletOutputStreamObject extends RestMethodParam {
protected ServletOutputStreamObject() {
- super(OTHER, null, ServletOutputStream.class);
+ super(OTHER, ServletOutputStream.class);
}
@Override /* RestMethodParam */
@@ -1152,7 +1132,7 @@ class RestParamDefaults {
static final class WriterObject extends RestMethodParam {
protected WriterObject() {
- super(OTHER, null, Writer.class);
+ super(OTHER, Writer.class);
}
@Override /* RestMethodParam */
@@ -1164,7 +1144,7 @@ class RestParamDefaults {
static final class RequestHeadersObject extends RestMethodParam {
protected RequestHeadersObject() {
- super(OTHER, null, RequestHeaders.class);
+ super(OTHER, RequestHeaders.class);
}
@Override /* RestMethodParam */
@@ -1176,7 +1156,7 @@ class RestParamDefaults {
static final class RequestQueryObject extends RestMethodParam {
protected RequestQueryObject() {
- super(OTHER, null, RequestQuery.class);
+ super(OTHER, RequestQuery.class);
}
@Override /* RestMethodParam */
@@ -1188,7 +1168,7 @@ class RestParamDefaults {
static final class RequestFormDataObject extends RestMethodParam {
protected RequestFormDataObject() {
- super(OTHER, null, RequestFormData.class);
+ super(OTHER, RequestFormData.class);
}
@Override /* RestMethodParam */
@@ -1200,7 +1180,7 @@ class RestParamDefaults {
static final class HttpMethodObject extends RestMethodParam {
protected HttpMethodObject() {
- super(OTHER, null, HttpMethod.class);
+ super(OTHER, HttpMethod.class);
}
@Override /* RestMethodParam */
@@ -1212,7 +1192,7 @@ class RestParamDefaults {
static final class RestLoggerObject extends RestMethodParam {
protected RestLoggerObject() {
- super(OTHER, null, RestLogger.class);
+ super(OTHER, RestLogger.class);
}
@Override /* RestMethodParam */
@@ -1224,7 +1204,7 @@ class RestParamDefaults {
static final class RestContextObject extends RestMethodParam {
protected RestContextObject() {
- super(OTHER, null, RestContext.class);
+ super(OTHER, RestContext.class);
}
@Override /* RestMethodParam */
@@ -1236,7 +1216,7 @@ class RestParamDefaults {
static final class ParserObject extends RestMethodParam {
protected ParserObject() {
- super(OTHER, null, Parser.class);
+ super(OTHER, Parser.class);
}
@Override /* RestMethodParam */
@@ -1248,7 +1228,7 @@ class RestParamDefaults {
static final class ReaderParserObject extends RestMethodParam {
protected ReaderParserObject() {
- super(OTHER, null, ReaderParser.class);
+ super(OTHER, ReaderParser.class);
}
@Override /* RestMethodParam */
@@ -1260,7 +1240,7 @@ class RestParamDefaults {
static final class InputStreamParserObject extends RestMethodParam {
protected InputStreamParserObject() {
- super(OTHER, null, InputStreamParser.class);
+ super(OTHER, InputStreamParser.class);
}
@Override /* RestMethodParam */
@@ -1272,7 +1252,7 @@ class RestParamDefaults {
static final class LocaleObject extends RestMethodParam {
protected LocaleObject() {
- super(OTHER, null, Locale.class);
+ super(OTHER, Locale.class);
}
@Override /* RestMethodParam */
@@ -1284,7 +1264,7 @@ class RestParamDefaults {
static final class SwaggerObject extends RestMethodParam {
protected SwaggerObject() {
- super(OTHER, null, Swagger.class);
+ super(OTHER, Swagger.class);
}
@Override /* RestMethodParam */
@@ -1296,7 +1276,7 @@ class RestParamDefaults {
static final class RequestPathMatchObject extends RestMethodParam {
protected RequestPathMatchObject() {
- super(OTHER, null, RequestPathMatch.class);
+ super(OTHER, RequestPathMatch.class);
}
@Override /* RestMethodParam */
@@ -1308,7 +1288,7 @@ class RestParamDefaults {
static final class RequestBodyObject extends RestMethodParam {
protected RequestBodyObject() {
- super(BODY, null, RequestBody.class);
+ super(BODY, RequestBody.class);
}
@Override /* RestMethodParam */
@@ -1320,7 +1300,7 @@ class RestParamDefaults {
static final class ConfigObject extends RestMethodParam {
protected ConfigObject() {
- super(OTHER, null, Config.class);
+ super(OTHER, Config.class);
}
@Override /* RestMethodParam */
@@ -1332,7 +1312,7 @@ class RestParamDefaults {
static final class UriContextObject extends RestMethodParam {
protected UriContextObject() {
- super(OTHER, null, UriContext.class);
+ super(OTHER, UriContext.class);
}
@Override /* RestMethodParam */
@@ -1344,7 +1324,7 @@ class RestParamDefaults {
static final class UriResolverObject extends RestMethodParam {
protected UriResolverObject() {
- super(OTHER, null, UriResolver.class);
+ super(OTHER, UriResolver.class);
}
@Override /* RestMethodParam */
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
index 9013981..9714566 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
@@ -21,13 +21,13 @@ import java.lang.annotation.*;
import org.apache.juneau.rest.*;
/**
- * Annotation that can be applied to a parameter of a {@link RestMethod
@RestMethod} annotated method to identify it as the HTTP
+ * Annotation that can be applied to a parameter of a {@link RestMethod
@RestMethod} annotated method or POJO class to identify it as the HTTP
* request body converted to a POJO.
*
* <h5 class='section'>Example:</h5>
* <p class='bcode'>
* <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
- * <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res,
<ja>@Body</ja> Person person) {
+ * <jk>public void</jk> addPerson(<ja>@Body</ja> Person person) {
* ...
* }
* </p>
@@ -36,7 +36,7 @@ import org.apache.juneau.rest.*;
* This is functionally equivalent to the following code...
* <p class='bcode'>
* <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
- * <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res) {
+ * <jk>public void</jk> addPerson(RestRequest req, RestResponse res) {
* Person person = req.getBody().asType(Person.<jk>class</jk>);
* ...
* }
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
index eb21173..17867f8 100644
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
@@ -30,6 +30,9 @@ import org.apache.juneau.utils.*;
import org.junit.*;
import org.junit.runners.*;
+/**
+ * Tests the {@link BasicRestInfoProvider} class.
+ */
@SuppressWarnings("javadoc")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BasicRestInfoProviderTest {
@@ -6615,12 +6618,6 @@ public class BasicRestInfoProviderTest {
@RestMethod(name=GET,path="/schema5")
public void ub05e(@Response UB05e b) {}
- @RestMethod(name=GET,path="/schema6")
- public void ub05f(@Response Integer b) {}
-
- @RestMethod(name=GET,path="/schema7")
- public void ub05g(@Response Boolean b) {}
-
public static class UB07 {}
@RestMethod(name=GET,path="/headers1")
@@ -6689,14 +6686,6 @@ public class BasicRestInfoProviderTest {
assertObjectEquals("{type:'string'}", getSwagger(new
UB()).getPaths().get("/schema5").get("get").getResponse(200).getSchema());
}
@Test
- public void ub05f_Response_onParameter_schema6() throws Exception {
- assertObjectEquals("{format:'int32',type:'integer'}",
getSwagger(new
UB()).getPaths().get("/schema6").get("get").getResponse(200).getSchema());
- }
- @Test
- public void ub05g_Response_onParameter_schema7() throws Exception {
- assertObjectEquals("{type:'boolean'}", getSwagger(new
UB()).getPaths().get("/schema7").get("get").getResponse(200).getSchema());
- }
- @Test
public void ub07_Response_onParameter_headers1() throws Exception {
assertObjectEquals("{foo:{type:'a'}}", getSwagger(new
UB()).getPaths().get("/headers1").get("get").getResponse(200).getHeaders());
}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
index dd76d36..f4aadef 100644
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
@@ -15,21 +15,31 @@ package org.apache.juneau.rest.annotation;
import static org.apache.juneau.http.HttpMethodName.*;
import static org.junit.Assert.*;
+import java.io.*;
+import java.util.*;
+
import javax.servlet.http.*;
+import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.util.*;
import org.junit.*;
import org.junit.runners.*;
-@SuppressWarnings("javadoc")
+/**
+ * Tests the {@link Body} annotation.
+ */
+@SuppressWarnings({"javadoc","serial"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BodyTest {
-
- private void call(Object resource, HttpServletRequest req,
HttpServletResponse res) throws Exception {
- RestContext rc = RestContext.create(resource).build();
- rc.getCallHandler().service(req, res);
+
+ private static Map<Class<?>,RestContext> CONTEXTS = new HashMap<>();
+
+ private static void call(Class<?> c, HttpServletRequest req,
HttpServletResponse res) throws Exception {
+ if (! CONTEXTS.containsKey(c))
+ CONTEXTS.put(c,
RestContext.create(c.newInstance()).build());
+ CONTEXTS.get(c).getCallHandler().service(req, res);
}
//-----------------------------------------------------------------------------------------------------------------
@@ -62,36 +72,86 @@ public class BodyTest {
public A04 a04(@Body A04 b) {
return b;
}
+
+ public static class A05 {
+ String s;
+
+ public A05(InputStream in) throws Exception {
+ this.s = IOUtils.read(in);
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return s;
+ }
+ }
+
+ @RestMethod(name=PUT, path="/inputStream")
+ public A05 a05(@Body A05 b) throws Exception {
+ return b;
+ }
+
+ public static class A06 {
+ private String s;
+
+ public A06(Reader in) throws Exception {
+ this.s = IOUtils.read(in);
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return s;
+ }
+ }
+
+ @RestMethod(name=PUT, path="/reader")
+ public A06 a06(@Body A06 b) throws Exception {
+ return b;
+ }
}
@Test
public void a01_onParameter_string() throws Exception {
MockServletRequest req = MockServletRequest.create("PUT",
"/string").body("'foo'");
MockServletResponse res = MockServletResponse.create();
- call(new A(), req, res);
+ call(A.class, req, res);
assertEquals("'foo'", res.getBodyAsString());
}
@Test
public void a02_onParameter_integer() throws Exception {
MockServletRequest req = MockServletRequest.create("PUT",
"/integer").body("123");
MockServletResponse res = MockServletResponse.create();
- call(new A(), req, res);
+ call(A.class, req, res);
assertEquals("123", res.getBodyAsString());
}
@Test
public void a03_onParameter_boolean() throws Exception {
MockServletRequest req = MockServletRequest.create("PUT",
"/boolean").body("true");
MockServletResponse res = MockServletResponse.create();
- call(new A(), req, res);
+ call(A.class, req, res);
assertEquals("true", res.getBodyAsString());
}
@Test
public void a04_onParameter_bean() throws Exception {
MockServletRequest req = MockServletRequest.create("PUT",
"/bean").body("{f1:'a'}");
MockServletResponse res = MockServletResponse.create();
- call(new A(), req, res);
+ call(A.class, req, res);
assertEquals("{f1:'a'}", res.getBodyAsString());
}
+ @Test
+ public void a05_onParameter_inputStream() throws Exception {
+ MockServletRequest req = MockServletRequest.create("PUT",
"/inputStream").body("a");
+ MockServletResponse res = MockServletResponse.create();
+ call(A.class, req, res);
+ assertEquals("'a'", res.getBodyAsString());
+ }
+ @Test
+ public void a06_onParameter_reader() throws Exception {
+ MockServletRequest req = MockServletRequest.create("PUT",
"/reader").body("a");
+ MockServletResponse res = MockServletResponse.create();
+ call(A.class, req, res);
+ assertEquals("'a'", res.getBodyAsString());
+ }
//-----------------------------------------------------------------------------------------------------------------
// @Body on POJO
@@ -128,20 +188,87 @@ public class BodyTest {
public B02 b02(B02 b) {
return b;
}
+
+ @Body
+ public static class B03 extends LinkedList<B02> {}
+
+ @RestMethod(name=PUT, path="/beanList")
+ public B03 b03(B03 b) {
+ return b;
+ }
+
+ @Body
+ public static class B04 {
+ String s;
+
+ public B04(InputStream in) throws Exception {
+ this.s = IOUtils.read(in);
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return s;
+ }
+ }
+
+ @RestMethod(name=PUT, path="/inputStream")
+ public B04 b04(B04 b) throws Exception {
+ return b;
+ }
+
+ @Body
+ public static class B05 {
+ private String s;
+
+ public B05(Reader in) throws Exception {
+ this.s = IOUtils.read(in);
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return s;
+ }
+ }
+
+ @RestMethod(name=PUT, path="/reader")
+ public B05 b05(B05 b) throws Exception {
+ return b;
+ }
}
@Test
- public void a01_onPojo_string() throws Exception {
- MockServletRequest req = MockServletRequest.create("PUT",
"/string").body("'foo'");
+ public void b01_onPojo_string() throws Exception {
+ MockServletRequest req = MockServletRequest.create(PUT,
"/string").body("'foo'");
MockServletResponse res = MockServletResponse.create();
- call(new B(), req, res);
+ call(B.class, req, res);
assertEquals("'foo'", res.getBodyAsString());
}
@Test
- public void a04_onPojo_bean() throws Exception {
- MockServletRequest req = MockServletRequest.create("PUT",
"/bean").body("{f1:'a'}");
+ public void b02_onPojo_bean() throws Exception {
+ MockServletRequest req = MockServletRequest.create(PUT,
"/bean").body("{f1:'a'}");
MockServletResponse res = MockServletResponse.create();
- call(new B(), req, res);
+ call(B.class, req, res);
assertEquals("{f1:'a'}", res.getBodyAsString());
}
+ @Test
+ public void b03_onPojo_beanList() throws Exception {
+ MockServletRequest req = MockServletRequest.create(PUT,
"/beanList").body("[{f1:'a'}]");
+ MockServletResponse res = MockServletResponse.create();
+ call(B.class, req, res);
+ assertEquals("[{f1:'a'}]", res.getBodyAsString());
+ }
+ @Test
+ public void b04_onPojo_inputStream() throws Exception {
+ MockServletRequest req = MockServletRequest.create(PUT,
"/inputStream").body("a");
+ MockServletResponse res = MockServletResponse.create();
+ call(B.class, req, res);
+ assertEquals("'a'", res.getBodyAsString());
+ }
+ @Test
+ public void b05_onPojo_reader() throws Exception {
+ MockServletRequest req = MockServletRequest.create(PUT,
"/reader").body("a");
+ MockServletResponse res = MockServletResponse.create();
+ call(B.class, req, res);
+ assertEquals("'a'", res.getBodyAsString());
+ }
}
--
To stop receiving notification emails like this one, please contact
[email protected].