blob: 296a1200ad5e9b9f2ebfc7d959a56389c6e86b42 [file] [log] [blame]
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* UriBuilder.java
*
* Created on July 18, 2007, 11:53 AM
*
*/
package javax.ws.rs.core;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Map;
import javax.ws.rs.ext.RuntimeDelegate;
/**
* URI template aware utility class for building URIs from their components. See
* {@link javax.ws.rs.Path#value} for an explanation of URI templates.
*
* <p>Builder methods perform contextual encoding of characters not permitted in
* the corresponding URI component following the rules of the
* <a href="http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1">application/x-www-form-urlencoded</a>
* media type for query parameters and
* <a href="http://ietf.org/rfc/rfc3986.txt">RFC 3986</a> 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.</p>
*
* <p>URI templates are allowed in most components of a URI but their value is
* restricted to a particular component. E.g.
* <blockquote><code>UriBuilder.fromPath("{arg1}").build("foo#bar");</code></blockquote>
* would result in encoding of the '#' such that the resulting URI is
* "foo%23bar". To create a URI "foo#bar" use
* <blockquote><code>UriBuilder.fromPath("{arg1}").fragment("{arg2}").build("foo", "bar")</code></blockquote>
* 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.
*
* @see java.net.URI
* @see javax.ws.rs.Path
*/
public abstract class UriBuilder {
/**
* Protected constructor, use one of the static <code>from<i>XXX</i></code>
* methods to obtain an instance.
*/
protected UriBuilder() {}
/**
* Creates a new instance of UriBuilder.
* @return a new instance of UriBuilder
*/
protected static UriBuilder newInstance() {
UriBuilder b = RuntimeDelegate.getInstance().createUriBuilder();
return b;
}
/**
* 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 null
*/
public static UriBuilder fromUri(URI uri) throws IllegalArgumentException {
UriBuilder b = newInstance();
b.uri(uri);
return b;
}
/**
* Create a new instance initialized from an existing URI.
* @param uri a URI that will be used to initialize the UriBuilder, may not
* contain URI parameters.
* @return a new UriBuilder
* @throws IllegalArgumentException if uri is not a valid URI or is null
*/
public static UriBuilder fromUri(String uri) throws IllegalArgumentException {
URI u;
try {
u = URI.create(uri);
} catch (NullPointerException ex) {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
return fromUri(u);
}
/**
* 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 null
*/
public static UriBuilder fromPath(String path) throws IllegalArgumentException {
UriBuilder b = newInstance();
b.path(path);
return b;
}
/**
* Create a new instance representing a relative URI initialized from a
* root resource class.
*
* @param resource a root resource whose {@link javax.ws.rs.Path} value will
* be used to initialize the UriBuilder.
* @return a new UriBuilder
* @throws IllegalArgumentException if resource is not annotated with
* {@link javax.ws.rs.Path} or resource is null.
*/
public static UriBuilder fromResource(Class<?> resource) throws IllegalArgumentException {
UriBuilder b = newInstance();
b.path(resource);
return b;
}
/**
* 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} method.
* @return a copy of the UriBuilder
*/
@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 uri is null
*/
public abstract UriBuilder uri(URI uri) throws IllegalArgumentException;
/**
* Set the URI scheme.
* @param scheme the URI scheme, may contain URI template parameters.
* A null value will unset the URI scheme.
* @return the updated UriBuilder
* @throws IllegalArgumentException if scheme is invalid
*/
public abstract UriBuilder scheme(String scheme) throws IllegalArgumentException;
/**
* 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 null
*/
public abstract UriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException;
/**
* Set the URI user-info.
* @param ui the URI user-info, may contain URI template parameters.
* A null value will unset userInfo component of the URI.
* @return the updated UriBuilder
*/
public abstract UriBuilder userInfo(String ui);
/**
* Set the URI host.
* @return the updated UriBuilder
* @param host the URI host, may contain URI template parameters.
* A null value will unset the host component of the URI.
* @throws IllegalArgumentException if host is invalid.
*/
public abstract UriBuilder host(String host) throws IllegalArgumentException;
/**
* 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) throws IllegalArgumentException;
/**
* 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 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 null
*/
public abstract UriBuilder path(String path) throws IllegalArgumentException;
/**
* 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 javax.ws.rs.Path} value will be
* used to obtain the path to append.
* @return the updated UriBuilder
* @throws IllegalArgumentException if resource is null, or
* if resource is not annotated with {@link javax.ws.rs.Path}
*/
public abstract UriBuilder path(Class resource) throws IllegalArgumentException;
/**
* 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)</code>, it
* can only be used in cases where there is a single method with the
* specified name that is annotated with {@link javax.ws.rs.Path}.
*
* @param resource the resource containing the method
* @param method the name of the method whose {@link javax.ws.rs.Path} value will be
* used to obtain the path to append
* @return the updated UriBuilder
* @throws IllegalArgumentException if resource or method is null,
* or there is more than or less than one variant of the method annotated with
* {@link javax.ws.rs.Path}
*/
public abstract UriBuilder path(Class resource, String method) throws IllegalArgumentException;
/**
* Append the path from a {@link javax.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 javax.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 null or is
* not annotated with a {@link javax.ws.rs.Path}
*/
public abstract UriBuilder path(Method method) throws IllegalArgumentException;
/**
* 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 null
*/
public abstract UriBuilder segment(String... segments) throws IllegalArgumentException;
/**
* 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 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 <a href="http://www.w3.org/DesignIssues/MatrixURIs.html">Matrix URIs</a>
*/
public abstract UriBuilder replaceMatrix(String matrix) throws IllegalArgumentException;
/**
* 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 null
* @see <a href="http://www.w3.org/DesignIssues/MatrixURIs.html">Matrix URIs</a>
*/
public abstract UriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException;
/**
* 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 null then all current values of the parameter are removed.
* @return the updated UriBuilder
* @throws IllegalArgumentException if name is null.
* @see <a href="http://www.w3.org/DesignIssues/MatrixURIs.html">Matrix URIs</a>
*/
public abstract UriBuilder replaceMatrixParam(String name, Object... values) throws IllegalArgumentException;
/**
* 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 null value will remove all query parameters.
* @return the updated UriBuilder
* @throws IllegalArgumentException if query cannot be parsed
*/
public abstract UriBuilder replaceQuery(String query) throws IllegalArgumentException;
/**
* 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 null
*/
public abstract UriBuilder queryParam(String name, Object... values) throws IllegalArgumentException;
/**
* 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 null then all current values of the parameter are removed.
* @return the updated UriBuilder
* @throws IllegalArgumentException if name is null
*/
public abstract UriBuilder replaceQueryParam(String name, Object... values) throws IllegalArgumentException;
/**
* Set the URI fragment.
* @param fragment the URI fragment, may contain URI template parameters.
* A null value will remove any existing fragment.
* @return the updated UriBuilder
*/
public abstract UriBuilder fragment(String fragment);
/**
* Build a URI, any URI template parameters will be replaced by the value in
* the supplied map. Values are converted to <code>String</code> using
* their <code>toString</code> 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.
* @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 null.
* @throws UriBuilderException if a URI cannot be constructed based on the
* current state of the builder.
*/
public abstract URI buildFromMap(Map<String, ? extends Object> values)
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</code> using
* their <code>toString</code> 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 null.
* @throws UriBuilderException if a URI cannot be constructed based on the
* current state of the builder.
*/
public abstract URI buildFromEncodedMap(Map<String, ? extends 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</code> using
* their <code>toString</code> 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.
* <p>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", <i>not</i>
* "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 null.
* @throws UriBuilderException if a URI cannot be constructed based on the
* current state of the builder.
*/
public abstract URI build(Object... values)
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</code> using
* their <code>toString</code> 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.
* <p>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", <i>not</i>
* "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 null.
* @throws UriBuilderException if a URI cannot be constructed based on the
* current state of the builder.
*/
public abstract URI buildFromEncoded(Object... values)
throws IllegalArgumentException, UriBuilderException;
}