1   package com.atlassian.plugins.rest.module;
2   
3   import com.atlassian.plugin.osgi.factory.OsgiPlugin;
4   import com.google.common.base.Preconditions;
5   import com.sun.jersey.api.core.ResourceConfig;
6   import com.sun.jersey.core.spi.component.ComponentContext;
7   import com.sun.jersey.core.spi.component.ComponentScope;
8   import com.sun.jersey.core.spi.component.ioc.IoCComponentProvider;
9   import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory;
10  import com.sun.jersey.core.spi.component.ioc.IoCManagedComponentProvider;
11  import com.sun.jersey.spi.resource.PerRequest;
12  
13  import java.util.Collections;
14  import java.util.HashSet;
15  import java.util.Set;
16  
17  /**
18   * <p>The OSGi component provider factory.</p>
19   * <p>This will support <em>user defined</em> resources and providers only.</p>
20   */
21  class OsgiComponentProviderFactory implements IoCComponentProviderFactory
22  {
23      /**
24       * The plugin that this factory belongs to.
25       */
26      private final OsgiPlugin plugin;
27  
28      /**
29       * The set of <em>user defined</em> resources and providers.
30       */
31      private final Set<Class<?>> classes;
32  
33      private final Set<?> instances;
34  
35      public OsgiComponentProviderFactory(ResourceConfig resourceConfig, OsgiPlugin plugin)
36      {
37          this.plugin = Preconditions.checkNotNull(plugin);
38  
39          // get the "user defined" resource and provider classes
40          final Set<Class<?>> classes = Preconditions.checkNotNull(resourceConfig).getClasses();
41          if (classes != null)
42          {
43              this.classes = new HashSet<Class<?>>(classes);
44          }
45          else
46          {
47              this.classes = Collections.emptySet();
48          }
49  
50          if (resourceConfig instanceof OsgiResourceConfig)
51          {
52              instances = ((OsgiResourceConfig) resourceConfig).getInstances();
53          }
54          else
55          {
56              instances = Collections.emptySet();
57          }
58      }
59  
60      public IoCComponentProvider getComponentProvider(final Class<?> c)
61      {
62          return getComponentProvider(null, c);
63      }
64  
65      public IoCComponentProvider getComponentProvider(ComponentContext cc, Class<?> c)
66      {
67          if (!classes.contains(c))
68          {
69              return null;
70          }
71          final Object instance = getInstance(c);
72          return instance == null ? new AutowiredOsgiComponentProvider(plugin, c) : new InstanceOsgiComponentProvider(instance);
73      }
74  
75      private Object getInstance(Class<?> c)
76      {
77          for (Object o : instances)
78          {
79              if (o.getClass().equals(c))
80              {
81                  return o;
82              }
83          }
84          return null;
85      }
86  
87      private static class AutowiredOsgiComponentProvider implements IoCManagedComponentProvider
88      {
89          private final OsgiPlugin plugin;
90          private final Class<?> componentClass;
91  
92          public AutowiredOsgiComponentProvider(OsgiPlugin plugin, Class<?> componentClass)
93          {
94              this.plugin = plugin;
95              this.componentClass = componentClass;
96          }
97  
98          public Object getInstance()
99          {
100             return plugin.autowire(componentClass);
101         }
102 
103         public ComponentScope getScope()
104         {
105             // If the class is annotated with PerRequest, then it should return per request, otherwise,
106             // default to singleton
107             if (componentClass.getAnnotation(PerRequest.class) != null)
108             {
109                 return ComponentScope.PerRequest;
110             }
111             return ComponentScope.Singleton;
112         }
113 
114         public Object getInjectableInstance(Object o)
115         {
116             plugin.autowire(o);
117             return o;
118         }
119     }
120 
121     private static class InstanceOsgiComponentProvider implements IoCManagedComponentProvider
122     {
123         private final Object instance;
124 
125         public InstanceOsgiComponentProvider(Object instance)
126         {
127             this.instance = Preconditions.checkNotNull(instance);
128         }
129 
130         public ComponentScope getScope()
131         {
132             return ComponentScope.Singleton;
133         }
134 
135         public Object getInstance()
136         {
137             return instance;
138         }
139 
140         public Object getInjectableInstance(Object o)
141         {
142             return o;
143         }
144     }
145 }