/** * 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.internal.core; import java.net.URI; import java.util.List; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; import org.restlet.ext.jaxrs.ExtendedUriInfo; /** * A ThreadLocalizedUriInfo is used to inject, if a {@link UriInfo} is required * to inject. It must be new instantiated for every place to inject. * * @author Stephan Koops * @see UriInfo * @see ThreadLocalizedContext */ public class ThreadLocalizedUriInfo implements UriInfo { private final ThreadLocal<MatchedInfo> matchedInfos = new ThreadLocal<MatchedInfo>(); private final ThreadLocalizedContext tlContext; /** * Creates a new ThreadLocalizedUriInfo * * @param tlContext */ public ThreadLocalizedUriInfo(ThreadLocalizedContext tlContext) { this.tlContext = tlContext; } /** * @return the MatchedInfo with the current data from the * {@link CallContext}. * @throws IllegalStateException * if no CallContext could be loaded. */ private MatchedInfo createAncestorInfo() throws IllegalStateException { final CallContext callContext = getCallContext(); return new MatchedInfo(callContext.getMatchedURIs(), callContext.getMatchedResources()); } private MatchedInfo get() throws IllegalStateException { MatchedInfo matchedInfo = this.matchedInfos.get(); if (matchedInfo != null) { return matchedInfo; } matchedInfo = createAncestorInfo(); this.matchedInfos.set(matchedInfo); return matchedInfo; } /** * @see JaxRsUriInfo#getAbsolutePath() * @see UriInfo#getAbsolutePath() */ public URI getAbsolutePath() { return getCallContext().getAbsolutePath(); } /** * @see JaxRsUriInfo#getAbsolutePathBuilder() * @see UriInfo#getAbsolutePathBuilder() * @see ExtendedUriInfo#getAbsolutePathBuilder() */ public UriBuilder getAbsolutePathBuilder() { return getCallContext().getAbsolutePathBuilder(); } /** * @see JaxRsUriInfo#getBaseUri() * @see UriInfo#getBaseUri() */ public URI getBaseUri() { return getCallContext().getBaseUri(); } /** * @see JaxRsUriInfo#getBaseUriBuilder() * @see UriInfo#getBaseUriBuilder() */ public UriBuilder getBaseUriBuilder() { return getCallContext().getBaseUriBuilder(); } protected CallContext getCallContext() throws IllegalStateException { return this.tlContext.get(); } /** * @see JaxRsUriInfo#getMatchedResources() * @see UriInfo#getMatchedResources() */ public List<Object> getMatchedResources() { return get().getResources(); } /** * @see UriInfo#getMatchedURIs() */ public List<String> getMatchedURIs() { return get().getUris(true); } /** * @see JaxRsUriInfo#getAncestorResourceURIs(boolean) * @see UriInfo#getAncestorResourceURIs(boolean) */ public List<String> getMatchedURIs(boolean decode) { return get().getUris(decode); } /** * @see JaxRsUriInfo#getPath() * @see UriInfo#getPath() */ public String getPath() { return getCallContext().getPath(); } /** * @see JaxRsUriInfo#getPath(boolean) * @see UriInfo#getPath(boolean) */ public String getPath(boolean decode) { return getCallContext().getPath(decode); } /** * @see JaxRsUriInfo#getPathParameters() * @see UriInfo#getPathParameters() */ public MultivaluedMap<String, String> getPathParameters() { return getCallContext().getPathParameters(); } /** * @see JaxRsUriInfo#getPathParameters(boolean) * @see UriInfo#getPathParameters(boolean) */ public MultivaluedMap<String, String> getPathParameters(boolean decode) { return getCallContext().getPathParameters(decode); } /** * @see JaxRsUriInfo#getPathSegments() * @see UriInfo#getPathSegments() */ public List<PathSegment> getPathSegments() { return getCallContext().getPathSegments(); } /** * @see JaxRsUriInfo#getPathSegments(boolean) * @see UriInfo#getPathSegments(boolean) */ public List<PathSegment> getPathSegments(boolean decode) { return getCallContext().getPathSegments(decode); } /** * @see JaxRsUriInfo#getQueryParameters() * @see UriInfo#getQueryParameters() */ public MultivaluedMap<String, String> getQueryParameters() { return getCallContext().getQueryParameters(); } /** * @see JaxRsUriInfo#getQueryParameters(boolean) * @see UriInfo#getQueryParameters(boolean) */ public MultivaluedMap<String, String> getQueryParameters(boolean decode) { return getCallContext().getQueryParameters(decode, true); } /** * @see JaxRsUriInfo#getQueryParameters(boolean) * @see UriInfo#getQueryParameters(boolean) */ public MultivaluedMap<String, String> getQueryParameters(boolean decode, boolean caseSensitive) { return getCallContext().getQueryParameters(decode, caseSensitive); } /** * @see JaxRsUriInfo#getRequestUri() * @see UriInfo#getRequestUri() */ public URI getRequestUri() { return getCallContext().getRequestUri(); } /** * @see JaxRsUriInfo#getRequestUriBuilder() * @see UriInfo#getRequestUriBuilder() */ public UriBuilder getRequestUriBuilder() { return getCallContext().getRequestUriBuilder(); } /** * Removes the MatchedInfo for the current thread. */ public void reset() { this.matchedInfos.remove(); } /** * Saves the current state of the ancestorResource(URI)s for the current * thread. * * @param saveState * if true, the current state is save for the current thread from * the current {@link CallContext}; if false (for singeltons), * the saved object for the current thread is removed. */ public void saveStateForCurrentThread(boolean saveState) { if (saveState) { this.matchedInfos.set(createAncestorInfo()); } else { reset(); } } }