All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.rest.RequestPath Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * 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.internal.StringUtils.*;

import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.oapi.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.rest.exception.*;

/**
 * Contains information about the matched path on the HTTP request.
 *
 * 

* Provides access to the matched path variables and path match remainder. * *

See Also:
*
    *
*/ public class RequestPath extends TreeMap { private static final long serialVersionUID = 1L; private final RestRequest req; private HttpPartParser parser; private String pattern; RequestPath(RestRequest req) { super(String.CASE_INSENSITIVE_ORDER); this.req = req; } RequestPath parser(HttpPartParser parser) { this.parser = parser; return this; } RequestPath remainder(String remainder) { put("/**", remainder); put("/*", urlDecode(remainder)); return this; } RequestPath pattern(String pattern) { this.pattern = pattern; 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) { super.put(name, value.toString()); } /** * Returns the specified path parameter converted to a String. * * @param name The path variable name. * @return The parameter value. * @throws BadRequest Thrown if input could not be parsed. * @throws InternalServerError Thrown if any other exception occurs. */ public String getString(String name) throws BadRequest, InternalServerError { return getInner(parser, null, name, null, req.getBeanSession().string()); } /** * Returns the specified path parameter converted to an integer. * * @param name The path variable name. * @return The parameter value. * @throws BadRequest Thrown if input could not be parsed. * @throws InternalServerError Thrown if any other exception occurs. */ public int getInt(String name) throws BadRequest, InternalServerError { return getInner(parser, null, name, null, getClassMeta(int.class)); } /** * Returns the specified path parameter converted to a boolean. * * @param name The path variable name. * @return The parameter value. * @throws BadRequest Thrown if input could not be parsed. * @throws InternalServerError Thrown if any other exception occurs. */ public boolean getBoolean(String name) throws BadRequest, InternalServerError { return getInner(null, null, name, null, getClassMeta(boolean.class)); } /** * Returns the specified path parameter value converted to a POJO using the {@link HttpPartParser} registered with the resource. * *
Examples:
*

* // Parse into an integer. * int myparam = path.get("myparam", int.class); * * // Parse into an int array. * int[] myparam = path.get("myparam", int[].class); * // Parse into a bean. * MyBean myparam = path.get("myparam", MyBean.class); * * // Parse into a linked-list of objects. * List myparam = path.get("myparam", LinkedList.class); * * // Parse into a map of object keys/values. * Map myparam = path.get("myparam", TreeMap.class); *

* *
See Also:
*
    *
  • {@link RestContext#REST_partParser} *
* * @param name The attribute name. * @param type The class type to convert the attribute value to. * @param The class type to convert the attribute value to. * @return The attribute value converted to the specified class type. * @throws BadRequest Thrown if input could not be parsed. * @throws InternalServerError Thrown if any other exception occurs. */ public T get(String name, Class type) throws BadRequest, InternalServerError { return getInner(null, null, name, null, this.getClassMeta(type)); } /** * Same as {@link #get(String, Class)} but allows you to override the part parser. * * @param parser * The parser to use for parsing the string value. *
If null, uses the part parser defined on the resource/method. * @param schema * The schema object that defines the format of the input. *
If null, defaults to the schema defined on the parser. *
If that's also null, defaults to {@link HttpPartSchema#DEFAULT}. *
Only used if parser is schema-aware (e.g. {@link OpenApiParser}). * @param name The attribute name. * @param type The class type to convert the attribute value to. * @param The class type to convert the attribute value to. * @return The attribute value converted to the specified class type. * @throws BadRequest Thrown if input could not be parsed or fails schema validation. * @throws InternalServerError Thrown if any other exception occurs. */ public T get(HttpPartParser parser, HttpPartSchema schema, String name, Class type) throws BadRequest, InternalServerError { return getInner(parser, schema, name, null, this.getClassMeta(type)); } /** * Returns the specified query parameter value converted to a POJO using the {@link HttpPartParser} registered with the resource. * *

* Similar to {@link #get(String,Class)} but allows for complex collections of POJOs to be created. * *

* Use this method if you want to parse into a parameterized Map/Collection object. * *

Examples:
*

* // Parse into a linked-list of strings. * List<String> myparam = req.getPathParameter("myparam", LinkedList.class, String.class); * * // Parse into a linked-list of linked-lists of strings. * List<List<String>> myparam = req.getPathParameter("myparam", LinkedList.class, LinkedList.class, String.class); * * // Parse into a map of string keys/values. * Map<String,String> myparam = req.getPathParameter("myparam", TreeMap.class, String.class, String.class); * * // Parse into a map containing string keys and values of lists containing beans. * Map<String,List<MyBean>> myparam = req.getPathParameter("myparam", TreeMap.class, String.class, List.class, MyBean.class); *

* *
Notes:
*
    *
  • * Collections must be followed by zero or one parameter representing the value type. *
  • * Maps must be followed by zero or two parameters representing the key and value types. *
* *
See Also:
*
    *
  • {@link RestContext#REST_partParser} *
* * @param name The attribute name. * @param type * The type of object to create. *
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. *
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} *
Ignored if the main type is not a map or collection. * @param The class type to convert the attribute value to. * @return The attribute value converted to the specified class type. * @throws BadRequest Thrown if input could not be parsed. * @throws InternalServerError Thrown if any other exception occurs. */ public T get(String name, Type type, Type...args) throws BadRequest, InternalServerError { return getInner(null, null, name, null, this.getClassMeta(type, args)); } /** * Same as {@link #get(String, Type, Type...)} but allows you to override the part parser. * * @param parser * The parser to use for parsing the string value. *
If null, uses the part parser defined on the resource/method. * @param schema * The schema object that defines the format of the input. *
If null, defaults to the schema defined on the parser. *
If that's also null, defaults to {@link HttpPartSchema#DEFAULT}. *
Only used if parser is schema-aware (e.g. {@link OpenApiParser}). * @param name The attribute name. * @param type * The type of object to create. *
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. *
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} *
Ignored if the main type is not a map or collection. * @param The class type to convert the attribute value to. * @return The attribute value converted to the specified class type. * @throws BadRequest Thrown if input could not be parsed or fails schema validation. * @throws InternalServerError Thrown if any other exception occurs. */ public T get(HttpPartParser parser, HttpPartSchema schema, String name, Type type, Type...args) throws BadRequest, InternalServerError { return getInner(parser, schema, name, null, this.getClassMeta(type, args)); } /* Workhorse method */ private T getInner(HttpPartParser parser, HttpPartSchema schema, String name, T def, ClassMeta cm) throws BadRequest, InternalServerError { try { if (cm.isMapOrBean() && isOneOf(name, "*", "")) { ObjectMap m = new ObjectMap(); for (Map.Entry e : this.entrySet()) { String k = e.getKey(); HttpPartSchema pschema = schema == null ? null : schema.getProperty(k); ClassMeta cm2 = cm.getValueType(); m.put(k, getInner(parser, pschema, k, null, cm2)); } return req.getBeanSession().convertToType(m, cm); } T t = parse(parser, schema, get(name), cm); return (t == null ? def : t); } catch (SchemaValidationException e) { throw new BadRequest(e, "Validation failed on path parameter ''{0}''. ", name); } catch (ParseException e) { throw new BadRequest(e, "Could not parse path parameter ''{0}''.", name) ; } catch (Exception e) { throw new InternalServerError(e, "Could not parse path parameter ''{0}''.", name) ; } } /* Workhorse method */ private T parse(HttpPartParser parser, HttpPartSchema schema, String val, ClassMeta cm) throws SchemaValidationException, ParseException { if (parser == null) parser = this.parser; return parser.createPartSession(req.getParserSessionArgs()).parse(HttpPartType.PATH, schema, val, cm); } /** * Returns the decoded remainder of the URL following any path pattern matches. * *

* The behavior of path remainder is shown below given the path pattern "/foo/*": *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
URLPath Remainder
/foonull
/foo/""
/foo//"/"
/foo///"//"
/foo/a/b"a/b"
/foo//a/b/"/a/b/"
/foo/a%2Fb"a/b"
* *
Example:
*

* // REST method * @RestMethod(name=GET,path="/foo/{bar}/*") * public String doGetById(RequestPathMatch path, int bar) { * return path.getRemainder(); * } *

* *

* The remainder can also be retrieved by calling get("/*"). * * @return The path remainder string. */ public String getRemainder() { return get("/*"); } /** * Same as {@link #getRemainder()} but doesn't decode characters. * *

* The undecoded remainder can also be retrieved by calling get("/**"). * * @return The un-decoded path remainder. */ public String getRemainderUndecoded() { return get("/**"); } /** * Returns the path pattern that matched this request. * * @return The path pattern that matched this request. */ public String getPattern() { return pattern; } //----------------------------------------------------------------------------------------------------------------- // Helper methods //----------------------------------------------------------------------------------------------------------------- private ClassMeta getClassMeta(Type type, Type...args) { return req.getBeanSession().getClassMeta(type, args); } private ClassMeta getClassMeta(Class type) { return req.getBeanSession().getClassMeta(type); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy