1   package com.atlassian.plugins.rest.module.jersey;
2   
3   import com.atlassian.plugin.AutowireCapablePlugin;
4   import com.atlassian.plugin.Plugin;
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  {
16      private final RequestFactory<? extends Request> delegateRequestFactory;
17      private final Plugin plugin;
18      private final Bundle bundle;
19  
20      /**
21       * lazily-loaded on init() *
22       */
23      private volatile JerseyEntityHandler jerseyEntityHandler;
24  
25      public JerseyRequestFactory(NonMarshallingRequestFactory<? extends Request> delegateRequestFactory, Plugin plugin, Bundle bundle)
26      {
27          this.plugin = plugin;
28          this.delegateRequestFactory = delegateRequestFactory;
29          this.bundle = bundle;
30      }
31  
32      public Request createRequest(final Request.MethodType methodType, final String s)
33      {
34          ensureInitalised();
35          ChainingClassLoader chainingClassLoader = getChainingClassLoader(plugin);
36          Request delegateRequest = delegateRequestFactory.createRequest(methodType, s);
37          JerseyRequest request = new JerseyRequest(delegateRequest, jerseyEntityHandler);
38          return (Request) Proxy.newProxyInstance(
39                  getClass().getClassLoader(),
40                  new Class[]{Request.class},
41                  new ContextClassLoaderSwitchingProxy(request, chainingClassLoader)
42          );
43      }
44  
45      public boolean supportsHeader()
46      {
47          ensureInitalised();
48          return delegateRequestFactory.supportsHeader();
49      }
50  
51      private void ensureInitalised()
52      {
53          if (jerseyEntityHandler == null)
54          {
55              throw new IllegalStateException("Must call init() before use");
56          }
57      }
58  
59      void destroy()
60      {
61          jerseyEntityHandler.destroy();
62      }
63  
64      void init()
65      {
66          ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
67          ChainingClassLoader chainingClassLoader = getChainingClassLoader(plugin);
68          try
69          {
70              Thread.currentThread().setContextClassLoader(chainingClassLoader);
71              jerseyEntityHandler = new JerseyEntityHandler((AutowireCapablePlugin) plugin, bundle);
72          }
73          finally
74          {
75              Thread.currentThread().setContextClassLoader(oldClassLoader);
76          }
77      }
78  
79      private ChainingClassLoader getChainingClassLoader(final Plugin plugin)
80      {
81          return new ChainingClassLoader(getClass().getClassLoader(), plugin.getClassLoader());
82      }
83  }