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

jakarta.ws.rs.core.UriBuilder Maven / Gradle / Ivy

/*
 * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.ws.rs.core;

import java.lang.reflect.Method;
import java.net.URI;
import java.util.Map;

import jakarta.ws.rs.ext.RuntimeDelegate;

/**
 * URI template-aware utility class for building URIs from their components. See {@link jakarta.ws.rs.Path#value} for an
 * explanation of URI templates.
 *
 * 

* Builder methods perform contextual encoding of characters not permitted in the corresponding URI component following * the rules of the * application/x-www-form-urlencoded media type * for query parameters and RFC 3986 for all other components. Note that * only characters not permitted in a particular component are subject to encoding so, e.g., a path supplied to one of * the {@code path} methods may contain matrix parameters or multiple path segments since the separators are legal * characters and will not be encoded. Percent encoded values are also recognized where allowed and will not be double * encoded. *

* *

* URI templates are allowed in most components of a URI but their value is restricted to a particular component. E.g. *

UriBuilder.fromPath("{arg1}").build("foo#bar");
would result in encoding of the * '#' such that the resulting URI is "foo%23bar". To create a URI "foo#bar" use *
UriBuilder.fromPath("{arg1}").fragment("{arg2}").build("foo", "bar")
instead. * URI template names and delimiters are never encoded but their values are encoded when a URI is built. Template * parameter regular expressions are ignored when building a URI, i.e. no validation is performed. * * @author Paul Sandoz * @author Marc Hadley * @see java.net.URI * @see jakarta.ws.rs.Path * @since 1.0 */ public abstract class UriBuilder { /** * Protected constructor, use one of the static fromXxx(...) methods to obtain an instance. */ protected UriBuilder() { } /** * Creates a new instance of UriBuilder. * * @return a new instance of UriBuilder. * @since 3.0 */ public static UriBuilder newInstance() { return RuntimeDelegate.getInstance().createUriBuilder(); } /** * Create a new instance initialized from an existing URI. * * @param uri a URI that will be used to initialize the UriBuilder. * @return a new UriBuilder. * @throws IllegalArgumentException if uri is {@code null}. */ public static UriBuilder fromUri(final URI uri) { return newInstance().uri(uri); } /** * Create a new instance initialized from an existing URI. * * @param uriTemplate a URI template that will be used to initialize the UriBuilder, may contain URI parameters. * @return a new UriBuilder. * @throws IllegalArgumentException if {@code uriTemplate} is not a valid URI template or is {@code null}. */ public static UriBuilder fromUri(final String uriTemplate) { return newInstance().uri(uriTemplate); } /** * Create a new instance initialized from a Link. * * @param link a Link that will be used to initialize the UriBuilder, only its URI is used. * @return a new UriBuilder * @throws IllegalArgumentException if link is {@code null} * @since 2.0 */ public static UriBuilder fromLink(final Link link) { if (link == null) { throw new IllegalArgumentException("The provider 'link' parameter value is 'null'."); } return UriBuilder.fromUri(link.getUri()); } /** * Create a new instance representing a relative URI initialized from a URI path. * * @param path a URI path that will be used to initialize the UriBuilder, may contain URI template parameters. * @return a new UriBuilder. * @throws IllegalArgumentException if path is {@code null}. */ public static UriBuilder fromPath(final String path) throws IllegalArgumentException { return newInstance().path(path); } /** * Create a new instance representing a relative URI initialized from a root resource class. * * @param resource a root resource whose {@link jakarta.ws.rs.Path} value will be used to initialize the UriBuilder. * @return a new UriBuilder. * @throws IllegalArgumentException if resource is not annotated with {@link jakarta.ws.rs.Path} or resource is * {@code null}. */ public static UriBuilder fromResource(final Class resource) { return newInstance().path(resource); } /** * Create a new instance representing a relative URI initialized from a {@link jakarta.ws.rs.Path}-annotated method. * * This method can only be used in cases where there is a single method with the specified name that is annotated with * {@link jakarta.ws.rs.Path}. * * @param resource the resource containing the method. * @param method the name of the method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append. * @return the updated UriBuilder. * @throws IllegalArgumentException if resource or method is {@code null}, or there is more than or less than one * variant of the method annotated with {@link jakarta.ws.rs.Path}. * @since 2.0 */ public static UriBuilder fromMethod(final Class resource, final String method) { return newInstance().path(resource, method); } /** * Create a copy of the UriBuilder preserving its state. This is a more efficient means of creating a copy than * constructing a new UriBuilder from a URI returned by the {@link #build(Object...)} method. * * @return a copy of the UriBuilder. */ @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException") @Override public abstract UriBuilder clone(); /** * Copies the non-null components of the supplied URI to the UriBuilder replacing any existing values for those * components. * * @param uri the URI to copy components from. * @return the updated UriBuilder. * @throws IllegalArgumentException if the {@code uri} parameter is {@code null}. */ public abstract UriBuilder uri(URI uri); /** * Parses the {@code uriTemplate} string and copies the parsed components of the supplied URI to the UriBuilder * replacing any existing values for those components. * * @param uriTemplate a URI template that will be used to initialize the UriBuilder, may contain URI parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if {@code uriTemplate} is not a valid URI template or is {@code null}. * @since 2.0 */ public abstract UriBuilder uri(String uriTemplate); /** * Set the URI scheme. * * @param scheme the URI scheme, may contain URI template parameters. A {@code null} value will unset the URI scheme, * but will not unset the any scheme-specific-part components. * @return the updated UriBuilder. * @throws IllegalArgumentException if scheme is invalid. */ public abstract UriBuilder scheme(String scheme); /** * Set the URI scheme-specific-part (see {@link java.net.URI}). This method will overwrite any existing values for * authority, user-info, host, port and path. * * @param ssp the URI scheme-specific-part, may contain URI template parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if ssp cannot be parsed or is {@code null}. */ public abstract UriBuilder schemeSpecificPart(String ssp); /** * Set the URI user-info. * * @param ui the URI user-info, may contain URI template parameters. A {@code null} value will unset userInfo component * of the URI. * @return the updated UriBuilder. */ public abstract UriBuilder userInfo(String ui); /** * Set the URI host. * * @param host the URI host, may contain URI template parameters. A {@code null} value will unset the host component of * the URI, but will not unset other authority component parts ({@link #userInfo(String) user info} or {@link #port(int) * port}). * @return the updated UriBuilder. * @throws IllegalArgumentException if host is invalid. */ public abstract UriBuilder host(String host); /** * Set the URI port. * * @param port the URI port, a value of -1 will unset an explicit port. * @return the updated UriBuilder. * @throws IllegalArgumentException if port is invalid. */ public abstract UriBuilder port(int port); /** * Set the URI path. This method will overwrite any existing path and associated matrix parameters. Existing '/' * characters are preserved thus a single value can represent multiple URI path segments. * * @param path the path, may contain URI template parameters. A {@code null} value will unset the path component of the * URI. * @return the updated UriBuilder. */ public abstract UriBuilder replacePath(String path); /** * Append path to the existing path. When constructing the final path, a '/' separator will be inserted between the * existing path and the supplied path if necessary. Existing '/' characters are preserved thus a single value can * represent multiple URI path segments. * * @param path the path, may contain URI template parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if path is {@code null}. */ public abstract UriBuilder path(String path); /** * Append the path from a Path-annotated class to the existing path. When constructing the final path, a '/' separator * will be inserted between the existing path and the supplied path if necessary. * * @param resource a resource whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append. * @return the updated UriBuilder. * @throws IllegalArgumentException if resource is {@code null}, or if resource is not annotated with * {@link jakarta.ws.rs.Path}. */ public abstract UriBuilder path(Class resource); /** * Append the path from a Path-annotated method to the existing path. When constructing the final path, a '/' separator * will be inserted between the existing path and the supplied path if necessary. This method is a convenience shortcut * to {@code path(Method)}, it can only be used in cases where there is a single method with the specified name that is * annotated with {@link jakarta.ws.rs.Path}. * * @param resource the resource containing the method. * @param method the name of the method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append. * @return the updated UriBuilder. * @throws IllegalArgumentException if resource or method is {@code null}, or there is more than or less than one * variant of the method annotated with {@link jakarta.ws.rs.Path}. */ public abstract UriBuilder path(Class resource, String method); /** * Append the path from a {@link jakarta.ws.rs.Path}-annotated method to the existing path. When constructing the final * path, a '/' separator will be inserted between the existing path and the supplied path if necessary. * * @param method a method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append to the existing * path. * @return the updated UriBuilder. * @throws IllegalArgumentException if method is {@code null} or is not annotated with a {@link jakarta.ws.rs.Path}. */ public abstract UriBuilder path(Method method); /** * Append path segments to the existing path. When constructing the final path, a '/' separator will be inserted between * the existing path and the first path segment if necessary and each supplied segment will also be separated by '/'. * Existing '/' characters are encoded thus a single value can only represent a single URI path segment. * * @param segments the path segment values, each may contain URI template parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if segments or any element of segments is {@code null}. */ public abstract UriBuilder segment(String... segments); /** * Set the matrix parameters of the current final segment of the current URI path. This method will overwrite any * existing matrix parameters on the current final segment of the current URI path. Note that the matrix parameters are * tied to a particular path segment; subsequent addition of path segments will not affect their position in the URI * path. * * @param matrix the matrix parameters, may contain URI template parameters. A {@code null} value will remove all matrix * parameters of the current final segment of the current URI path. * @return the updated UriBuilder. * @throws IllegalArgumentException if matrix cannot be parsed. * @see Matrix URIs */ public abstract UriBuilder replaceMatrix(String matrix); /** * Append a matrix parameter to the existing set of matrix parameters of the current final segment of the URI path. If * multiple values are supplied the parameter will be added once per value. Note that the matrix parameters are tied to * a particular path segment; subsequent addition of path segments will not affect their position in the URI path. * * @param name the matrix parameter name, may contain URI template parameters. * @param values the matrix parameter value(s), each object will be converted. to a {@code String} using its * {@code toString()} method. Stringified values may contain URI template parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if name or values is {@code null}. * @see Matrix URIs */ public abstract UriBuilder matrixParam(String name, Object... values); /** * Replace the existing value(s) of a matrix parameter on the current final segment of the URI path. If multiple values * are supplied the parameter will be added once per value. Note that the matrix parameters are tied to a particular * path segment; subsequent addition of path segments will not affect their position in the URI path. * * @param name the matrix parameter name, may contain URI template parameters. * @param values the matrix parameter value(s), each object will be converted. to a {@code String} using its * {@code toString()} method. Stringified values may contain URI template parameters. If {@code values} is empty or * {@code null} then all current values of the parameter are removed. * @return the updated UriBuilder. * @throws IllegalArgumentException if name is {@code null}. * @see Matrix URIs */ public abstract UriBuilder replaceMatrixParam(String name, Object... values); /** * Set the URI query string. This method will overwrite any existing query parameters. * * @param query the URI query string, may contain URI template parameters. A {@code null} value will remove all query * parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if query cannot be parsed. */ public abstract UriBuilder replaceQuery(String query); /** * Append a query parameter to the existing set of query parameters. If multiple values are supplied the parameter will * be added once per value. * * @param name the query parameter name, may contain URI template parameters. * @param values the query parameter value(s), each object will be converted to a {@code String} using its * {@code toString()} method. Stringified values may contain URI template parameters. * @return the updated UriBuilder. * @throws IllegalArgumentException if name or values is {@code null}. */ public abstract UriBuilder queryParam(String name, Object... values); /** * Replace the existing value(s) of a query parameter. If multiple values are supplied the parameter will be added once * per value. * * @param name the query parameter name, may contain URI template parameters. * @param values the query parameter value(s), each object will be converted to a {@code String} using its * {@code toString()} method. Stringified values may contain URI template parameters. If {@code values} is empty or * {@code null} then all current values of the parameter are removed. * @return the updated UriBuilder. * @throws IllegalArgumentException if name is {@code null}. */ public abstract UriBuilder replaceQueryParam(String name, Object... values); /** * Set the URI fragment. * * @param fragment the URI fragment, may contain URI template parameters. A {@code null} value will remove any existing * fragment. * @return the updated UriBuilder. */ public abstract UriBuilder fragment(String fragment); /** * Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied value. * * In case a {@code null} template name or value is entered a {@link IllegalArgumentException} is thrown. * * @param name name of the URI template. * @param value value to be used to resolve the template. * @return the updated UriBuilder. * @throws IllegalArgumentException if the resolved template name or value is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplate(String name, Object value); /** * Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied value. * * In case a {@code null} template name or value is entered a {@link IllegalArgumentException} is thrown. * * @param name name of the URI template. * @param value value to be used to resolve the template. * @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in template values will be encoded if * the template is placed in the URI path component, otherwise the slash characters will not be encoded in path * templates. * @return the updated UriBuilder. * @throws IllegalArgumentException if the resolved template name or value is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplate(String name, Object value, boolean encodeSlashInPath); /** * Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied encoded value. * * A template with a matching name will be replaced by the supplied value. Value is converted to {@code String} using * its {@code toString()} method and is then encoded to match the rules of the URI component to which they pertain. All * % characters in the stringified values that are not followed by two hexadecimal numbers will be encoded. * * In case a {@code null} template name or encoded value is entered a {@link IllegalArgumentException} is thrown. * * @param name name of the URI template. * @param value encoded value to be used to resolve the template. * @return the updated UriBuilder. * @throws IllegalArgumentException if the resolved template name or encoded value is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplateFromEncoded(String name, Object value); /** * Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs. * * A call to the method with an empty parameter map is ignored. * * @param templateValues a map of URI template names and their values. * @return the updated UriBuilder. * @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplates(Map templateValues); /** * Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs. * * A call to the method with an empty parameter map is ignored. * * @param templateValues a map of URI template names and their values. * @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in template values will be encoded if * the template is placed in the URI path component, otherwise the slash characters will not be encoded in path * templates. * @return the updated UriBuilder. * @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplates(Map templateValues, boolean encodeSlashInPath) throws IllegalArgumentException; /** * Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs. * * All templates with their name matching one of the keys in the supplied map will be replaced by the value in the * supplied map. Values are converted to {@code String} using their {@code toString()} method and are then encoded to * match the rules of the URI component to which they pertain. All % characters in the stringified values that are not * followed by two hexadecimal numbers will be encoded. * * A call to the method with an empty parameter map is ignored. * * @param templateValues a map of URI template names and their values. * @return the updated UriBuilder. * @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}. * @since 2.0 */ public abstract UriBuilder resolveTemplatesFromEncoded(Map templateValues); /** * Build a URI. * * Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String} * using their {@code toString()} method and are then encoded to match the rules of the URI component to which they * pertain. All {@code '%'} characters in the stringified values will be encoded. The state of the builder is * unaffected; this method may be called multiple times on the same builder instance. *

* NOTE: By default all {@code '/'} characters in the stringified values will be encoded in path templates, i.e. the * result is identical to invoking {@link #buildFromMap(java.util.Map, boolean) buildFromMap(valueMap, true)}. To * override this behavior use {@code buildFromMap(valueMap, false)} instead. *

* * @param values a map of URI template parameter names and values. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template * parameter value is {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #buildFromMap(java.util.Map, boolean) * @see #buildFromEncodedMap(java.util.Map) */ public abstract URI buildFromMap(Map values); /** * Build a URI. * * Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String} * using their {@code toString()} method and are then encoded to match the rules of the URI component to which they * pertain. All {@code '%'} characters in the stringified values will be encoded. The state of the builder is * unaffected; this method may be called multiple times on the same builder instance. *

* The {@code encodeSlashInPath} parameter may be used to override the default encoding of {@code '/'} characters in the * stringified template values in cases when the template is part of the URI path component when using the * {@link #buildFromMap(java.util.Map)} method. If the {@code encodeSlashInPath} parameter is set to {@code true} * (default), the slash ({@code '/'}) characters in parameter values will be encoded if the template is placed in the * URI path component. If set to {@code false} the default encoding behavior is overridden an slash characters in * template values will not be encoded when used to substitute path templates. *

* * @param values a map of URI template parameter names and values. * @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in parameter values will be encoded if * the template is placed in the URI path component, otherwise the slash characters will not be encoded in path * templates. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template * parameter value is {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #buildFromMap(java.util.Map) * @see #buildFromEncodedMap(java.util.Map) */ public abstract URI buildFromMap(Map values, boolean encodeSlashInPath) throws IllegalArgumentException, UriBuilderException; /** * Build a URI. * * Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String} * using their {@code toString()} method and are then encoded to match the rules of the URI component to which they * pertain. All % characters in the stringified values that are not followed by two hexadecimal numbers will be encoded. * The state of the builder is unaffected; this method may be called multiple times on the same builder instance. * * @param values a map of URI template parameter names and values. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template * parameter value is {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #buildFromMap(java.util.Map) * @see #buildFromMap(java.util.Map, boolean) * @since 2.0 */ public abstract URI buildFromEncodedMap(Map values) throws IllegalArgumentException, UriBuilderException; /** * Build a URI, using the supplied values in order to replace any URI template parameters. Values are converted to * {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to * which they pertain. All '%' characters in the stringified values will be encoded. The state of the builder is * unaffected; this method may be called multiple times on the same builder instance. *

* All instances of the same template parameter will be replaced by the same value that corresponds to the position of * the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result * in the the URI "x/y/x", not "x/y/z". *

*

* NOTE: By default all {@code '/'} characters in the stringified values will be encoded in path templates, i.e. the * result is identical to invoking {@link #build(Object[], boolean)} build(values, true)}. To override this behavior use * {@code build(values, false)} instead. *

* * @param values a list of URI template parameter values. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is * {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #build(Object[], boolean) * @see #buildFromEncoded(Object...) */ public abstract URI build(Object... values) throws IllegalArgumentException, UriBuilderException; /** * Build a URI, using the supplied values in order to replace any URI template parameters. Values are converted to * {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to * which they pertain. All '%' characters in the stringified values will be encoded. The state of the builder is * unaffected; this method may be called multiple times on the same builder instance. *

* All instances of the same template parameter will be replaced by the same value that corresponds to the position of * the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result * in the the URI "x/y/x", not "x/y/z". *

*

* The {@code encodeSlashInPath} parameter may be used to override the default encoding of {@code '/'} characters in the * stringified template values in cases when the template is part of the URI path component when using the * {@link #build(Object[])} method. If the {@code encodeSlashInPath} parameter is set to {@code true} (default), the * slash ({@code '/'}) characters in parameter values will be encoded if the template is placed in the URI path * component. If set to {@code false} the default encoding behavior is overridden an slash characters in template values * will not be encoded when used to substitute path templates. *

* * @param values a list of URI template parameter values. * @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in parameter values will be encoded if * the template is placed in the URI path component, otherwise the slash characters will not be encoded in path * templates. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is * {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #build(Object[]) * @see #buildFromEncoded(Object...) * @since 2.0 */ public abstract URI build(Object[] values, boolean encodeSlashInPath) throws IllegalArgumentException, UriBuilderException; /** * Build a URI. Any URI templates parameters will be replaced with the supplied values in order. Values are converted to * {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to * which they pertain. All % characters in the stringified values that are not followed by two hexadecimal numbers will * be encoded. The state of the builder is unaffected; this method may be called multiple times on the same builder * instance. *

* All instances of the same template parameter will be replaced by the same value that corresponds to the position of * the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result * in the the URI "x/y/x", not "x/y/z". * * @param values a list of URI template parameter values. * @return the URI built from the UriBuilder. * @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is * {@code null}. * @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder. * @see #build(Object[]) * @see #build(Object[], boolean) */ public abstract URI buildFromEncoded(Object... values) throws IllegalArgumentException, UriBuilderException; /** * Get the URI template string represented by this URI builder. * * @return the URI template string for this URI builder. * @since 2.0 */ public abstract String toTemplate(); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy