1 package com.atlassian.plugins.rest.module.util; 2 3 import com.atlassian.plugins.rest.common.util.RestUrlBuilder; 4 import org.springframework.util.Assert; 5 6 import javax.ws.rs.core.Response; 7 import javax.ws.rs.ext.RuntimeDelegate; 8 import java.net.URI; 9 10 /** 11 * @since 2.2 12 */ 13 public class RestUrlBuilderImpl implements RestUrlBuilder 14 { 15 public RestUrlBuilderImpl() 16 { 17 /** 18 * IMPLEMENTATION NOTE: 19 * 20 * <p> 21 * We're forcing jsr311 to initialize itself now that the context 22 * classloader is still set to the rest bundle (which has access to 23 * {@link com.sun.ws.rs.ext.RuntimeDelegateImpl}. 24 * </p> 25 * <p> 26 * If we wait for it to lazily initialize itself, we can (and in fact, 27 * we did) run into trouble when 28 * {@link #getUrlFor(java.net.URI, Class)} is called by a different 29 * plugin. In that scenario, by the time the caller then invokes a 30 * method on the returned cglib-generated proxy instance which 31 * triggers initialization of the jsr311 library, we get a 32 * {@link ClassNotFoundException} because 33 * {@link javax.ws.rs.ext.FactoryFinder#newInstance(String, ClassLoader)} 34 * relies on the context classloader to have access to 35 * {@link com.sun.ws.rs.ext.RuntimeDelegateImpl}, which it doesn't 36 * because that invocation is performed inside the calling plugin. 37 * </p> 38 * <p> 39 * It seems likely the above problem only applies to jsr311-1.0 (the 40 * one atlassian.jersey-library ships with) and is fixed in 1.1.1, so 41 * once we upgrade jersey, we should be able to get rid of this hack. 42 */ 43 RuntimeDelegate.getInstance(); 44 } 45 46 public URI getURI(Response resource) 47 { 48 if (resource instanceof GeneratedURIResponse) 49 { 50 return ((GeneratedURIResponse) resource).getURI(); 51 } 52 else 53 { 54 throw new IllegalArgumentException("Supplied response is not a generated one"); 55 } 56 } 57 58 public <T> T getUrlFor(URI baseUri, Class<T> resourceClass) 59 { 60 Assert.notNull(resourceClass, "resourceClass cannot be null"); 61 Assert.notNull(baseUri, "baseUri cannot be null"); 62 return ProxyUtils.create(resourceClass, new ResourcePathUrlInvokable(resourceClass, baseUri)); 63 } 64 }