1 package com.atlassian.plugins.rest.module;
2
3 import com.atlassian.plugin.AutowireCapablePlugin;
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 {
46 private final OsgiServiceAccessor<ResourceFilterFactory> resourceFilterFactories;
47 private final OsgiServiceAccessor<InjectableProvider> injectableProviders;
48 private final OsgiServiceAccessor<TemplateProcessor> templateProcessors;
49 private final OsgiServiceAccessor<MessageBodyReader> messageBodyReaders;
50 private final OsgiServiceAccessor<ResourceMethodDispatchProvider> dispatchProviders;
51 private final OsgiServiceAccessor<Module> modules;
52 private final AutowireCapablePlugin plugin;
53 private final Bundle bundle;
54
55 public ResourceConfigManager(AutowireCapablePlugin plugin, Bundle bundle)
56 {
57 this.plugin = plugin;
58 this.bundle = bundle;
59 BundleContext bundleContext = bundle.getBundleContext();
60
61
62 resourceFilterFactories = new OsgiServiceAccessor<ResourceFilterFactory>(ResourceFilterFactory.class, bundleContext, new OsgiFactory<ResourceFilterFactory>()
63 {
64 public ResourceFilterFactory getInstance(BundleContext bundleContext, ServiceReference serviceReference)
65 {
66 return new OsgiServiceReferenceResourceFilterFactory(bundleContext, serviceReference);
67 }
68 });
69
70
71 injectableProviders = new OsgiServiceAccessor<InjectableProvider>(InjectableProvider.class, bundleContext, new OsgiFactory<InjectableProvider>()
72 {
73 public InjectableProvider getInstance(BundleContext bundleContext, ServiceReference serviceReference)
74 {
75 return (InjectableProvider) bundleContext.getService(serviceReference);
76 }
77 });
78
79 templateProcessors = new OsgiServiceAccessor<TemplateProcessor>(TemplateProcessor.class, bundleContext, new OsgiFactory<TemplateProcessor>()
80 {
81 public TemplateProcessor getInstance(BundleContext bundleContext, ServiceReference serviceReference)
82 {
83 return (TemplateProcessor) bundleContext.getService(serviceReference);
84 }
85 });
86
87 messageBodyReaders = new OsgiServiceAccessor<MessageBodyReader>(MessageBodyReader.class, bundleContext, new OsgiFactory<MessageBodyReader>()
88 {
89 public MessageBodyReader getInstance(final BundleContext bundleContext, final ServiceReference serviceReference)
90 {
91 return (MessageBodyReader) bundleContext.getService(serviceReference);
92 }
93 });
94
95 dispatchProviders = new OsgiServiceAccessor<ResourceMethodDispatchProvider>(ResourceMethodDispatchProvider.class, bundleContext, new OsgiFactory<ResourceMethodDispatchProvider>()
96 {
97 public ResourceMethodDispatchProvider getInstance(final BundleContext bundleContext, final ServiceReference serviceReference)
98 {
99 return (ResourceMethodDispatchProvider) bundleContext.getService(serviceReference);
100 }
101 });
102
103 modules = new OsgiServiceAccessor<Module>(Module.class, bundleContext, new OsgiFactory<Module>()
104 {
105 public Module getInstance(final BundleContext bundleContext, final ServiceReference serviceReference)
106 {
107 return (Module) bundleContext.getService(serviceReference);
108 }
109 });
110 }
111
112 public ResourceConfig createResourceConfig(Map<String, Object> props, String[] excludes, Set<String> packages)
113 {
114
115 final Collection<String> excludesCollection = excludes != null ? Arrays.asList(excludes) : Collections.<String>emptyList();
116
117 final EntityExpanderResolver expanderResolver = new ChainingEntityExpanderResolver(Lists.<EntityExpanderResolver>newArrayList(
118 new PluginEntityExpanderResolver(plugin),
119 new CollectionEntityExpanderResolver(),
120 new ListWrapperEntityExpanderResolver(),
121 new ExpandConstraintEntityExpanderResolver(),
122 new SelfExpandingExpander.Resolver(),
123 new IdentityEntityExpanderResolver()
124 ));
125
126 final Collection<Object> providers = Lists.newLinkedList();
127 providers.addAll(injectableProviders.get());
128 providers.addAll(templateProcessors.get());
129 providers.addAll(messageBodyReaders.get());
130 providers.addAll(dispatchProviders.get());
131
132 providers.add(new InterceptorChainBuilderProvider(plugin, new ExpandInterceptor(expanderResolver)));
133
134 List<ContainerRequestFilter> containerRequestFilters = newArrayList(new ExtensionJerseyFilter(excludesCollection), new AcceptHeaderJerseyMvcFilter(), new CorsAcceptOptionsPreflightFilter());
135
136 ImmutableList.Builder containerResponseFilters =
137 new ImmutableList.Builder<ContainerResponseFilter>();
138 containerResponseFilters.add(new AntiSniffingResponseFilter());
139
140 if ("true".equals(System.getProperty(ATLASSIAN_ALLOW_JSONP)))
141 {
142 containerResponseFilters.add(new JsonWithPaddingResponseFilter());
143 }
144
145 return new OsgiResourceConfig(bundle, packages,
146 containerRequestFilters,
147 containerResponseFilters.build(),
148 resourceFilterFactories.get(),
149 modules.get(),
150 providers);
151 }
152
153 public void destroy()
154 {
155 resourceFilterFactories.release();
156 injectableProviders.release();
157 templateProcessors.release();
158 messageBodyReaders.release();
159 dispatchProviders.release();
160 modules.release();
161 }
162
163
164 }