/** * Copyright 2005-2014 Restlet * * The contents of this file are subject to the terms of one of the following * open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can * select the license that you prefer but you may not use this file except in * compliance with one of these Licenses. * * You can obtain a copy of the Apache 2.0 license at * http://www.opensource.org/licenses/apache-2.0 * * You can obtain a copy of the EPL 1.0 license at * http://www.opensource.org/licenses/eclipse-1.0 * * See the Licenses for the specific language governing permissions and * limitations under the Licenses. * * Alternatively, you can obtain a royalty free commercial license with less * limitations, transferable or non-transferable, directly at * http://restlet.com/products/restlet-framework * * Restlet is a registered trademark of Restlet S.A.S. */ package org.restlet.ext.jaxrs; import java.lang.reflect.Method; import java.net.URI; import java.util.Map; import java.util.StringTokenizer; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilderException; import org.restlet.Application; import org.restlet.data.Language; import org.restlet.data.MediaType; import org.restlet.data.Metadata; import org.restlet.ext.jaxrs.internal.util.Util; import org.restlet.service.MetadataService; /** * This {@link UriBuilder} extension provides special help for "file" * extensions. They will not be removed, if path will be changed (e.g. replaced, * removed or matrix parameters added). For further information see * {@link #extension(String)}, {@link #extensionLanguage(String)} and * {@link #extensionMedia(String)}. You could get an instance with an * {@link ExtendedUriInfo}. * * @author Stephan Koops */ public class ExtendedUriBuilder extends AbstractUriBuilder { /** * 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 ExtendedUriBuilder fromPath(String path) throws IllegalArgumentException { ExtendedUriBuilder b = newInstance(); b.replacePath(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 ExtendedUriBuilder fromResource(Class<?> resource) throws IllegalArgumentException { ExtendedUriBuilder b = newInstance(); b.path(resource); 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 ExtendedUriBuilder 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 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 ExtendedUriBuilder fromUri(URI uri) throws IllegalArgumentException { ExtendedUriBuilder b = newInstance(); b.uri(uri); return b; } /** * Creates a new instance of UriBuilder. * * @return a new instance of UriBuilder */ public static ExtendedUriBuilder newInstance() { return new ExtendedUriBuilder(); } /** The extension for the language */ private String extensionLanguage; /** The extension for the media type */ private String extensionMedia; /** * Other extensions as language and media type * * @see #extensionLanguage * @see #extensionMedia */ private String extensionOthers; /** {@inheritDoc} */ @Override public URI build(Object... values) throws IllegalArgumentException, UriBuilderException { return super.build(values); } /** {@inheritDoc} */ @Override public URI buildFromEncoded(Object... values) throws IllegalArgumentException, UriBuilderException { return super.buildFromEncoded(values); } /** {@inheritDoc} */ @Override public URI buildFromEncodedMap(Map<String, ? extends Object> values) throws IllegalArgumentException, UriBuilderException { return super.buildFromEncodedMap(values); } /** * @see javax.ws.rs.core.UriBuilder#buildFromMap(java.util.Map) */ @Override public URI buildFromMap(Map<String, ? extends Object> values) throws IllegalArgumentException, UriBuilderException { return super.buildFromMap(values); } /** {@inheritDoc} */ @Override public ExtendedUriBuilder clone() { ExtendedUriBuilder clone = new ExtendedUriBuilder(); super.copyInto(clone); clone.extension(this.getExtension()); return clone; } /** * Set the extension that will be appended to the final path segment at * build time. An initial "." will be appended if necessary. If the final * path segment already contains an extension, it will be retained and the * supplied extension will be used as a new extension. * * <p> * Note that the extension will be appended to the path component, matrix * and query parameters will follow any appended extension. * </p> * * @param extensions * the extensions to append at build time, a null value will * result in no extension being appended. * @return the updated UriBuilder */ public ExtendedUriBuilder extension(String extensions) { if (extensions == null) { this.extensionLanguage = null; this.extensionMedia = null; this.extensionOthers = null; return this; } MetadataService metadataService; metadataService = Application.getCurrent().getMetadataService(); StringTokenizer stt = new StringTokenizer(extensions, "."); while (stt.hasMoreTokens()) { String extension = stt.nextToken(); Metadata metadata = metadataService.getMetadata(extension); if (metadata instanceof Language) { this.extensionLanguage = extension; } else if (metadata instanceof MediaType) { this.extensionMedia = extension; } else { if (extensionOthers == null) this.extensionOthers = extension; else this.extensionOthers += "." + extension; } } return this; } /** * Appends an extension for the language ("de", "en", "fr" or whatever). * <code>null</code> resets the language extension. * * @param language * @return this {@link ExtendedUriBuilder} */ public ExtendedUriBuilder extensionLanguage(String language) { if (Util.startsWith(language, '.')) { this.extensionLanguage = language.substring(1); } else { this.extensionLanguage = language; } return this; } /** * Appends an extension for the media type ("html", "pdf", "gif" or * whatever). <code>null</code> resets the media type extension. * * @param mediaExtension * @return this ExtendedUriBuilder */ public ExtendedUriBuilder extensionMedia(String mediaExtension) { if (Util.startsWith(mediaExtension, '.')) { this.extensionMedia = mediaExtension.substring(1); } else { this.extensionMedia = mediaExtension; } return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder fragment(String fragment) { super.fragment(fragment); return this; } /** * Returns the extension of the current uri, if available. * * @return the extension for content negotiation, including a "." at the * start, or <code>null</code> if no extension is available. Never * returns "" or ".". */ @Override public String getExtension() { StringBuilder stb = new StringBuilder(); if (extensionOthers != null) { stb.append('.'); stb.append(extensionOthers); } if (extensionLanguage != null) { stb.append('.'); stb.append(extensionLanguage); } if (extensionMedia != null) { stb.append('.'); stb.append(extensionMedia); } if (stb.length() == 0) return null; return stb.toString(); } /** {@inheritDoc} */ @Override public ExtendedUriBuilder host(String host) throws IllegalArgumentException { super.host(host); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException { super.matrixParam(name, values); return this; } /** {@inheritDoc} */ @Override @SuppressWarnings("rawtypes") public ExtendedUriBuilder path(Class resource) throws IllegalArgumentException { super.path(resource); return this; } /** {@inheritDoc} */ @Override @SuppressWarnings("rawtypes") public ExtendedUriBuilder path(Class resource, String methodName) throws IllegalArgumentException { path(resource); super.path(resource, methodName); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder path(Method method) throws IllegalArgumentException { super.path(method); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder path(String pathToAppend) throws IllegalArgumentException { super.path(pathToAppend); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder port(int port) throws IllegalArgumentException { super.port(port); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder port(String port) throws IllegalArgumentException { super.port(port); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder queryParam(String name, Object... values) throws IllegalArgumentException { super.queryParam(name, values); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder replaceMatrix(String matrix) throws IllegalArgumentException { super.replaceMatrix(matrix); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder replaceMatrixParam(String name, Object... values) throws IllegalArgumentException { super.replaceMatrixParam(name, values); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder replacePath(String newPath) { if (newPath == null) { super.replacePath(newPath); this.extension(null); return this; } int beginLastSegment = newPath.lastIndexOf('/'); int beginLastMatrix = newPath.indexOf(';', beginLastSegment); int endExt = beginLastMatrix > 0 ? beginLastMatrix : newPath.length(); int beginExtensions = Util.indexOfBetween(newPath, '.', beginLastSegment, endExt); if (beginExtensions < 0) { super.replacePath(newPath); return this; } String extensions = newPath.substring(beginExtensions, endExt); StringBuilder pathStb = new StringBuilder(); pathStb.append(newPath, 0, beginExtensions); pathStb.append(newPath, endExt, newPath.length()); this.extension(extensions); super.replacePath(pathStb); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder replaceQuery(String query) throws IllegalArgumentException { super.replaceQuery(query); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder replaceQueryParam(String name, Object... values) throws IllegalArgumentException { super.replaceQueryParam(name, values); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder scheme(String scheme) throws IllegalArgumentException { super.scheme(scheme); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException { super.schemeSpecificPart(ssp); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder segment(String... segments) throws IllegalArgumentException { super.segment(segments); return this; } /** {@inheritDoc} */ @Override public String toString() { return super.toString(); } /** {@inheritDoc} */ @Override public ExtendedUriBuilder uri(URI uri) throws IllegalArgumentException { super.uri(uri); return this; } /** {@inheritDoc} */ @Override public ExtendedUriBuilder userInfo(String ui) { super.userInfo(ui); return this; } }