1 package com.atlassian.plugins.rest.module.jersey;
2
3 import com.atlassian.plugin.Plugin;
4 import com.atlassian.plugin.module.ContainerManagedPlugin;
5 import com.atlassian.plugins.rest.module.ChainingClassLoader;
6 import com.atlassian.plugins.rest.module.ContextClassLoaderSwitchingProxy;
7 import com.atlassian.sal.api.net.NonMarshallingRequestFactory;
8 import com.atlassian.sal.api.net.Request;
9 import com.atlassian.sal.api.net.RequestFactory;
10 import org.osgi.framework.Bundle;
11
12 import java.lang.reflect.Proxy;
13
14 public class JerseyRequestFactory implements RequestFactory {
15 private final RequestFactory<? extends Request> delegateRequestFactory;
16 private final Plugin plugin;
17 private final Bundle bundle;
18
19 private volatile JerseyEntityHandler jerseyEntityHandler;
20
21 public JerseyRequestFactory(final NonMarshallingRequestFactory<? extends Request> delegateRequestFactory,
22 final Plugin plugin,
23 final Bundle bundle) {
24 this.plugin = plugin;
25 this.delegateRequestFactory = delegateRequestFactory;
26 this.bundle = bundle;
27 }
28
29 public Request createRequest(final Request.MethodType methodType, final String s) {
30 ensureInitalised();
31 final Request delegateRequest = delegateRequestFactory.createRequest(methodType, s);
32 final JerseyRequest request = new JerseyRequest(delegateRequest, jerseyEntityHandler, plugin);
33 return (Request) Proxy.newProxyInstance(
34 getClass().getClassLoader(),
35 new Class[]{Request.class},
36 new ContextClassLoaderSwitchingProxy(request, getChainingClassLoader(plugin))
37 );
38 }
39
40 public boolean supportsHeader() {
41 ensureInitalised();
42 return delegateRequestFactory.supportsHeader();
43 }
44
45 private void ensureInitalised() {
46 if (jerseyEntityHandler == null) {
47 jerseyEntityHandler = createHandler();
48 }
49 }
50
51 private JerseyEntityHandler createHandler() {
52 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
53 ChainingClassLoader chainingClassLoader = getChainingClassLoader(plugin);
54 try {
55 Thread.currentThread().setContextClassLoader(chainingClassLoader);
56 return new JerseyEntityHandler((ContainerManagedPlugin) plugin, bundle);
57 } finally {
58 Thread.currentThread().setContextClassLoader(oldClassLoader);
59 }
60 }
61
62 void destroy() {
63 if (jerseyEntityHandler != null) {
64 jerseyEntityHandler.destroy();
65 }
66 }
67
68 private ChainingClassLoader getChainingClassLoader(final Plugin plugin) {
69 return new ChainingClassLoader(getClass().getClassLoader(), plugin.getClassLoader());
70 }
71 }