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 }