View Javadoc

1   package com.atlassian.plugins.rest.module;
2   
3   import com.atlassian.plugin.module.ContainerManagedPlugin;
4   import com.atlassian.plugins.rest.common.expand.AdditionalExpandsProvider;
5   import com.atlassian.plugins.rest.common.expand.SelfExpandingExpander;
6   import com.atlassian.plugins.rest.common.expand.interceptor.ExpandInterceptor;
7   import com.atlassian.plugins.rest.common.expand.resolver.ChainingEntityExpanderResolver;
8   import com.atlassian.plugins.rest.common.expand.resolver.CollectionEntityExpanderResolver;
9   import com.atlassian.plugins.rest.common.expand.resolver.EntityExpanderResolver;
10  import com.atlassian.plugins.rest.common.expand.resolver.ExpandConstraintEntityExpanderResolver;
11  import com.atlassian.plugins.rest.common.expand.resolver.IdentityEntityExpanderResolver;
12  import com.atlassian.plugins.rest.common.expand.resolver.ListWrapperEntityExpanderResolver;
13  import com.atlassian.plugins.rest.common.filter.ExtensionJerseyFilter;
14  import com.atlassian.plugins.rest.common.interceptor.impl.InterceptorChainBuilderProvider;
15  import com.atlassian.plugins.rest.common.security.jersey.AntiSniffingResponseFilter;
16  import com.atlassian.plugins.rest.module.expand.resolver.PluginEntityExpanderResolver;
17  import com.atlassian.plugins.rest.module.filter.AcceptHeaderJerseyMvcFilter;
18  import com.atlassian.plugins.rest.module.filter.AcceptLanguageFilter;
19  import com.atlassian.plugins.rest.module.filter.CorsAcceptOptionsPreflightFilter;
20  import com.atlassian.plugins.rest.module.json.JsonWithPaddingResponseFilter;
21  import com.google.common.collect.ImmutableList;
22  import com.google.common.collect.Lists;
23  import com.sun.jersey.api.core.DefaultResourceConfig;
24  import com.sun.jersey.spi.container.ContainerRequestFilter;
25  import com.sun.jersey.spi.container.ContainerResponseFilter;
26  import com.sun.jersey.spi.container.ResourceFilterFactory;
27  import com.sun.jersey.spi.container.ResourceMethodDispatchProvider;
28  import com.sun.jersey.spi.inject.InjectableProvider;
29  import com.sun.jersey.spi.template.TemplateProcessor;
30  
31  import org.codehaus.jackson.map.Module;
32  import org.osgi.framework.Bundle;
33  import org.osgi.framework.BundleContext;
34  import org.osgi.framework.ServiceReference;
35  
36  import javax.ws.rs.ext.MessageBodyReader;
37  
38  import java.util.Arrays;
39  import java.util.Collection;
40  import java.util.Collections;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.Set;
44  
45  import static com.atlassian.plugins.rest.module.json.JsonWithPaddingResponseFilter.ATLASSIAN_ALLOW_JSONP;
46  import static com.google.common.collect.Lists.newArrayList;
47  
48  public class ResourceConfigManager {
49      private final OsgiServiceAccessor<ResourceFilterFactory> resourceFilterFactories;
50      private final OsgiServiceAccessor<InjectableProvider> injectableProviders;
51      private final OsgiServiceAccessor<TemplateProcessor> templateProcessors;
52      private final OsgiServiceAccessor<MessageBodyReader> messageBodyReaders;
53      private final OsgiServiceAccessor<ResourceMethodDispatchProvider> dispatchProviders;
54      private final OsgiServiceAccessor<Module> modules;
55      private final OsgiServiceAccessor<AdditionalExpandsProvider> additionalExpandsProvider;
56      private final ContainerManagedPlugin plugin;
57      private final Bundle bundle;
58  
59      public ResourceConfigManager(ContainerManagedPlugin plugin, Bundle bundle) {
60          this.plugin = plugin;
61          this.bundle = bundle;
62          BundleContext bundleContext = bundle.getBundleContext();
63  
64          // looking up resource filters
65          resourceFilterFactories = new OsgiServiceAccessor<ResourceFilterFactory>(ResourceFilterFactory.class, bundleContext, new OsgiFactory<ResourceFilterFactory>() {
66              public ResourceFilterFactory getInstance(BundleContext bundleContext, ServiceReference serviceReference) {
67                  return new OsgiServiceReferenceResourceFilterFactory(bundleContext, serviceReference);
68              }
69          });
70  
71          // looking up injectable providers
72          injectableProviders = new OsgiServiceAccessor<InjectableProvider>(InjectableProvider.class, bundleContext, new OsgiFactory<InjectableProvider>() {
73              public InjectableProvider getInstance(BundleContext bundleContext, ServiceReference serviceReference) {
74                  return (InjectableProvider) bundleContext.getService(serviceReference);
75              }
76          });
77  
78          templateProcessors = new OsgiServiceAccessor<TemplateProcessor>(TemplateProcessor.class, bundleContext, new OsgiFactory<TemplateProcessor>() {
79              public TemplateProcessor getInstance(BundleContext bundleContext, ServiceReference serviceReference) {
80                  return (TemplateProcessor) bundleContext.getService(serviceReference);
81              }
82          });
83  
84          messageBodyReaders = new OsgiServiceAccessor<MessageBodyReader>(MessageBodyReader.class, bundleContext, new OsgiFactory<MessageBodyReader>() {
85              public MessageBodyReader getInstance(final BundleContext bundleContext, final ServiceReference serviceReference) {
86                  return (MessageBodyReader) bundleContext.getService(serviceReference);
87              }
88          });
89  
90          dispatchProviders = new OsgiServiceAccessor<ResourceMethodDispatchProvider>(ResourceMethodDispatchProvider.class, bundleContext, new OsgiFactory<ResourceMethodDispatchProvider>() {
91              public ResourceMethodDispatchProvider getInstance(final BundleContext bundleContext, final ServiceReference serviceReference) {
92                  return (ResourceMethodDispatchProvider) bundleContext.getService(serviceReference);
93              }
94          });
95  
96          modules = new OsgiServiceAccessor<Module>(Module.class, bundleContext, new OsgiFactory<Module>() {
97              public Module getInstance(final BundleContext bundleContext, final ServiceReference serviceReference) {
98                  return (Module) bundleContext.getService(serviceReference);
99              }
100         });
101 
102         additionalExpandsProvider = new OsgiServiceAccessor<>(AdditionalExpandsProvider.class, bundleContext, (bundleContext1, serviceReference) -> (AdditionalExpandsProvider) bundleContext1.getService(serviceReference));
103     }
104 
105     public DefaultResourceConfig createResourceConfig(Map<String, Object> props, String[] excludes, Set<String> packages) {
106         // get the excludes parameter
107         final Collection<String> excludesCollection = excludes != null ? Arrays.asList(excludes) : Collections.<String>emptyList();
108 
109         final EntityExpanderResolver expanderResolver = new ChainingEntityExpanderResolver(Lists.<EntityExpanderResolver>newArrayList(
110                 new PluginEntityExpanderResolver(plugin),
111                 new CollectionEntityExpanderResolver(),
112                 new ListWrapperEntityExpanderResolver(),
113                 new ExpandConstraintEntityExpanderResolver(),
114                 new SelfExpandingExpander.Resolver(),
115                 new IdentityEntityExpanderResolver()
116         ));
117 
118         final Collection<Object> providers = Lists.newLinkedList();
119         providers.addAll(injectableProviders.get());
120         providers.addAll(templateProcessors.get());
121         providers.addAll(messageBodyReaders.get());
122         providers.addAll(dispatchProviders.get());
123 
124         providers.add(new InterceptorChainBuilderProvider(plugin, new ExpandInterceptor(expanderResolver, additionalExpandsProvider.get())));
125 
126         List<ContainerRequestFilter> containerRequestFilters = newArrayList(
127                 new ExtensionJerseyFilter(excludesCollection),
128                 new AcceptHeaderJerseyMvcFilter(),
129                 new AcceptLanguageFilter(),
130                 new CorsAcceptOptionsPreflightFilter()
131         );
132 
133         ImmutableList.Builder containerResponseFilters =
134                 new ImmutableList.Builder<ContainerResponseFilter>();
135         containerResponseFilters.add(new AntiSniffingResponseFilter());
136 
137         if ("true".equals(System.getProperty(ATLASSIAN_ALLOW_JSONP))) {
138             containerResponseFilters.add(new JsonWithPaddingResponseFilter());
139         }
140 
141         final OsgiResourceConfig osgiResourceConfig = new OsgiResourceConfig(bundle, packages,
142                 containerRequestFilters,
143                 containerResponseFilters.build(),
144                 resourceFilterFactories.get(),
145                 modules.get(),
146                 providers);
147 
148         return osgiResourceConfig;
149     }
150 
151     public void destroy() {
152         resourceFilterFactories.release();
153         injectableProviders.release();
154         templateProcessors.release();
155         messageBodyReaders.release();
156         dispatchProviders.release();
157         modules.release();
158         additionalExpandsProvider.release();
159     }
160 
161 
162 }