http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java new file mode 100644 index 0000000..b0617bd --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java @@ -0,0 +1,675 @@ +// *************************************************************************************************************************** +// * 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.rest; + +import java.lang.reflect.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.http.*; +import org.apache.juneau.http.Date; +import org.apache.juneau.internal.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.urlencoding.*; + +/** + * Represents the headers in an HTTP request. + * <p> + * Entries are stored in a case-insensitive map. + */ +public class RequestHeaders extends TreeMap<String,String[]> { + private static final long serialVersionUID = 1L; + + private UrlEncodingParser parser; + private BeanSession beanSession; + private RequestQuery queryParams; + + RequestHeaders() { + super(String.CASE_INSENSITIVE_ORDER); + } + + RequestHeaders setParser(UrlEncodingParser parser) { + this.parser = parser; + return this; + } + + RequestHeaders setBeanSession(BeanSession beanSession) { + this.beanSession = beanSession; + return this; + } + + RequestHeaders setQueryParams(RequestQuery queryParams) { + this.queryParams = queryParams; + return this; + } + + /** + * Adds default entries to these headers. + * <p> + * This includes the default headers defined on the servlet and method levels. + * + * @param defaultEntries The default entries. Can be <jk>null</jk>. + * @return This object (for method chaining). + */ + public RequestHeaders addDefault(Map<String,String> defaultEntries) { + if (defaultEntries != null) { + for (Map.Entry<String,String> e : defaultEntries.entrySet()) { + String key = e.getKey(), value = e.getValue(); + String[] v = get(key); + if (v == null) + put(key, new String[]{value}); + } + } + return this; + } + + /** + * Adds a set of header values to this object. + * + * @param name The header name. + * @param values The header values. + * @return This object (for method chaining). + */ + public RequestHeaders put(String name, Enumeration<String> values) { + // Optimized for enumerations of one entry, the most-common case. + if (values.hasMoreElements()) { + String v = values.nextElement(); + if (! v.isEmpty()) { + String[] s = new String[]{v}; + while (values.hasMoreElements()) + s = ArrayUtils.append(s, values.nextElement()); + put(name, s); + } + } + return this; + } + + /** + * Returns the specified header value, or <jk>null</jk> if the header doesn't exist. + * <p> + * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string. + * <p> + * @param name The header name. + * @return The header value, or <jk>null</jk> if it doesn't exist. + */ + public String getFirst(String name) { + return getFirst(name, null); + } + + /** + * Returns the specified header value, or a default value if the header doesn't exist. + * <p> + * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string. + * + * @param name The HTTP header name. + * @param def The default value to return if the header value isn't found. + * @return The header value, or the default value if the header isn't present. + */ + public String getFirst(String name, String def) { + String[] v = null; + if (queryParams != null) + v = queryParams.get(name); + if (v == null || v.length == 0) + v = get(name); + if (v == null || v.length == 0) + return def; + return v[0]; + } + + /** + * Sets a request header value. + * + * @param name The header name. + * @param value The header value. + */ + public void put(String name, Object value) { + super.put(name, new String[]{StringUtils.toString(value)}); + } + + /** + * Returns the specified header value converted to a POJO. + * <p> + * The type can be any POJO type convertable from a <code>String</code> + * (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>). + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into an integer.</jc> + * <jk>int</jk> myheader = req.getHeader(<js>"My-Header"</js>, <jk>int</jk>.<jk>class</jk>); + * + * <jc>// Parse a UUID.</jc> + * UUID myheader = req.getHeader(<js>"My-Header"</js>, UUID.<jk>class</jk>); + * </p> + * + * @param name The HTTP header name. + * @param type The class type to convert the header value to. + * @param <T> The class type to convert the header value to. + * @return The parameter value converted to the specified class type. + */ + public <T> T get(String name, Class<T> type) { + String h = getFirst(name); + return beanSession.convertToType(h, type); + } + + /** + * Same as {@link #get(String, Class)} but returns a default value if not found. + * + * @param name The HTTP header name. + * @param def The default value if the header was not specified or is <jk>null</jk>. + * @param type The class type to convert the header value to. + * @param <T> The class type to convert the header value to. + * @return The parameter value converted to the specified class type. + */ + public <T> T get(String name, T def, Class<T> type) { + String h = getFirst(name); + if (h == null) + return def; + return beanSession.convertToType(h, type); + } + + /** + * Returns the specified header value converted to a POJO. + * <p> + * The type can be any POJO type convertable from a <code>String</code> + * (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>). + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into a linked-list of strings.</jc> + * List<String> myheader = req.getHeader(<js>"My-Header"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); + * </p> + * + * @param name The HTTP header name. + * @param type The type of object to create. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * @param args The type arguments of the class if it's a collection or map. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * <br>Ignored if the main type is not a map or collection. + * @param <T> The class type to convert the header value to. + * @return The parameter value converted to the specified class type. + * @throws ParseException If the header could not be converted to the specified type. + */ + public <T> T get(String name, Type type, Type...args) throws ParseException { + String h = getFirst(name); + return parser.parsePart(h, type, args); + } + + /** + * Returns the <code>Accept</code> header on the request. + * <p> + * Content-Types that are acceptable for the response. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Accept: text/plain + * </p> + * + * @return The parsed <code>Accept</code> header on the request, or <jk>null</jk> if not found. + * + */ + public Accept getAccept() { + return Accept.forString(getFirst("Accept")); + } + + /** + * Returns the <code>Accept-Charset</code> header on the request. + * <p> + * Character sets that are acceptable. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Accept-Charset: utf-8 + * </p> + * + * @return The parsed <code>Accept-Charset</code> header on the request, or <jk>null</jk> if not found. + */ + public AcceptCharset getAcceptCharset() { + return AcceptCharset.forString(getFirst("Accept-Charset")); + } + + /** + * Returns the <code>Accept-Encoding</code> header on the request. + * <p> + * List of acceptable encodings. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Accept-Encoding: gzip, deflate + * </p> + * + * @return The parsed <code>Accept-Encoding</code> header on the request, or <jk>null</jk> if not found. + */ + public AcceptEncoding getAcceptEncoding() { + return AcceptEncoding.forString(getFirst("Accept-Encoding")); + } + + /** + * Returns the <code>Accept-Language</code> header on the request. + * <p> + * List of acceptable human languages for response. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Accept-Language: en-US + * </p> + * + * @return The parsed <code>Accept-Language</code> header on the request, or <jk>null</jk> if not found. + */ + public AcceptLanguage getAcceptLanguage() { + return AcceptLanguage.forString(getFirst("Accept-Language")); + } + + /** + * Returns the <code>Authorization</code> header on the request. + * <p> + * Authentication credentials for HTTP authentication. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== + * </p> + * + * @return The parsed <code>Authorization</code> header on the request, or <jk>null</jk> if not found. + */ + public Authorization getAuthorization() { + return Authorization.forString(getFirst("Authorization")); + } + + /** + * Returns the <code>Cache-Control</code> header on the request. + * <p> + * Used to specify directives that must be obeyed by all caching mechanisms along the request-response chain. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Cache-Control: no-cache + * </p> + * + * @return The parsed <code>Cache-Control</code> header on the request, or <jk>null</jk> if not found. + */ + public CacheControl getCacheControl() { + return CacheControl.forString(getFirst("Cache-Control")); + } + + /** + * Returns the <code>Connection</code> header on the request. + * <p> + * Control options for the current connection and list of hop-by-hop request fields. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Connection: keep-alive + * Connection: Upgrade + * </p> + * + * @return The parsed <code></code> header on the request, or <jk>null</jk> if not found. + */ + public Connection getConnection() { + return Connection.forString(getFirst("Connection")); + } + + /** + * Returns the <code>Content-Length</code> header on the request. + * <p> + * The length of the request body in octets (8-bit bytes). + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Content-Length: 348 + * </p> + * + * @return The parsed <code>Content-Length</code> header on the request, or <jk>null</jk> if not found. + */ + public ContentLength getContentLength() { + return ContentLength.forString(getFirst("Content-Length")); + } + + /** + * Returns the <code>Content-Type</code> header on the request. + * <p> + * The MIME type of the body of the request (used with POST and PUT requests). + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Content-Type: application/x-www-form-urlencoded + * </p> + * + * @return The parsed <code>Content-Type</code> header on the request, or <jk>null</jk> if not found. + */ + public ContentType getContentType() { + return ContentType.forString(getFirst("Content-Type")); + } + + /** + * Returns the <code>Date</code> 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). + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Date: Tue, 15 Nov 1994 08:12:31 GMT + * </p> + * + * @return The parsed <code>Date</code> header on the request, or <jk>null</jk> if not found. + */ + public Date getDate() { + return Date.forString(getFirst("Date")); + } + + /** + * Returns the <code>Expect</code> header on the request. + * <p> + * Indicates that particular server behaviors are required by the client. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Expect: 100-continue + * </p> + * + * @return The parsed <code>Expect</code> header on the request, or <jk>null</jk> if not found. + */ + public Expect getExpect() { + return Expect.forString(getFirst("Expect")); + } + + /** + * Returns the <code>From</code> header on the request. + * <p> + * The email address of the user making the request. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * From: [email protected] + * </p> + * + * @return The parsed <code>From</code> header on the request, or <jk>null</jk> if not found. + */ + public From getFrom() { + return From.forString(getFirst("From")); + } + + /** + * Returns the <code>Host</code> 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. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Host: en.wikipedia.org:8080 + * Host: en.wikipedia.org + * </p> + * + * @return The parsed <code>Host</code> header on the request, or <jk>null</jk> if not found. + */ + public Host getHost() { + return Host.forString(getFirst("Host")); + } + + /** + * Returns the <code>If-Match</code> 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. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * If-Match: "737060cd8c284d8af7ad3082f209582d" + * </p> + * + * @return The parsed <code>If-Match</code> header on the request, or <jk>null</jk> if not found. + */ + public IfMatch getIfMatch() { + return IfMatch.forString(getFirst("If-Match")); + } + + /** + * Returns the <code>If-Modified-Since</code> header on the request. + * <p> + * Allows a 304 Not Modified to be returned if content is unchanged. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT + * </p> + * + * @return The parsed <code>If-Modified-Since</code> header on the request, or <jk>null</jk> if not found. + */ + public IfModifiedSince getIfModifiedSince() { + return IfModifiedSince.forString(getFirst("If-Modified-Since")); + } + + /** + * Returns the <code>If-None-Match</code> header on the request. + * <p> + * Allows a 304 Not Modified to be returned if content is unchanged, see HTTP ETag. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * If-None-Match: "737060cd8c284d8af7ad3082f209582d" + * </p> + * + * @return The parsed <code>If-None-Match</code> header on the request, or <jk>null</jk> if not found. + */ + public IfNoneMatch getIfNoneMatch() { + return IfNoneMatch.forString(getFirst("If-None-Match")); + } + + /** + * Returns the <code>If-Range</code> header on the request. + * <p> + * If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * If-Range: "737060cd8c284d8af7ad3082f209582d" + * </p> + * + * @return The parsed <code>If-Range</code> header on the request, or <jk>null</jk> if not found. + */ + public IfRange getIfRange() { + return IfRange.forString(getFirst("If-Range")); + } + + /** + * Returns the <code>If-Unmodified-Since</code> header on the request. + * <p> + * Only send the response if the entity has not been modified since a specific time. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT + * </p> + * + * @return The parsed <code>If-Unmodified-Since</code> header on the request, or <jk>null</jk> if not found. + */ + public IfUnmodifiedSince getIfUnmodifiedSince() { + return IfUnmodifiedSince.forString(getFirst("If-Unmodified-Since")); + } + + /** + * Returns the <code>Max-Forwards</code> header on the request. + * <p> + * Limit the number of times the message can be forwarded through proxies or gateways. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Max-Forwards: 10 + * </p> + * + * @return The parsed <code>Max-Forwards</code> header on the request, or <jk>null</jk> if not found. + */ + public MaxForwards getMaxForwards() { + return MaxForwards.forString(getFirst("Max-Forwards")); + } + + /** + * Returns the <code>Pragma</code> header on the request. + * <p> + * Implementation-specific fields that may have various effects anywhere along the request-response chain. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Pragma: no-cache + * </p> + * + * @return The parsed <code>Pragma</code> header on the request, or <jk>null</jk> if not found. + */ + public Pragma getPragma() { + return Pragma.forString(getFirst("Pragma")); + } + + /** + * Returns the <code>Proxy-Authorization</code> header on the request. + * <p> + * Authorization credentials for connecting to a proxy. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== + * </p> + * + * @return The parsed <code>Proxy-Authorization</code> header on the request, or <jk>null</jk> if not found. + */ + public ProxyAuthorization getProxyAuthorization() { + return ProxyAuthorization.forString(getFirst("Proxy-Authorization")); + } + + /** + * Returns the <code>Range</code> header on the request. + * <p> + * Request only part of an entity. Bytes are numbered from 0. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Range: bytes=500-999 + * </p> + * + * @return The parsed <code>Range</code> header on the request, or <jk>null</jk> if not found. + */ + public Range getRange() { + return Range.forString(getFirst("Range")); + } + + /** + * Returns the <code>Referer</code> header on the request. + * <p> + * This is the address of the previous web page from which a link to the currently requested page was followed. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Referer: http://en.wikipedia.org/wiki/Main_Page + * </p> + * + * @return The parsed <code>Referer</code> header on the request, or <jk>null</jk> if not found. + */ + public Referer getReferer() { + return Referer.forString(getFirst("Referer")); + } + + /** + * Returns the <code>TE</code> 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. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * TE: trailers, deflate + * </p> + * + * @return The parsed <code>TE</code> header on the request, or <jk>null</jk> if not found. + */ + public TE getTE() { + return TE.forString(getFirst("TE")); + } + + /** + * Returns the <code>Time-Zone</code> header value on the request if there is one. + * <p> + * Example: <js>"GMT"</js>. + * + * @return The <code>Time-Zone</code> header value on the request, or <jk>null</jk> if not present. + */ + public TimeZone getTimeZone() { + String tz = getFirst("Time-Zone"); + if (tz != null) + return TimeZone.getTimeZone(tz); + return null; + } + + /** + * Returns the <code>User-Agent</code> header on the request. + * <p> + * The user agent string of the user agent. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0 + * </p> + * + * @return The parsed <code>User-Agent</code> header on the request, or <jk>null</jk> if not found. + */ + public UserAgent getUserAgent() { + return UserAgent.forString(getFirst("User-Agent")); + } + + /** + * Returns the <code>Upgrade</code> header on the request. + * <p> + * Ask the server to upgrade to another protocol. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket + * </p> + * + * @return The parsed <code>Upgrade</code> header on the request, or <jk>null</jk> if not found. + */ + public Upgrade getUpgrade() { + return Upgrade.forString(getFirst("Upgrade")); + } + + /** + * Returns the <code>Via</code> header on the request. + * <p> + * Informs the server of proxies through which the request was sent. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Via: 1.0 fred, 1.1 example.com (Apache/1.1) + * </p> + * + * @return The parsed <code>Via</code> header on the request, or <jk>null</jk> if not found. + */ + public Via getVia() { + return Via.forString(getFirst("Via")); + } + + /** + * Returns the <code>Warning</code> header on the request. + * <p> + * A general warning about possible problems with the entity body. + * + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * Warning: 199 Miscellaneous warning + * </p> + * + * @return The parsed <code>Warning</code> header on the request, or <jk>null</jk> if not found. + */ + public Warning getWarning() { + return Warning.forString(getFirst("Warning")); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java new file mode 100644 index 0000000..8a12a0e --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java @@ -0,0 +1,137 @@ +// *************************************************************************************************************************** +// * 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.rest; + +import java.lang.reflect.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.urlencoding.*; + +/** + * Represents the path parameters on an HTTP request. + */ +@SuppressWarnings("unchecked") +public class RequestPathParams extends TreeMap<String,String> { + private static final long serialVersionUID = 1L; + + private UrlEncodingParser parser; + private BeanSession beanSession; + + RequestPathParams() { + super(String.CASE_INSENSITIVE_ORDER); + } + + RequestPathParams setParser(UrlEncodingParser parser) { + this.parser = parser; + return this; + } + + RequestPathParams setBeanSession(BeanSession beanSession) { + this.beanSession = beanSession; + return this; + } + + /** + * Sets a request query parameter value. + * + * @param name The parameter name. + * @param value The parameter value. + */ + public void put(String name, Object value) { + put(name, value); + } + + /** + * Returns the specified path parameter converted to a POJO. + * <p> + * The type can be any POJO type convertable from a <code>String</code> (See <a class="doclink" + * href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>). + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into an integer.</jc> + * <jk>int</jk> myparam = req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>.<jk>class</jk>); + * + * <jc>// Parse into an int array.</jc> + * <jk>int</jk>[] myparam = req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>); + + * <jc>// Parse into a bean.</jc> + * MyBean myparam = req.getPathParameter(<js>"myparam"</js>, MyBean.<jk>class</jk>); + * + * <jc>// Parse into a linked-list of objects.</jc> + * List myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>); + * + * <jc>// Parse into a map of object keys/values.</jc> + * Map myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>); + * </p> + * + * @param name The attribute name. + * @param type The class type to convert the attribute value to. + * @param <T> The class type to convert the attribute value to. + * @return The attribute value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, Class<T> type) throws ParseException { + return parse(name, beanSession.getClassMeta(type)); + } + + /** + * Returns the specified path parameter converted to a POJO. + * <p> + * The type can be any POJO type convertable from a <code>String</code> (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>). + * <p> + * Use this method if you want to parse into a parameterized <code>Map</code>/<code>Collection</code> object. + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into a linked-list of strings.</jc> + * List<String> myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a linked-list of linked-lists of strings.</jc> + * List<List<String>> myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a map of string keys/values.</jc> + * Map<String,String> myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> + * Map<String,List<MyBean>> myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); + * </p> + * + * @param name The attribute name. + * @param type The type of object to create. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * @param args The type arguments of the class if it's a collection or map. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * <br>Ignored if the main type is not a map or collection. + * @param <T> The class type to convert the attribute value to. + * @return The attribute value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, Type type, Type...args) throws ParseException { + return (T)parse(name, beanSession.getClassMeta(type, args)); + } + + /* Workhorse method */ + <T> T parse(String name, ClassMeta<T> cm) throws ParseException { + Object attr = get(name); + T t = null; + if (attr != null) + t = parser.parsePart(attr.toString(), cm); + if (t == null && cm.isPrimitive()) + return cm.getPrimitiveDefault(); + return t; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java new file mode 100644 index 0000000..6a9a564 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java @@ -0,0 +1,287 @@ +// *************************************************************************************************************************** +// * 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.rest; + +import java.lang.reflect.*; +import java.util.*; + +import javax.servlet.http.*; + +import org.apache.juneau.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.urlencoding.*; + +/** + * Represents the query parameters in an HTTP request. + */ +@SuppressWarnings("unchecked") +public final class RequestQuery extends LinkedHashMap<String,String[]> { + private static final long serialVersionUID = 1L; + + private UrlEncodingParser parser; + private BeanSession beanSession; + + RequestQuery setParser(UrlEncodingParser parser) { + this.parser = parser; + return this; + } + + RequestQuery setBeanSession(BeanSession beanSession) { + this.beanSession = beanSession; + return this; + } + + /** + * Sets a request query parameter value. + * + * @param name The parameter name. + * @param value The parameter value. + */ + public void put(String name, Object value) { + put(name, new String[]{StringUtils.toString(value)}); + } + + /** + * Returns a query parameter value. + * <p> + * Same as {@link HttpServletRequest#getParameter(String)} except only looks in the URL string, not parameters from URL-Encoded FORM posts. + * <p> + * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body. + * + * @param name The URL parameter name. + * @return The parameter value, or <jk>null</jk> if parameter not specified or has no value (e.g. <js>"&foo"</js>. + */ + public String getFirst(String name) { + String[] v = get(name); + if (v == null || v.length == 0) + return null; + if (v.length == 1 && v[0] != null && v[0].isEmpty()) { + // Fix for behavior difference between Tomcat and WAS. + // getParameter("foo") on "&foo" in Tomcat returns "". + // getParameter("foo") on "&foo" in WAS returns null. + if (containsKey(name)) + return null; + } + return v[0]; + } + + /** + * Same as {@link #getFirst(String)} but returns the specified default value if the query parameter was not specified. + * + * @param name The URL parameter name. + * @param def The default value. + * @return The parameter value, or the default value if parameter not specified or has no value (e.g. <js>"&foo"</js>. + */ + public String getFirst(String name, String def) { + String s = getFirst(name); + return s == null ? def : s; + } + + /** + * Returns the specified query parameter value converted to a POJO. + * <p> + * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body. + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into an integer.</jc> + * <jk>int</jk> myparam = req.getQueryParameter(<js>"myparam"</js>, <jk>int</jk>.<jk>class</jk>); + * + * <jc>// Parse into an int array.</jc> + * <jk>int</jk>[] myparam = req.getQueryParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>); + + * <jc>// Parse into a bean.</jc> + * MyBean myparam = req.getQueryParameter(<js>"myparam"</js>, MyBean.<jk>class</jk>); + * + * <jc>// Parse into a linked-list of objects.</jc> + * List myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>); + * + * <jc>// Parse into a map of object keys/values.</jc> + * Map myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>); + * </p> + * + * @param name The parameter name. + * @param type The class type to convert the parameter value to. + * @param <T> The class type to convert the parameter value to. + * @return The parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, Class<T> type) throws ParseException { + return get(name, beanSession.getClassMeta(type)); + } + + /** + * Same as {@link #get(String, Class)} except returns a default value if not found. + * + * @param name The parameter name. + * @param def The default value if the parameter was not specified or is <jk>null</jk>. + * @param type The class type to convert the parameter value to. + * @param <T> The class type to convert the parameter value to. + * @return The parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, T def, Class<T> type) throws ParseException { + return get(name, def, beanSession.getClassMeta(type)); + } + + /** + * Returns the specified query parameter value converted to a POJO. + * <p> + * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body. + * <p> + * Use this method if you want to parse into a parameterized <code>Map</code>/<code>Collection</code> object. + * <p> + * <h5 class='section'>Examples:</h5> + * <p class='bcode'> + * <jc>// Parse into a linked-list of strings.</jc> + * Listt<String> myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a linked-list of linked-lists of strings.</jc> + * Listt<List<String>> myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a map of string keys/values.</jc> + * Map<String,String> myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); + * + * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> + * Map<String,List<MyBean>> myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); + * </p> + * + * @param name The parameter name. + * @param type The type of object to create. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * @param args The type arguments of the class if it's a collection or map. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * <br>Ignored if the main type is not a map or collection. + * @param <T> The class type to convert the parameter value to. + * @return The parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, Type type, Type...args) throws ParseException { + return (T)parse(name, beanSession.getClassMeta(type, args)); + } + + /** + * Same as {@link #get(String, Class)} except returns a default value if not found. + * + * @param name The parameter name. + * @param type The type of object to create. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * @param args The type arguments of the class if it's a collection or map. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * <br>Ignored if the main type is not a map or collection. + * @param def The default value if the parameter was not specified or is <jk>null</jk>. + * @param <T> The class type to convert the parameter value to. + * @return The parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T get(String name, Object def, Type type, Type...args) throws ParseException { + return (T)parse(name, def, beanSession.getClassMeta(type, args)); + } + + /** + * Same as {@link #get(String, Class)} except for use on multi-part parameters + * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>). + * <p> + * This method must only be called when parsing into classes of type Collection or array. + * + * @param name The query parameter name. + * @param c The class type to convert the parameter value to. + * @param <T> The class type to convert the parameter value to. + * @return The query parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T getAll(String name, Class<T> c) throws ParseException { + return getAll(name, beanSession.getClassMeta(c)); + } + + /** + * Same as {@link #get(String, Type, Type...)} except for use on multi-part parameters + * (e.g. <js>"&key=1&key=2&key=3"</js> instead of <js>"&key=(1,2,3)"</js>). + * <p> + * This method must only be called when parsing into classes of type Collection or array. + * + * @param name The query parameter name. + * @param type The type of object to create. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * @param args The type arguments of the class if it's a collection or map. + * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} + * <br>Ignored if the main type is not a map or collection. + * @param <T> The class type to convert the parameter value to. + * @return The query parameter value converted to the specified class type. + * @throws ParseException + */ + public <T> T getAll(String name, Type type, Type...args) throws ParseException { + return (T)parseAll(name, beanSession.getClassMeta(type, args)); + } + + /** + * Returns <jk>true</jk> if the request contains any of the specified query parameters. + * + * @param params The list of parameters to check for. + * @return <jk>true</jk> if the request contains any of the specified query parameters. + */ + public boolean containsAnyKeys(String...params) { + for (String p : params) + if (containsKey(p)) + return true; + return false; + } + + /* Workhorse method */ + private <T> T parse(String name, T def, ClassMeta<T> cm) throws ParseException { + String val = getFirst(name); + if (val == null) + return def; + return parseValue(val, cm); + } + + /* Workhorse method */ + private <T> T parse(String name, ClassMeta<T> cm) throws ParseException { + String val = getFirst(name); + if (cm.isPrimitive() && (val == null || val.isEmpty())) + return cm.getPrimitiveDefault(); + return parseValue(val, cm); + } + + /* Workhorse method */ + @SuppressWarnings("rawtypes") + private <T> T parseAll(String name, ClassMeta<T> cm) throws ParseException { + String[] p = get(name); + if (p == null) + return null; + if (cm.isArray()) { + List c = new ArrayList(); + for (int i = 0; i < p.length; i++) + c.add(parseValue(p[i], cm.getElementType())); + return (T)ArrayUtils.toArray(c, cm.getElementType().getInnerClass()); + } else if (cm.isCollection()) { + try { + Collection c = (Collection)(cm.canCreateNewInstance() ? cm.newInstance() : new ObjectList()); + for (int i = 0; i < p.length; i++) + c.add(parseValue(p[i], cm.getElementType())); + return (T)c; + } catch (ParseException e) { + throw e; + } catch (Exception e) { + // Typically an instantiation exception. + throw new ParseException(e); + } + } + throw new ParseException("Invalid call to getQueryParameters(String, ClassMeta). Class type must be a Collection or array."); + } + + private <T> T parseValue(String val, ClassMeta<T> c) throws ParseException { + return parser.parsePart(val, c); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java index 97ab2d4..54a3fa0 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java @@ -444,7 +444,7 @@ public final class RestContext extends Context { if (m != null) { try { // Parse the args and invoke the method. - Parser p = req.getParser(); + Parser p = req.getBody().getParser(); Object input = p.isReaderParser() ? req.getReader() : req.getInputStream(); Object output = m.invoke(o, p.parseArgs(input, m.getGenericParameterTypes())); res.setOutput(output); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java new file mode 100644 index 0000000..a900c14 --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java @@ -0,0 +1,978 @@ +// *************************************************************************************************************************** +// * 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.rest; + +import static org.apache.juneau.rest.RestParamType.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.logging.*; + +import javax.servlet.*; +import javax.servlet.http.*; + +import org.apache.juneau.*; +import org.apache.juneau.dto.swagger.*; +import org.apache.juneau.http.*; +import org.apache.juneau.http.Date; +import org.apache.juneau.ini.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.utils.*; + +/** + * REST java method parameter resolver. + */ +public abstract class RestParam { + + /** + * Standard set of method parameter resolvers. + */ + public static final Map<Class<?>,RestParam> STANDARD_RESOLVERS; + + static { + Map<Class<?>,RestParam> m = new HashMap<Class<?>,RestParam>(); + + @SuppressWarnings("rawtypes") + Class[] r = new Class[] { + + // Standard top-level objects + HttpServletRequestObject.class, + RestRequestObject.class, + HttpServletResponseObject.class, + RestResponseObject.class, + + // Headers + AcceptHeader.class, + AcceptCharsetHeader.class, + AcceptEncodingHeader.class, + AcceptLanguageHeader.class, + AuthorizationHeader.class, + CacheControlHeader.class, + ConnectionHeader.class, + ContentLengthHeader.class, + ContentTypeHeader.class, + DateHeader.class, + ExpectHeader.class, + FromHeader.class, + HostHeader.class, + IfMatchHeader.class, + IfModifiedSinceHeader.class, + IfNoneMatchHeader.class, + IfRangeHeader.class, + IfUnmodifiedSinceHeader.class, + MaxForwardsHeader.class, + PragmaHeader.class, + ProxyAuthorizationHeader.class, + RangeHeader.class, + RefererHeader.class, + TEHeader.class, + UserAgentHeader.class, + UpgradeHeader.class, + ViaHeader.class, + WarningHeader.class, + TimeZoneHeader.class, + + // Other objects + ResourceBundleObject.class, + MessageBundleObject.class, + InputStreamObject.class, + ServletInputStreamObject.class, + ReaderObject.class, + OutputStreamObject.class, + ServletOutputStreamObject.class, + WriterObject.class, + RequestHeadersObject.class, + RequestQueryParamsObject.class, + RequestFormDataObject.class, + HttpMethodObject.class, + LoggerObject.class, + JuneauLoggerObject.class, + RestContextObject.class, + ParserObject.class, + LocaleObject.class, + SwaggerObject.class, + RequestPathParamsObject.class, + RequestBodyObject.class, + ConfigFileObject.class, + }; + + for (Class<?> c : r) { + try { + RestParam mpr = (RestParam)c.newInstance(); + m.put(mpr.forClass(), mpr); + } catch (Exception e) { + e.printStackTrace(); + } + } + + STANDARD_RESOLVERS = Collections.unmodifiableMap(m); + } + + final RestParamType paramType; + final String name; + final Type type; + + /** + * 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 RestParam(RestParamType paramType, String name, Type type) { + this.paramType = paramType; + this.name = name; + this.type = type; + } + + /** + * Resolves the parameter object. + * + * @param req The rest request. + * @param res The rest response. + * @return The resolved object. + * @throws Exception + */ + public abstract Object resolve(RestRequest req, RestResponse res) throws Exception; + + /** + * Returns the parameter class type that this parameter resolver is meant for. + * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}. + */ + protected Class<?> forClass() { + if (type instanceof Class) + return (Class<?>)type; + return null; + } + + /** + * Returns the swagger parameter type for this parameter as shown in the Swagger doc. + * @return the swagger parameter type for this parameter. + */ + protected RestParamType getParamType() { + return paramType; + } + + /** + * Returns the parameter name for this parameter as shown in the Swagger doc. + * @return the parameter name for this parameter. + */ + protected String getName() { + return name; + } + + //------------------------------------------------------------------------------------------------------------------- + // Request / Response retrievers + //------------------------------------------------------------------------------------------------------------------- + + static final class HttpServletRequestObject extends RestParam { + + protected HttpServletRequestObject() { + super(OTHER, null, HttpServletRequest.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) { + return req; + } + } + + static final class HttpServletResponseObject extends RestParam { + + protected HttpServletResponseObject() { + super(OTHER, null, HttpServletResponse.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) { + return res; + } + } + + static final class RestRequestObject extends RestParam { + + protected RestRequestObject() { + super(OTHER, null, RestRequest.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) { + return req; + } + } + + static final class RestResponseObject extends RestParam { + + protected RestResponseObject() { + super(OTHER, null, RestResponse.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) { + return res; + } + } + + //------------------------------------------------------------------------------------------------------------------- + // Header retrievers + //------------------------------------------------------------------------------------------------------------------- + + static final class AcceptHeader extends RestParam { + + protected AcceptHeader() { + super(HEADER, "Accept-Header", AcceptHeader.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getAccept(); + } + } + + static final class AcceptCharsetHeader extends RestParam { + + protected AcceptCharsetHeader() { + super(HEADER, "Accept-Charset", AcceptCharset.class); + } + + @Override /* RestParam */ + public AcceptCharset resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getAcceptCharset(); + } + } + + static final class AcceptEncodingHeader extends RestParam { + + protected AcceptEncodingHeader() { + super(HEADER, "Accept-Encoding", AcceptEncoding.class); + } + + @Override + public AcceptEncoding resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getAcceptEncoding(); + } + } + + static final class AcceptLanguageHeader extends RestParam { + + protected AcceptLanguageHeader() { + super(HEADER, "Accept-Language", AcceptLanguage.class); + } + + @Override + public AcceptLanguage resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getAcceptLanguage(); + } + } + + static final class AuthorizationHeader extends RestParam { + + protected AuthorizationHeader() { + super(HEADER, "Authorization", Authorization.class); + } + + @Override + public Authorization resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getAuthorization(); + } + } + + static final class CacheControlHeader extends RestParam { + + protected CacheControlHeader() { + super(HEADER, "Cache-Control", CacheControl.class); + } + + @Override + public CacheControl resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getCacheControl(); + } + } + + static final class ConnectionHeader extends RestParam { + + protected ConnectionHeader() { + super(HEADER, "Connection", Connection.class); + } + + @Override + public Connection resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getConnection(); + } + } + + static final class ContentLengthHeader extends RestParam { + + protected ContentLengthHeader() { + super(HEADER, "Content-Length", ContentLength.class); + } + + @Override + public ContentLength resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getContentLength(); + } + } + + static final class ContentTypeHeader extends RestParam { + + protected ContentTypeHeader() { + super(HEADER, "Content-Type", ContentType.class); + } + + @Override + public ContentType resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getContentType(); + } + } + + static final class DateHeader extends RestParam { + + protected DateHeader() { + super(HEADER, "Date", Date.class); + } + + @Override + public Date resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getDate(); + } + } + + static final class ExpectHeader extends RestParam { + + protected ExpectHeader() { + super(HEADER, "Expect", Expect.class); + } + + @Override + public Expect resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getExpect(); + } + } + + static final class FromHeader extends RestParam { + + protected FromHeader() { + super(HEADER, "From", From.class); + } + + @Override + public From resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getFrom(); + } + } + + static final class HostHeader extends RestParam { + + protected HostHeader() { + super(HEADER, "Host", Host.class); + } + + @Override + public Host resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getHost(); + } + } + + static final class IfMatchHeader extends RestParam { + + protected IfMatchHeader() { + super(HEADER, "If-Match", IfMatch.class); + } + + @Override + public IfMatch resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getIfMatch(); + } + } + + static final class IfModifiedSinceHeader extends RestParam { + + protected IfModifiedSinceHeader() { + super(HEADER, "If-Modified-Since", IfModifiedSince.class); + } + + @Override + public IfModifiedSince resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getIfModifiedSince(); + } + } + + static final class IfNoneMatchHeader extends RestParam { + + protected IfNoneMatchHeader() { + super(HEADER, "If-None-Match", IfNoneMatch.class); + } + + @Override + public IfNoneMatch resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getIfNoneMatch(); + } + } + + static final class IfRangeHeader extends RestParam { + + protected IfRangeHeader() { + super(HEADER, "If-Range", IfRange.class); + } + + @Override + public IfRange resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getIfRange(); + } + } + + static final class IfUnmodifiedSinceHeader extends RestParam { + + protected IfUnmodifiedSinceHeader() { + super(HEADER, "If-Unmodified-Since", IfUnmodifiedSince.class); + } + + @Override + public IfUnmodifiedSince resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getIfUnmodifiedSince(); + } + } + + static final class MaxForwardsHeader extends RestParam { + + protected MaxForwardsHeader() { + super(HEADER, "Max-Forwards", MaxForwards.class); + } + + @Override + public MaxForwards resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getMaxForwards(); + } + } + + static final class PragmaHeader extends RestParam { + + protected PragmaHeader() { + super(HEADER, "Pragma", Pragma.class); + } + + @Override + public Pragma resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getPragma(); + } + } + + static final class ProxyAuthorizationHeader extends RestParam { + + protected ProxyAuthorizationHeader() { + super(HEADER, "Proxy-Authorization", ProxyAuthorization.class); + } + + @Override + public ProxyAuthorization resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getProxyAuthorization(); + } + } + + static final class RangeHeader extends RestParam { + + protected RangeHeader() { + super(HEADER, "Range", Range.class); + } + + @Override + public Range resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getRange(); + } + } + + static final class RefererHeader extends RestParam { + + protected RefererHeader() { + super(HEADER, "Referer", Referer.class); + } + + @Override + public Referer resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getReferer(); + } + } + + static final class TEHeader extends RestParam { + + protected TEHeader() { + super(HEADER, "TE", TE.class); + } + + @Override + public TE resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getTE(); + } + } + + static final class UserAgentHeader extends RestParam { + + protected UserAgentHeader() { + super(HEADER, "User-Agent", UserAgent.class); + } + + @Override + public UserAgent resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getUserAgent(); + } + } + + static final class UpgradeHeader extends RestParam { + + protected UpgradeHeader() { + super(HEADER, "Upgrade", Upgrade.class); + } + + @Override + public Upgrade resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getUpgrade(); + } + } + + static final class ViaHeader extends RestParam { + + protected ViaHeader() { + super(HEADER, "Via", Via.class); + } + + @Override + public Via resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getVia(); + } + } + + static final class WarningHeader extends RestParam { + + protected WarningHeader() { + super(HEADER, "Warning", Warning.class); + } + + @Override + public Warning resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getWarning(); + } + } + + static final class TimeZoneHeader extends RestParam { + + protected TimeZoneHeader() { + super(HEADER, "Time-Zone", TimeZone.class); + } + + @Override + public TimeZone resolve(RestRequest req, RestResponse res) { + return req.getHeaders().getTimeZone(); + } + } + + //------------------------------------------------------------------------------------------------------------------- + // Annotated retrievers + //------------------------------------------------------------------------------------------------------------------- + + static final class PathParameterObject extends RestParam { + + protected PathParameterObject(String name, Type type) { + super(PATH, name, type); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getPathParams().get(name, type); + } + } + + static final class BodyObject extends RestParam { + + protected BodyObject(Type type) { + super(BODY, null, type); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getBody().asType(type); + } + } + + static final class HeaderObject extends RestParam { + + protected HeaderObject(String name, Type type) { + super(HEADER, name, type); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getHeaders().get(name, type); + } + } + + static final class MethodObject extends RestParam { + + protected MethodObject() { + super(OTHER, null, null); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getMethod(); + } + } + + static final class FormDataObject extends RestParam { + private final boolean multiPart, plainParams; + + protected FormDataObject(String name, Type type, boolean multiPart, boolean plainParams) { + super(FORMDATA, name, type); + this.multiPart = multiPart; + this.plainParams = plainParams; + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + BeanSession bs = req.getBeanSession(); + if (multiPart) + return req.getFormData().getAll(name, type); + if (plainParams) + return bs.convertToType(req.getFormData(name), bs.getClassMeta(type)); + return req.getFormData().get(name, type); + } + } + + static final class QueryObject extends RestParam { + private final boolean multiPart, plainParams; + + protected QueryObject(String name, Type type, boolean multiPart, boolean plainParams) { + super(QUERY, name, type); + this.multiPart = multiPart; + this.plainParams = plainParams; + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + BeanSession bs = req.getBeanSession(); + if (multiPart) + return req.getQuery().getAll(name, type); + if (plainParams) + return bs.convertToType(req.getQuery(name), bs.getClassMeta(type)); + return req.getQuery().get(name, type); + } + } + + static final class HasFormDataObject extends RestParam { + + protected HasFormDataObject(String name, Type type) { + super(FORMDATA, name, type); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + BeanSession bs = req.getBeanSession(); + return bs.convertToType(req.getFormData().containsKey(name), bs.getClassMeta(type)); + } + } + + static final class HasQueryObject extends RestParam { + + protected HasQueryObject(String name, Type type) { + super(QUERY, name, type); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + BeanSession bs = req.getBeanSession(); + return bs.convertToType(req.getQuery().containsKey(name), bs.getClassMeta(type)); + } + } + + static final class PathRemainderObject extends RestParam { + + protected PathRemainderObject() { + super(OTHER, null, null); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getPathRemainder(); + } + } + + static final class PropsObject extends RestParam { + + protected PropsObject() { + super(OTHER, null, null); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getProperties(); + } + } + + //------------------------------------------------------------------------------------------------------------------- + // Other retrievers + //------------------------------------------------------------------------------------------------------------------- + + static final class ResourceBundleObject extends RestParam { + + protected ResourceBundleObject() { + super(OTHER, null, ResourceBundle.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getResourceBundle(); + } + } + + static final class MessageBundleObject extends RestParam { + + protected MessageBundleObject() { + super(OTHER, null, MessageBundle.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getResourceBundle(); + } + } + + static final class InputStreamObject extends RestParam { + + protected InputStreamObject() { + super(OTHER, null, InputStream.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getInputStream(); + } + } + + static final class ServletInputStreamObject extends RestParam { + + protected ServletInputStreamObject() { + super(OTHER, null, ServletInputStream.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getInputStream(); + } + } + + static final class ReaderObject extends RestParam { + + protected ReaderObject() { + super(OTHER, null, Reader.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getReader(); + } + } + + static final class OutputStreamObject extends RestParam { + + protected OutputStreamObject() { + super(OTHER, null, OutputStream.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return res.getOutputStream(); + } + } + + static final class ServletOutputStreamObject extends RestParam { + + protected ServletOutputStreamObject() { + super(OTHER, null, ServletOutputStream.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return res.getOutputStream(); + } + } + + static final class WriterObject extends RestParam { + + protected WriterObject() { + super(OTHER, null, Writer.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return res.getWriter(); + } + } + + static final class RequestHeadersObject extends RestParam { + + protected RequestHeadersObject() { + super(OTHER, null, RequestHeaders.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getHeaders(); + } + } + + static final class RequestQueryParamsObject extends RestParam { + + protected RequestQueryParamsObject() { + super(OTHER, null, RequestQuery.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getQuery(); + } + } + + static final class RequestFormDataObject extends RestParam { + + protected RequestFormDataObject() { + super(OTHER, null, RequestFormData.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getFormData(); + } + } + + static final class HttpMethodObject extends RestParam { + + protected HttpMethodObject() { + super(OTHER, null, HttpMethod.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getHttpMethod(); + } + } + + static final class LoggerObject extends RestParam { + + protected LoggerObject() { + super(OTHER, null, Logger.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getContext().getLogger().getLogger(); + } + } + + static final class JuneauLoggerObject extends RestParam { + + protected JuneauLoggerObject() { + super(OTHER, null, JuneauLogger.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getContext().getLogger().getLogger(); + } + } + + static final class RestContextObject extends RestParam { + + protected RestContextObject() { + super(OTHER, null, RestContext.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getContext(); + } + } + + static final class ParserObject extends RestParam { + + protected ParserObject() { + super(OTHER, null, Parser.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getBody().getParser(); + } + } + + static final class LocaleObject extends RestParam { + + protected LocaleObject() { + super(OTHER, null, Locale.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getLocale(); + } + } + + static final class SwaggerObject extends RestParam { + + protected SwaggerObject() { + super(OTHER, null, Swagger.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getSwagger(); + } + } + + static final class RequestPathParamsObject extends RestParam { + + protected RequestPathParamsObject() { + super(OTHER, null, RequestPathParams.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getPathParams(); + } + } + + static final class RequestBodyObject extends RestParam { + + protected RequestBodyObject() { + super(BODY, null, RequestBody.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getBody(); + } + } + + static final class ConfigFileObject extends RestParam { + + protected ConfigFileObject() { + super(OTHER, null, ConfigFile.class); + } + + @Override /* RestParam */ + public Object resolve(RestRequest req, RestResponse res) throws Exception { + return req.getConfigFile(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java new file mode 100644 index 0000000..70fe2eb --- /dev/null +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java @@ -0,0 +1,48 @@ +// *************************************************************************************************************************** +// * 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.rest; + +/** + * Represents the possible parameter types as defined by the Swagger 2.0 specification. + */ +public enum RestParamType { + + /** Path variable */ + PATH("path"), + + /** Header value */ + HEADER("header"), + + /** Form data entry */ + FORMDATA("formData"), + + /** Query parameter */ + QUERY("query"), + + /** Request body */ + BODY("body"), + + /** Not a standard Swagger-defined field */ + OTHER("other"); + + private final String value; + + private RestParamType(String value) { + this.value = value; + } + + @Override /* Object */ + public String toString() { + return value; + } +}
