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 602d6f2 RestRequest API cleanup.
602d6f2 is described below
commit 602d6f2a39700e1e7c70b577871358da0af91353
Author: JamesBognar <[email protected]>
AuthorDate: Sun Nov 7 11:53:11 2021 -0500
RestRequest API cleanup.
---
.../src/main/java/org/apache/juneau/ClassMeta.java | 41 +-
.../java/org/apache/juneau/http/HttpParts.java | 101 ++++
.../java/org/apache/juneau/http/header/Accept.java | 3 +-
.../org/apache/juneau/http/header/ContentType.java | 3 +-
.../java/org/apache/juneau/rest/RequestBody.java | 8 +-
.../org/apache/juneau/rest/RequestFormParam.java | 25 -
.../org/apache/juneau/rest/RequestFormParams.java | 23 +-
.../java/org/apache/juneau/rest/RequestHeader.java | 27 -
.../org/apache/juneau/rest/RequestHeaders.java | 21 +
.../org/apache/juneau/rest/RequestHttpPart.java | 36 ++
.../org/apache/juneau/rest/RequestPathParam.java | 26 -
.../org/apache/juneau/rest/RequestPathParams.java | 21 +
.../org/apache/juneau/rest/RequestQueryParam.java | 26 -
.../org/apache/juneau/rest/RequestQueryParams.java | 21 +
.../java/org/apache/juneau/rest/RestRequest.java | 560 ++++-----------------
.../annotation/Rest_AllowedHeaderParams_Test.java | 4 +-
16 files changed, 358 insertions(+), 588 deletions(-)
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 1199bad..a760fdc 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
@@ -29,6 +29,7 @@ import java.util.*;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
+import java.util.function.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
@@ -113,6 +114,9 @@ public final class ClassMeta<T> implements Type {
private final Map<Class<?>,Mutater<?,T>> fromMutaters = new
ConcurrentHashMap<>();
private final Map<Class<?>,Mutater<T,?>> toMutaters = new
ConcurrentHashMap<>();
private final Mutater<String,T> stringMutater;
+ private final Map<Class<?>,List<?>> annotationListMap = new
ConcurrentHashMap<>();
+ private final Map<Class<?>,Optional<?>> annotationLastMap = new
ConcurrentHashMap<>();
+ private final Map<String,Optional<?>> properties = new
ConcurrentHashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock(false);
private final Lock rLock = lock.readLock(), wLock = lock.writeLock();
@@ -2076,8 +2080,16 @@ public final class ClassMeta<T> implements Type {
* @param a The annotation to retrieve.
* @return The specified annotation, or <jk>null</jk> if the class does
not have the specified annotation.
*/
+ @SuppressWarnings("unchecked")
public <A extends Annotation> A getLastAnnotation(Class<A> a) {
- return info.getLastAnnotation(a, beanContext == null ?
BeanContext.DEFAULT : beanContext);
+ Optional<A> o = (Optional<A>)annotationLastMap.get(a);
+ if (o == null) {
+ if (beanContext == null)
+ return info.getLastAnnotation(a,
BeanContext.DEFAULT);
+ o = Optional.ofNullable(info.getLastAnnotation(a,
beanContext));
+ annotationLastMap.put(a, o);
+ }
+ return o.orElse(null);
}
/**
@@ -2088,8 +2100,33 @@ public final class ClassMeta<T> implements Type {
* @return
* A list of all matching annotations found or an empty list if
none found.
*/
+ @SuppressWarnings("unchecked")
public <A extends Annotation> List<A> getAnnotations(Class<A> a) {
- return info.getAnnotations(a, beanContext == null ?
BeanContext.DEFAULT : beanContext);
+ List<A> l = (List<A>)annotationListMap.get(a);
+ if (l == null) {
+ if (beanContext == null)
+ return info.getAnnotations(a,
BeanContext.DEFAULT);
+ l = Collections.unmodifiableList(info.getAnnotations(a,
beanContext));
+ annotationListMap.put(a, l);
+ }
+ return l;
+ }
+
+ /**
+ * Returns a calculated property on this context.
+ *
+ * @param name The name of the property.
+ * @param function The function used to create this property.
+ * @return The property value. Never <jk>null</jk>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T2> Optional<T2> getProperty(String name,
Function<ClassMeta<?>,T2> function) {
+ Optional<T2> t = (Optional<T2>) properties.get(name);
+ if (t == null) {
+ t = Optional.ofNullable(function.apply(this));
+ properties.put(name, t);
+ }
+ return t;
}
@Override /* Object */
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
index 95238f0..5e1e261 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
@@ -20,8 +20,10 @@ import java.util.*;
import java.util.function.*;
import org.apache.http.*;
+import org.apache.juneau.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.http.part.*;
+import org.apache.juneau.httppart.*;
import org.apache.juneau.reflect.*;
/**
@@ -411,6 +413,105 @@ public class HttpParts {
// Utility methods
//-----------------------------------------------------------------------------------------------------------------
+ private static final Function<ClassMeta<?>,String> HEADER_NAME_FUNCTION
= x -> {
+ for (org.apache.juneau.http.annotation.Header a :
x.getAnnotations(org.apache.juneau.http.annotation.Header.class)) {
+ if (! a.value().isEmpty())
+ return a.value();
+ if (! a.n().isEmpty())
+ return a.n();
+ if (! a.name().isEmpty())
+ return a.name();
+ }
+ return null;
+ };
+
+ private static final Function<ClassMeta<?>,String> QUERY_NAME_FUNCTION
= x -> {
+ for (org.apache.juneau.http.annotation.Query a :
x.getAnnotations(org.apache.juneau.http.annotation.Query.class)) {
+ if (! a.value().isEmpty())
+ return a.value();
+ if (! a.n().isEmpty())
+ return a.n();
+ if (! a.name().isEmpty())
+ return a.name();
+ }
+ return null;
+ };
+
+ private static final Function<ClassMeta<?>,String>
FORMDATA_NAME_FUNCTION = x -> {
+ for (org.apache.juneau.http.annotation.FormData a :
x.getAnnotations(org.apache.juneau.http.annotation.FormData.class)) {
+ if (! a.value().isEmpty())
+ return a.value();
+ if (! a.n().isEmpty())
+ return a.n();
+ if (! a.name().isEmpty())
+ return a.name();
+ }
+ return null;
+ };
+
+ private static final Function<ClassMeta<?>,String> PATH_NAME_FUNCTION =
x -> {
+ for (org.apache.juneau.http.annotation.Path a :
x.getAnnotations(org.apache.juneau.http.annotation.Path.class)) {
+ if (! a.value().isEmpty())
+ return a.value();
+ if (! a.n().isEmpty())
+ return a.n();
+ if (! a.name().isEmpty())
+ return a.name();
+ }
+ return null;
+ };
+
+ private static final Function<ClassMeta<?>,ConstructorInfo>
CONSTRUCTOR_FUNCTION = x -> {
+ ClassInfo ci = x.getInfo();
+ ConstructorInfo cc = ci.getConstructor(Visibility.PUBLIC,
String.class);
+ if (cc == null)
+ cc = ci.getConstructor(Visibility.PUBLIC, String.class,
String.class);
+ return cc;
+ };
+
+ /**
+ * Returns the name of the specified part type.
+ *
+ * <p>
+ * Gets the name from one of the following annotations:
+ * <ul class='javatreec'>
+ * <li class='ja'>{@link org.apache.juneau.http.annotation.Header}
+ * <li class='ja'>{@link org.apache.juneau.http.annotation.Query}
+ * <li class='ja'>{@link
org.apache.juneau.http.annotation.FormData}
+ * <li class='ja'>{@link org.apache.juneau.http.annotation.Path}
+ * </ul>
+ *
+ * @param partType The part type.
+ * @param type The type to check.
+ * @return The part name. Never <jk>null</jk>.
+ */
+ public static Optional<String> getName(HttpPartType partType,
ClassMeta<?> type) {
+ switch(partType) {
+ case FORMDATA: return
type.getProperty("HttpPartName.FormData", FORMDATA_NAME_FUNCTION);
+ case HEADER: return
type.getProperty("HttpPartName.Header", HEADER_NAME_FUNCTION);
+ case PATH: return type.getProperty("HttpPartName.Path",
PATH_NAME_FUNCTION);
+ case QUERY: return
type.getProperty("HttpPartName.Query", QUERY_NAME_FUNCTION);
+ default: return Optional.empty();
+ }
+ }
+
+ /**
+ * Returns the constructor for the specified type.
+ *
+ * <p>
+ * Looks for one of the following constructors:
+ * <ul class='javatree'>
+ * <li class='jm><c><jk>public</jv> T(String <jv>value</jv>);</c>
+ * <li class='jm><c><jk>public</jv> T(String <jv>name</jv>, String
<jv>value</jv>);</c>
+ * </ul>
+ *
+ * @param type The header type to find the constructor on.
+ * @return The constructor. Never <jk>null</jk>.
+ */
+ public static Optional<ConstructorInfo> getConstructor(ClassMeta<?>
type) {
+ return type.getProperty("HttpPart.Constructor",
CONSTRUCTOR_FUNCTION);
+ }
+
/**
* Utility method for converting an arbitrary object to a {@link
NameValuePair}.
*
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
index 7dee5b2..1e958bf 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
@@ -173,7 +173,8 @@ public class Accept extends BasicMediaRangeArrayHeader {
TEXT_HTML = of("text/html"),
TEXT_PLAIN = of("text/plain"),
TEXT_XML = of("text/xml"),
- WILDCARD = of("*/*");
+ WILDCARD = of("*/*"),
+ NULL = new Accept((String)null);
/**
* Static creator.
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
index c02b819..0fa704d 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
@@ -82,7 +82,8 @@ public class ContentType extends BasicMediaTypeHeader {
TEXT_OPENAPI = of("text/openapi"),
TEXT_PLAIN = of("text/plain"),
TEXT_XML = of("text/xml"),
- WILDCARD = of("*/*");
+ WILDCARD = of("*/*"),
+ NULL = new ContentType((String)null);
/**
* Static creator.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index 434c5d8..a9dffd2 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -363,10 +363,10 @@ public class RequestBody {
private MediaType getMediaType() {
if (mediaType != null)
return mediaType;
- ContentType ct = req.getContentType();
+ Optional<ContentType> ct = req.getHeader(ContentType.class);
if (!ct.isPresent() && body != null)
return MediaType.UON;
- return ct.isNotEmpty() ? ct.asMediaType().orElse(null) : null;
+ return ct.isPresent() ? ct.get().asMediaType().orElse(null) :
null;
}
/**
@@ -476,10 +476,10 @@ public class RequestBody {
if ((isEmpty(mt) || mt.toString().startsWith("text/plain")) &&
cm.hasStringMutater())
return cm.getStringMutater().mutate(asString());
- ContentType ct = req.getContentType();
+ Optional<ContentType> ct = req.getHeader(ContentType.class);
throw new UnsupportedMediaType(
"Unsupported media-type in request header
''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
- ct.isPresent() ? ct.asMediaType().orElse(null) :
"not-specified", json(req.getOpContext().getParsers().getSupportedMediaTypes())
+ ct.isPresent() ? ct.get().asMediaType().orElse(null) :
"not-specified", json(req.getOpContext().getParsers().getSupportedMediaTypes())
);
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
index a40f52d..2a0cbf4 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParam.java
@@ -13,7 +13,6 @@
package org.apache.juneau.rest;
import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ThrowableUtils.*;
import java.io.*;
@@ -21,12 +20,10 @@ import java.time.*;
import java.util.*;
import org.apache.http.*;
-import org.apache.juneau.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
-import org.apache.juneau.reflect.*;
/**
* Represents a single form-data parameter on an HTTP request.
@@ -121,28 +118,6 @@ public class RequestFormParam extends RequestHttpPart
implements NameValuePair {
}
/**
- * Returns the value of this parameter as a {@link BasicPart}.
- *
- * @param c The subclass of {@link BasicPart} to instantiate.
- * @param <T> The subclass of {@link BasicPart} to instantiate.
- * @return The value of this parameter as a string, never <jk>null</jk>.
- */
- public <T extends BasicPart> T asPart(Class<T> c) {
- try {
- ClassInfo ci = ClassInfo.of(c);
- ConstructorInfo cc =
ci.getConstructor(Visibility.PUBLIC, String.class);
- if (cc != null)
- return cc.invoke(orElse(null));
- cc = ci.getConstructor(Visibility.PUBLIC, String.class,
String.class);
- if (cc != null)
- return cc.invoke(getName(), orElse(null));
- } catch (Exception e) {
- throw runtimeException(e);
- }
- throw runtimeException("Could not determine a method to
construct type {0}", className(c));
- }
-
- /**
* Returns the value of this parameter as a {@link BasicCsvArrayPart}.
*
* @return The value of this parameter as a {@link BasicCsvArrayPart},
never <jk>null</jk>.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
index 5b01ffc..e44c5c8 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestFormParams.java
@@ -14,7 +14,10 @@ package org.apache.juneau.rest;
import static java.util.Collections.*;
import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
import java.time.*;
import java.util.*;
@@ -22,7 +25,10 @@ import java.util.*;
import javax.servlet.http.*;
import org.apache.http.*;
+import org.apache.juneau.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.header.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.rest.util.*;
@@ -51,7 +57,7 @@ public class RequestFormParams {
Collection<Part> c = null;
RequestBody body = req.getBody();
- if (body.isLoaded() || !
req.getContentType().equalsIgnoreCase("multipart/form-data"))
+ if (body.isLoaded() || !
req.getHeader(ContentType.class).orElse(ContentType.NULL).equalsIgnoreCase("multipart/form-data"))
m = RestUtils.parseQuery(body.getReader());
else {
c = req.getHttpServletRequest().getParts();
@@ -399,6 +405,21 @@ public class RequestFormParams {
}
/**
+ * Returns the form data parameter as the specified bean type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.FormData} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The bean, never <jk>null</jk>.
+ */
+ public <T> Optional<T> get(Class<T> type) {
+ ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+ String name = HttpParts.getName(FORMDATA,
cm).orElseThrow(()->runtimeException("@FormData(name) not found on class {0}",
className(type)));
+ return get(name).asPart(type);
+ }
+ /**
* Returns the last parameter with the specified name as a string.
*
* @param name The parameter name.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
index 59f106d..56f1f20 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeader.java
@@ -13,18 +13,13 @@
package org.apache.juneau.rest;
import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
-
import java.time.*;
import java.util.*;
import org.apache.http.*;
-import org.apache.juneau.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.http.response.BasicHttpException;
import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
import org.apache.juneau.rest.assertions.*;
/**
@@ -100,28 +95,6 @@ public class RequestHeader extends RequestHttpPart
implements Header {
}
/**
- * Returns the value of this header as a {@link BasicHeader}.
- *
- * @param c The subclass of {@link BasicHeader} to instantiate.
- * @param <T> The subclass of {@link BasicHeader} to instantiate.
- * @return The value of this header as a string, never <jk>null</jk>.
- */
- public <T extends BasicHeader> T asHeader(Class<T> c) {
- try {
- ClassInfo ci = ClassInfo.of(c);
- ConstructorInfo cc =
ci.getConstructor(Visibility.PUBLIC, String.class);
- if (cc != null)
- return cc.invoke(orElse(null));
- cc = ci.getConstructor(Visibility.PUBLIC, String.class,
String.class);
- if (cc != null)
- return cc.invoke(getName(), orElse(null));
- } catch (Exception e) {
- throw runtimeException(e);
- }
- throw runtimeException("Could not determine a method to
construct type {0}", className(c));
- }
-
- /**
* Returns the value of this header as a {@link BasicCsvArrayHeader}.
*
* @return The value of this header as a {@link BasicCsvArrayHeader},
never <jk>null</jk>.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
index 36e7a46..6683106 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHeaders.java
@@ -12,10 +12,13 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
import static java.util.Collections.*;
import static java.util.stream.Collectors.*;
import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
import java.time.*;
import java.util.*;
@@ -25,7 +28,9 @@ import org.apache.http.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.svl.*;
+import org.apache.juneau.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
/**
* Represents the headers in an HTTP request.
@@ -398,6 +403,22 @@ public class RequestHeaders {
}
/**
+ * Returns the header as the specified bean type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Header} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The bean, never <jk>null</jk>.
+ */
+ public <T> Optional<T> get(Class<T> type) {
+ ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+ String name = HttpParts.getName(HEADER,
cm).orElseThrow(()->runtimeException("@Header(name) not found on class {0}",
className(type)));
+ return get(name).asPart(type);
+ }
+
+ /**
* Returns the last header with the specified name as a string.
*
* @param name The header name.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
index 7fd1abd..0d471ff 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestHttpPart.java
@@ -13,16 +13,21 @@
package org.apache.juneau.rest;
import static org.apache.juneau.httppart.HttpPartType.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
+
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.*;
import org.apache.juneau.*;
+import org.apache.juneau.http.*;
import org.apache.juneau.http.response.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.ParseException;
+import org.apache.juneau.reflect.*;
/**
* Represents a single HTTP part on an HTTP request.
@@ -129,6 +134,28 @@ public abstract class RequestHttpPart {
}
/**
+ * Returns the value of this part as the specified type.
+ *
+ * <p>
+ * Looks for one of the following constructors:
+ * <ul class='javatree'>
+ * <li class='jm><c><jk>public</jv> T(String <jv>value</jv>);</c>
+ * <li class='jm><c><jk>public</jv> T(String <jv>name</jv>, String
<jv>value</jv>);</c>
+ * </ul>
+ *
+ * @param c The part type.
+ * @return The value of this part as the specified type, never
<jk>null</jk>.
+ */
+ public <T> Optional<T> asPart(Class<T> c) {
+ if (! isPresent())
+ return Optional.empty();
+ ConstructorInfo cc =
HttpParts.getConstructor(getRequest().getBeanSession().getClassMeta(c)).orElseThrow(()->runtimeException("Could
not determine a method to construct type {0}", className(c)));
+ if (cc.getParamCount() == 1)
+ return Optional.of(cc.invoke(get()));
+ return Optional.of(cc.invoke(getName(), get()));
+ }
+
+ /**
* Returns the value of this part as a string.
*
* @return The value of this part as a string, or {@link
Optional#empty()} if the part was not present.
@@ -249,6 +276,15 @@ public abstract class RequestHttpPart {
}
/**
+ * Returns the request that created this part.
+ *
+ * @return The request that created this part.
+ */
+ protected RestRequest getRequest() {
+ return request;
+ }
+
+ /**
* Gets the name of this part.
*
* @return The name of this part, never <jk>null</jk>.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
index 89a9115..a192709 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParam.java
@@ -13,18 +13,14 @@
package org.apache.juneau.rest;
import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
import java.time.*;
import java.util.*;
import org.apache.http.*;
-import org.apache.juneau.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
/**
* Represents a single path parameter on an HTTP request.
@@ -100,28 +96,6 @@ public class RequestPathParam extends RequestHttpPart
implements NameValuePair {
}
/**
- * Returns the value of this parameter as a {@link BasicPart}.
- *
- * @param c The subclass of {@link BasicPart} to instantiate.
- * @param <T> The subclass of {@link BasicPart} to instantiate.
- * @return The value of this parameter as a string, never <jk>null</jk>.
- */
- public <T extends BasicPart> T asPart(Class<T> c) {
- try {
- ClassInfo ci = ClassInfo.of(c);
- ConstructorInfo cc =
ci.getConstructor(Visibility.PUBLIC, String.class);
- if (cc != null)
- return cc.invoke(orElse(null));
- cc = ci.getConstructor(Visibility.PUBLIC, String.class,
String.class);
- if (cc != null)
- return cc.invoke(getName(), orElse(null));
- } catch (Exception e) {
- throw runtimeException(e);
- }
- throw runtimeException("Could not determine a method to
construct type {0}", className(c));
- }
-
- /**
* Returns the value of this parameter as a {@link BasicCsvArrayPart}.
*
* @return The value of this parameter as a {@link BasicCsvArrayPart},
never <jk>null</jk>.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
index efdb6ac..6acc5de 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestPathParams.java
@@ -12,9 +12,12 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
import static java.util.Collections.*;
import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
import java.time.*;
import java.util.*;
@@ -24,7 +27,9 @@ import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.rest.util.*;
import org.apache.juneau.svl.*;
+import org.apache.juneau.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
/**
* Represents the path parameters in an HTTP request.
@@ -355,6 +360,22 @@ public class RequestPathParams {
}
/**
+ * Returns the path parameter as the specified bean type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Path} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The bean, never <jk>null</jk>.
+ */
+ public <T> Optional<T> get(Class<T> type) {
+ ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+ String name = HttpParts.getName(PATH,
cm).orElseThrow(()->runtimeException("@Path(name) not found on class {0}",
className(type)));
+ return get(name).asPart(type);
+ }
+
+ /**
* Returns the last parameter with the specified name as a string.
*
* @param name The parameter name.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
index 2d5c90b..a6017fb 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParam.java
@@ -13,18 +13,14 @@
package org.apache.juneau.rest;
import static org.apache.juneau.httppart.HttpPartType.*;
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
import java.time.*;
import java.util.*;
import org.apache.http.*;
-import org.apache.juneau.*;
import org.apache.juneau.assertions.*;
import org.apache.juneau.http.part.*;
import org.apache.juneau.httppart.*;
-import org.apache.juneau.reflect.*;
/**
* Represents a single query parameter on an HTTP request.
@@ -100,28 +96,6 @@ public class RequestQueryParam extends RequestHttpPart
implements NameValuePair
}
/**
- * Returns the value of this parameter as a {@link BasicPart}.
- *
- * @param c The subclass of {@link BasicPart} to instantiate.
- * @param <T> The subclass of {@link BasicPart} to instantiate.
- * @return The value of this parameter as a string, never <jk>null</jk>.
- */
- public <T extends BasicPart> T asPart(Class<T> c) {
- try {
- ClassInfo ci = ClassInfo.of(c);
- ConstructorInfo cc =
ci.getConstructor(Visibility.PUBLIC, String.class);
- if (cc != null)
- return cc.invoke(orElse(null));
- cc = ci.getConstructor(Visibility.PUBLIC, String.class,
String.class);
- if (cc != null)
- return cc.invoke(getName(), orElse(null));
- } catch (Exception e) {
- throw runtimeException(e);
- }
- throw runtimeException("Could not determine a method to
construct type {0}", className(c));
- }
-
- /**
* Returns the value of this parameter as a {@link BasicCsvArrayPart}.
*
* @return The value of this parameter as a {@link BasicCsvArrayPart},
never <jk>null</jk>.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
index f0f341c..61e09f5 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestQueryParams.java
@@ -12,9 +12,12 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ThrowableUtils.*;
import static java.util.Collections.*;
import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.httppart.HttpPartType.*;
import java.time.*;
import java.util.*;
@@ -24,7 +27,9 @@ import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.svl.*;
import org.apache.juneau.utils.*;
+import org.apache.juneau.*;
import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
/**
* Represents the query parameters in an HTTP request.
@@ -365,6 +370,22 @@ public class RequestQueryParams {
}
/**
+ * Returns the query parameter as the specified bean type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Query} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The bean, never <jk>null</jk>.
+ */
+ public <T> Optional<T> get(Class<T> type) {
+ ClassMeta<T> cm = req.getBeanSession().getClassMeta(type);
+ String name = HttpParts.getName(QUERY,
cm).orElseThrow(()->runtimeException("@Query(name) not found on class {0}",
className(type)));
+ return get(name).asPart(type);
+ }
+
+ /**
* Returns the last parameter with the specified name as a string.
*
* @param name The parameter name.
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 8200b75..ef6c074 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -466,418 +466,58 @@ public final class RestRequest {
//-----------------------------------------------------------------------------------------------------------------
/**
- * Returns the <c>Accept</c> header on the request.
+ * Returns the request header of the specified type.
*
* <p>
- * Content-Types that are acceptable for the response.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Accept: text/plain
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Accept getAccept() {
- return headers.get("Accept").asHeader(Accept.class);
- }
-
- /**
- * Returns the <c>Accept-Charset</c> header on the request.
- *
- * <p>
- * Character sets that are acceptable.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Accept-Charset: utf-8
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public AcceptCharset getAcceptCharset() {
- return
headers.get("Accept-Charset").asHeader(AcceptCharset.class);
- }
-
- /**
- * Returns the <c>Accept-Encoding</c> header on the request.
- *
- * <p>
- * List of acceptable encodings.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Accept-Encoding: gzip, deflate
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public AcceptEncoding getAcceptEncoding() {
- return
headers.get("Accept-Encoding").asHeader(AcceptEncoding.class);
- }
-
- /**
- * Returns the <c>Accept-Language</c> header on the request.
- *
- * <p>
- * List of acceptable human languages for response.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Accept-Language: en-US
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public AcceptLanguage getAcceptLanguage() {
- return
headers.get("Accept-Language").asHeader(AcceptLanguage.class);
- }
-
- /**
- * Returns the <c>Authorization</c> header on the request.
- *
- * <p>
- * Authentication credentials for HTTP authentication.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Authorization getAuthorization() {
- return
headers.get("Authorization").asHeader(Authorization.class);
- }
-
- /**
- * Returns the <c>Cache-Control</c> header on the request.
- *
- * <p>
- * Used to specify directives that must be obeyed by all caching
mechanisms along the request-response chain.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Cache-Control: no-cache
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public CacheControl getCacheControl() {
- return
headers.get("Cache-Control").asHeader(CacheControl.class);
- }
-
- /**
- * Returns the <c>Connection</c> header on the request.
- *
- * <p>
- * Control options for the current connection and list of hop-by-hop
request fields.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Connection: keep-alive
- * Connection: Upgrade
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Connection getConnection() {
- return headers.get("Connection").asHeader(Connection.class);
- }
-
- /**
- * Returns the <c>Content-Length</c> header on the request.
- *
- * <p>
- * The length of the request body in octets (8-bit bytes).
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Content-Length: 348
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public ContentLength getContentLength() {
- return
headers.get("Content-Length").asHeader(ContentLength.class);
- }
-
- /**
- * Returns the <c>Content-Type</c> header on the request.
- *
- * <p>
- * The MIME type of the body of the request (used with POST and PUT
requests).
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Content-Type: application/x-www-form-urlencoded
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public ContentType getContentType() {
- return headers.get("Content-Type").asHeader(ContentType.class);
- }
-
- /**
- * Returns the <c>Date</c> header on the request.
- *
- * <p>
- * The date and time that the message was originated (in "HTTP-date"
format as defined by RFC 7231 Date/Time Formats).
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Date: Tue, 15 Nov 1994 08:12:31 GMT
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Date getDate() {
- return headers.get("Date").asHeader(Date.class);
- }
-
- /**
- * Returns the <c>Expect</c> header on the request.
- *
- * <p>
- * Indicates that particular server behaviors are required by the
client.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Expect: 100-continue
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Expect getExpect() {
- return headers.get("Expect").asHeader(Expect.class);
- }
-
- /**
- * Returns the <c>From</c> header on the request.
- *
- * <p>
- * The email address of the user making the request.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * From: [email protected]
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public From getFrom() {
- return headers.get("From").asHeader(From.class);
- }
-
- /**
- * Returns the <c>Host</c> header on the request.
- *
- * <p>
- * The domain name of the server (for virtual hosting), and the TCP
port number on which the server is listening.
- * The port number may be omitted if the port is the standard port for
the service requested.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Host: en.wikipedia.org:8080
- * Host: en.wikipedia.org
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Host getHost() {
- return headers.get("Host").asHeader(Host.class);
- }
-
- /**
- * Returns the <c>If-Match</c> header on the request.
- *
- * <p>
- * Only perform the action if the client supplied entity matches the
same entity on the server.
- * This is mainly for methods like PUT to only update a resource if it
has not been modified since the user last
- * updated it.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * If-Match: "737060cd8c284d8af7ad3082f209582d"
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public IfMatch getIfMatch() {
- return headers.get("If-Match").asHeader(IfMatch.class);
- }
-
- /**
- * Returns the <c>If-Modified-Since</c> header on the request.
- *
- * <p>
- * Allows a 304 Not Modified to be returned if content is unchanged.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public IfModifiedSince getIfModifiedSince() {
- return
headers.get("If-Modified-Since").asHeader(IfModifiedSince.class);
- }
-
- /**
- * Returns the <c>If-None-Match</c> header on the request.
- *
- * <p>
- * Allows a 304 Not Modified to be returned if content is unchanged,
see HTTP ETag.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * If-None-Match: "737060cd8c284d8af7ad3082f209582d"
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public IfNoneMatch getIfNoneMatch() {
- return headers.get("If-None-Match").asHeader(IfNoneMatch.class);
- }
-
- /**
- * Returns the <c>If-Range</c> header on the request.
- *
- * <p>
- * If the entity is unchanged, send me the part(s) that I am missing;
otherwise, send me the entire ofNullable(entity.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * If-Range: "737060cd8c284d8af7ad3082f209582d"
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public IfRange getIfRange() {
- return headers.get("If-Range").asHeader(IfRange.class);
- }
-
- /**
- * Returns the <c>If-Unmodified-Since</c> header on the request.
- *
- * <p>
- * Only send the response if the entity has not been modified since a
specific time.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public IfUnmodifiedSince getIfUnmodifiedSince() {
- return
headers.get("If-Unmodified-Since").asHeader(IfUnmodifiedSince.class);
- }
-
- /**
- * Returns the <c>Max-Forwards</c> header on the request.
- *
- * <p>
- * Limit the number of times the message can be forwarded through
proxies or gateways.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Max-Forwards: 10
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public MaxForwards getMaxForwards() {
- return headers.get("Max-Forwards").asHeader(MaxForwards.class);
- }
-
- /**
- * Returns the <c>Pragma</c> header on the request.
- *
- * <p>
- * Implementation-specific fields that may have various effects
anywhere along the request-response chain.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Pragma: no-cache
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Pragma getPragma() {
- return headers.get("Pragma").asHeader(Pragma.class);
- }
-
- /**
- * Returns the <c>Proxy-Authorization</c> header on the request.
- *
- * <p>
- * Authorization credentials for connecting to a proxy.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public ProxyAuthorization getProxyAuthorization() {
- return
headers.get("Proxy-Authorization").asHeader(ProxyAuthorization.class);
- }
-
- /**
- * Returns the <c>Range</c> header on the request.
- *
- * <p>
- * Request only part of an entity. Bytes are numbered from 0.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Range: bytes=500-999
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Range getRange() {
- return headers.get("Range").asHeader(Range.class);
- }
-
- /**
- * Returns the <c>Referer</c> header on the request.
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Header} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
*
* <p>
- * This is the address of the previous web page from which a link to
the currently requested page was followed.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Referer: http://en.wikipedia.org/wiki/Main_Page
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Referer getReferer() {
- return headers.get("Referer").asHeader(Referer.class);
- }
-
- /**
- * Returns the <c>TE</c> header on the request.
- *
- * <p>
- * The transfer encodings the user agent is willing to accept: the same
values as for the response header field
- * Transfer-Encoding can be used, plus the "trailers" value (related to
the "chunked" transfer method) to notify the
- * server it expects to receive additional fields in the trailer after
the last, zero-sized, chunk.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * TE: trailers, deflate
- * </p>
+ * Typically any of the following:
+ * <ul class='javatreec'>
+ * <li class='jc'>{@link Accept}
+ * <li class='jc'>{@link AcceptCharset}
+ * <li class='jc'>{@link AcceptEncoding}
+ * <li class='jc'>{@link AcceptLanguage}
+ * <li class='jc'>{@link AcceptRanges}
+ * <li class='jc'>{@link Authorization}
+ * <li class='jc'>{@link CacheControl}
+ * <li class='jc'>{@link ClientVersion}
+ * <li class='jc'>{@link Connection}
+ * <li class='jc'>{@link ContentDisposition}
+ * <li class='jc'>{@link ContentEncoding}
+ * <li class='jc'>{@link ContentLength}
+ * <li class='jc'>{@link ContentType}
+ * <li class='jc'>{@link Date}
+ * <li class='jc'>{@link Debug}
+ * <li class='jc'>{@link Expect}
+ * <li class='jc'>{@link Forwarded}
+ * <li class='jc'>{@link From}
+ * <li class='jc'>{@link Host}
+ * <li class='jc'>{@link IfMatch}
+ * <li class='jc'>{@link IfModifiedSince}
+ * <li class='jc'>{@link IfNoneMatch}
+ * <li class='jc'>{@link IfRange}
+ * <li class='jc'>{@link IfUnmodifiedSince}
+ * <li class='jc'>{@link MaxForwards}
+ * <li class='jc'>{@link NoTrace}
+ * <li class='jc'>{@link Origin}
+ * <li class='jc'>{@link Pragma}
+ * <li class='jc'>{@link ProxyAuthorization}
+ * <li class='jc'>{@link Range}
+ * <li class='jc'>{@link Referer}
+ * <li class='jc'>{@link TE}
+ * <li class='jc'>{@link Thrown}
+ * <li class='jc'>{@link Upgrade}
+ * <li class='jc'>{@link UserAgent}
+ * <li class='jc'>{@link Warning}
+ * </ul>
*
+ * @param type The bean type to create.
* @return The parsed header on the request, never <jk>null</jk>.
*/
- public TE getTE() {
- return headers.get("TE").asHeader(TE.class);
+ public <T> Optional<T> getHeader(Class<T> type) {
+ return headers.get(type);
}
/**
@@ -895,74 +535,6 @@ public final class RestRequest {
return empty();
}
- /**
- * Returns the <c>User-Agent</c> header on the request.
- *
- * <p>
- * The user agent string of the user agent.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0)
Gecko/20100101 Firefox/21.0
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public UserAgent getUserAgent() {
- return headers.get("Upgrade").asHeader(UserAgent.class);
- }
-
- /**
- * Returns the <c>Upgrade</c> header on the request.
- *
- * <p>
- * Ask the server to upgrade to another protocol.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Upgrade getUpgrade() {
- return headers.get("Upgrade").asHeader(Upgrade.class);
- }
-
- /**
- * Returns the <c>Via</c> header on the request.
- *
- * <p>
- * Informs the server of proxies through which the request was sent.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Via: 1.0 fred, 1.1 example.com (Apache/1.1)
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Via getVia() {
- return headers.get("Via").asHeader(Via.class);
- }
-
- /**
- * Returns the <c>Warning</c> header on the request.
- *
- * <p>
- * A general warning about possible problems with the entity body.
- *
- * <h5 class='figure'>Example:</h5>
- * <p class='bcode w800'>
- * Warning: 199 Miscellaneous warning
- * </p>
- *
- * @return The parsed header on the request, never <jk>null</jk>.
- */
- public Warning getWarning() {
- return headers.get("Warning").asHeader(Warning.class);
- }
-
//-----------------------------------------------------------------------------------------------------------------
// Attributes
//-----------------------------------------------------------------------------------------------------------------
@@ -1085,6 +657,20 @@ public final class RestRequest {
}
/**
+ * Returns the request query parameter of the specified type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Query} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The parsed query parameter on the request, never
<jk>null</jk>.
+ */
+ public <T> Optional<T> getQueryParam(Class<T> type) {
+ return queryParams.get(type);
+ }
+
+ /**
* Returns <jk>true</jk> if this request contains the specified header.
*
* @param name The header name.
@@ -1166,6 +752,20 @@ public final class RestRequest {
}
/**
+ * Returns the request form-data parameter of the specified type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.FormData} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The parsed form-data parameter on the request, never
<jk>null</jk>.
+ */
+ public <T> Optional<T> getFormParam(Class<T> type) {
+ return getFormParams().get(type);
+ }
+
+ /**
* Returns <jk>true</jk> if this request contains the specified header.
*
* @param name The header name.
@@ -1226,6 +826,20 @@ public final class RestRequest {
}
/**
+ * Returns the request path parameter of the specified type.
+ *
+ * <p>
+ * Type must have a name specified via the {@link
org.apache.juneau.http.annotation.Path} annotation
+ * and a public constructor that takes in either <c>value</c> or
<c>name,value</c> as strings.
+ *
+ * @param type The bean type to create.
+ * @return The parsed form-data parameter on the request, never
<jk>null</jk>.
+ */
+ public <T> Optional<T> getPathParam(Class<T> type) {
+ return pathParams.get(type);
+ }
+
+ /**
* Shortcut for calling <c>getPathParams().getRemainder()</c>.
*
* @return The path remainder value, never <jk>null</jk>.
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
index 39ddba9..d081b8f 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
@@ -30,8 +30,8 @@ public class Rest_AllowedHeaderParams_Test {
public static class A {
@RestOp
public String put(RequestHeaders h) {
- Accept accept = h.get("Accept").asHeader(Accept.class);
- ContentType contentType =
h.get("Content-Type").asHeader(ContentType.class);
+ Accept accept =
h.get("Accept").asPart(Accept.class).orElse(Accept.NULL);
+ ContentType contentType =
h.get("Content-Type").asPart(ContentType.class).orElse(ContentType.NULL);
return "Accept="+(accept.isPresent() ? accept.get() :
null)+",Content-Type=" + (contentType.isPresent() ? contentType.get() : null) +
",Custom=" + h.getString("Custom").orElse(null);
}
}