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