users@jersey.java.net

Re: [Jersey] Thread access to _at_Context objects?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 04 Nov 2009 10:31:21 +0100

On Nov 4, 2009, at 5:09 AM, Chris Hubick wrote:

> On Mon, 2009-11-02 at 11:08 +0100, Paul Sandoz wrote:
>> If you want we can work on providing thread-safe adapters for non-
>> thread-local proxy instances.
>
> FYI, I came up with the attached, in case anyone else has a similar
> need.

Thanks. I logged a feature, pointing to your email.

Paul.

>
> --
> Chris Hubick
> mailto:chris_at_hubick.com
> http://www.hubick.com/chris/
> import java.net.*;
> import java.security.*;
> import java.util.*;
> import java.util.concurrent.*;
>
> import javax.ws.rs.core.*;
>
>
> /**
> * JAX-RS Utilities.
> */
> public abstract class RESTUtil {
>
> public static class ConcurrentMultivaluedMapWrapper<K,V> extends
> AbstractMap<K,List<V>> implements MultivaluedMap<K,V> {
> protected final Map<K,List<V>> multivaluedMap;
>
> public ConcurrentMultivaluedMapWrapper(final MultivaluedMap<K,V>
> multivaluedMap) throws IllegalArgumentException {
> if (multivaluedMap == null) throw new
> IllegalArgumentException("null multivaluedMap");
> this.multivaluedMap = Collections.unmodifiableMap(new
> ConcurrentHashMap<K,List<V>>(multivaluedMap));
> return;
> }
>
> @Override
> public Set<Map.Entry<K,List<V>>> entrySet() {
> final Set<Map.Entry<K,List<V>>> entrySet =
> multivaluedMap.entrySet();
> if (entrySet == null) return null;
> final List<Map.Entry<K,List<V>>> concurrentEntries = new
> ArrayList<Map.Entry<K,List<V>>>(entrySet.size());
> for (Map.Entry<K,List<V>> entry : entrySet) {
> concurrentEntries.add(new
> AbstractMap.SimpleEntry<K,List<V>>(entry.getKey(),
> (entry.getValue() != null) ? Collections.unmodifiableList(new
> CopyOnWriteArrayList<V>(entry.getValue())) : null));
> }
> return Collections.unmodifiableSet(new
> CopyOnWriteArraySet<Map.Entry<K,List<V>>>(concurrentEntries));
> }
>
> @Override
> public void clear() {
> throw new UnsupportedOperationException();
> }
>
> @Override
> public boolean containsKey(final Object key) {
> return multivaluedMap.containsKey(key);
> }
>
> @Override
> public boolean containsValue(final Object value) {
> return multivaluedMap.containsValue(value);
> }
>
> @Override
> public List<V> get(final Object key) {
> final List<V> value = multivaluedMap.get(key);
> return (value != null) ? Collections.unmodifiableList(new
> CopyOnWriteArrayList<V>(value)) : null;
> }
>
> @Override
> public boolean isEmpty() {
> return multivaluedMap.isEmpty();
> }
>
> @Override
> public Set<K> keySet() {
> final Set<K> keySet = multivaluedMap.keySet();
> return (keySet != null) ? Collections.unmodifiableSet(new
> CopyOnWriteArraySet<K>(keySet)) : null;
> }
>
> @Override
> public List<V> remove(final Object key) {
> throw new UnsupportedOperationException();
> }
>
> @Override
> public int size() {
> return multivaluedMap.size();
> }
>
> @Override
> public void add(final K key, final V value) {
> throw new UnsupportedOperationException();
> }
>
> @Override
> public V getFirst(final K key) {
> final List<V> values = multivaluedMap.get(key);
> return ((values != null) && (!values.isEmpty())) ?
> values.get(0) : null;
> }
>
> @Override
> public void putSingle(final K key, final V value) {
> throw new UnsupportedOperationException();
> }
>
> @Override
> public List<V> put(final K key, final List<V> value) {
> throw new UnsupportedOperationException();
> }
>
> @Override
> public void putAll(final Map<? extends K,? extends List<V>> m) {
> throw new UnsupportedOperationException();
> }
>
> } // ConcurrentMultivaluedMapWrapper
>
> public static class ConcurrentRequestWrapper implements Request {
> protected final Request request;
>
> public ConcurrentRequestWrapper(final Request request) throws
> IllegalArgumentException {
> if (request == null) throw new IllegalArgumentException("null
> request");
> this.request = request;
> return;
> }
>
> @Override
> public Response.ResponseBuilder evaluatePreconditions() {
> synchronized (request) {
> return request.evaluatePreconditions();
> }
> }
>
> @Override
> public Response.ResponseBuilder evaluatePreconditions(final
> EntityTag eTag) {
> synchronized (request) {
> return request.evaluatePreconditions(eTag);
> }
> }
>
> @Override
> public Response.ResponseBuilder evaluatePreconditions(final Date
> lastModified) {
> synchronized (request) {
> return request.evaluatePreconditions(lastModified);
> }
> }
>
> @Override
> public Response.ResponseBuilder evaluatePreconditions(final Date
> lastModified, final EntityTag eTag) {
> synchronized (request) {
> return request.evaluatePreconditions(lastModified, eTag);
> }
> }
>
> @Override
> public String getMethod() {
> synchronized (request) {
> return request.getMethod();
> }
> }
>
> @Override
> public Variant selectVariant(final List<Variant> variants) throws
> IllegalArgumentException {
> synchronized (request) {
> return request.selectVariant(variants);
> }
> }
>
> } // ConcurrentRequestWrapper
>
> public static class ConcurrentUriInfoWrapper implements UriInfo {
> protected final UriInfo uriInfo;
>
> public ConcurrentUriInfoWrapper(final UriInfo uriInfo) throws
> IllegalArgumentException {
> if (uriInfo == null) throw new IllegalArgumentException("null
> uriInfo");
> this.uriInfo = uriInfo;
> return;
> }
>
> @Override
> public URI getAbsolutePath() {
> synchronized (uriInfo) {
> return uriInfo.getAbsolutePath();
> }
> }
>
> @Override
> public UriBuilder getAbsolutePathBuilder() {
> synchronized (uriInfo) {
> return uriInfo.getAbsolutePathBuilder();
> }
> }
>
> @Override
> public URI getBaseUri() {
> synchronized (uriInfo) {
> return uriInfo.getBaseUri();
> }
> }
>
> @Override
> public UriBuilder getBaseUriBuilder() {
> synchronized (uriInfo) {
> return uriInfo.getBaseUriBuilder();
> }
> }
>
> @Override
> public List<Object> getMatchedResources() {
> synchronized (uriInfo) {
> final List<Object> matchedResources =
> uriInfo.getMatchedResources();
> return (matchedResources != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<Object>(matchedResources)) : null;
> }
> }
>
> @Override
> public List<String> getMatchedURIs() {
> synchronized (uriInfo) {
> final List<String> matchedURIs = uriInfo.getMatchedURIs();
> return (matchedURIs != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<String>(matchedURIs)) : null;
> }
> }
>
> @Override
> public List<String> getMatchedURIs(boolean decode) {
> synchronized (uriInfo) {
> final List<String> matchedURIs =
> uriInfo.getMatchedURIs(decode);
> return (matchedURIs != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<String>(matchedURIs)) : null;
> }
> }
>
> @Override
> public String getPath() {
> synchronized (uriInfo) {
> return uriInfo.getPath();
> }
> }
>
> @Override
> public String getPath(boolean decode) {
> synchronized (uriInfo) {
> return uriInfo.getPath(decode);
> }
> }
>
> @Override
> public MultivaluedMap<String,String> getPathParameters() {
> synchronized (uriInfo) {
> final MultivaluedMap<String,String> pathParameters =
> uriInfo.getPathParameters();
> return (pathParameters != null) ? new
> ConcurrentMultivaluedMapWrapper<String,String>(pathParameters) : null;
> }
> }
>
> @Override
> public MultivaluedMap<String,String> getPathParameters(boolean
> decode) {
> synchronized (uriInfo) {
> final MultivaluedMap<String,String> pathParameters =
> uriInfo.getPathParameters(decode);
> return (pathParameters != null) ? new
> ConcurrentMultivaluedMapWrapper<String,String>(pathParameters) : null;
> }
> }
>
> @Override
> public List<PathSegment> getPathSegments() {
> synchronized (uriInfo) {
> final List<PathSegment> pathSegments =
> uriInfo.getPathSegments();
> return (pathSegments != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<PathSegment>(pathSegments)) : null;
> }
> }
>
> @Override
> public List<PathSegment> getPathSegments(boolean decode) {
> synchronized (uriInfo) {
> final List<PathSegment> pathSegments =
> uriInfo.getPathSegments(decode);
> return (pathSegments != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<PathSegment>(pathSegments)) : null;
> }
> }
>
> @Override
> public MultivaluedMap<String,String> getQueryParameters() {
> synchronized (uriInfo) {
> final MultivaluedMap<String,String> queryParameters =
> uriInfo.getQueryParameters();
> return (queryParameters != null) ? new
> ConcurrentMultivaluedMapWrapper<String,String>(queryParameters) :
> null;
> }
> }
>
> @Override
> public MultivaluedMap<String,String> getQueryParameters(boolean
> decode) {
> synchronized (uriInfo) {
> final MultivaluedMap<String,String> queryParameters =
> uriInfo.getQueryParameters(decode);
> return (queryParameters != null) ? new
> ConcurrentMultivaluedMapWrapper<String,String>(queryParameters) :
> null;
> }
> }
>
> @Override
> public URI getRequestUri() {
> synchronized (uriInfo) {
> return uriInfo.getRequestUri();
> }
> }
>
> @Override
> public UriBuilder getRequestUriBuilder() {
> synchronized (uriInfo) {
> return uriInfo.getRequestUriBuilder();
> }
> }
>
> } // ConcurrentUriInfoWrapper
>
> public static class ConcurrentSecurityContextWrapper implements
> SecurityContext {
> protected final SecurityContext securityContext;
>
> public ConcurrentSecurityContextWrapper(final SecurityContext
> securityContext) throws IllegalArgumentException {
> if (securityContext == null) throw new
> IllegalArgumentException("null securityContext");
> this.securityContext = securityContext;
> return;
> }
>
> @Override
> public String getAuthenticationScheme() {
> synchronized (securityContext) {
> return securityContext.getAuthenticationScheme();
> }
> }
>
> @Override
> public Principal getUserPrincipal() {
> synchronized (securityContext) {
> return securityContext.getUserPrincipal();
> }
> }
>
> @Override
> public boolean isSecure() {
> synchronized (securityContext) {
> return securityContext.isSecure();
> }
> }
>
> @Override
> public boolean isUserInRole(final String role) {
> synchronized (securityContext) {
> return securityContext.isUserInRole(role);
> }
> }
>
> } // ConcurrentSecurityContextWrapper
>
> public static class ConcurrentHttpHeadersWrapper implements
> HttpHeaders {
> protected final HttpHeaders httpHeaders;
>
> public ConcurrentHttpHeadersWrapper(final HttpHeaders
> httpHeaders) throws IllegalArgumentException {
> if (httpHeaders == null) throw new
> IllegalArgumentException("null httpHeaders");
> this.httpHeaders = httpHeaders;
> return;
> }
>
> @Override
> public List<Locale> getAcceptableLanguages() {
> synchronized (httpHeaders) {
> final List<Locale> acceptableLanguages =
> httpHeaders.getAcceptableLanguages();
> return (acceptableLanguages != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<Locale>(acceptableLanguages)) : null;
> }
> }
>
> @Override
> public List<MediaType> getAcceptableMediaTypes() {
> synchronized (httpHeaders) {
> final List<MediaType> acceptableMediaTypes =
> httpHeaders.getAcceptableMediaTypes();
> return (acceptableMediaTypes != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<MediaType>(acceptableMediaTypes)) : null;
> }
> }
>
> @Override
> public Map<String,Cookie> getCookies() {
> synchronized (httpHeaders) {
> final Map<String,Cookie> cookies = httpHeaders.getCookies();
> return (cookies != null) ? Collections.unmodifiableMap(new
> ConcurrentHashMap<String,Cookie>(cookies)) : null;
> }
> }
>
> @Override
> public Locale getLanguage() {
> synchronized (httpHeaders) {
> return httpHeaders.getLanguage();
> }
> }
>
> @Override
> public MediaType getMediaType() {
> synchronized (httpHeaders) {
> return httpHeaders.getMediaType();
> }
> }
>
> @Override
> public List<String> getRequestHeader(final String name) {
> synchronized (httpHeaders) {
> final List<String> requestHeader =
> httpHeaders.getRequestHeader(name);
> return (requestHeader != null) ?
> Collections.unmodifiableList(new
> CopyOnWriteArrayList<String>(requestHeader)) : null;
> }
> }
>
> @Override
> public MultivaluedMap<String,String> getRequestHeaders() {
> synchronized (httpHeaders) {
> final MultivaluedMap<String,String> requestHeaders =
> httpHeaders.getRequestHeaders();
> return (requestHeaders != null) ? new
> ConcurrentMultivaluedMapWrapper<String,String>(requestHeaders) : null;
> }
> }
>
> } // ConcurrentHttpHeadersWrapper
>
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net