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