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.spi.container.WebApplication;
7 import com.sun.jersey.spi.container.servlet.ServletContainer;
8 import com.sun.jersey.spi.container.servlet.WebConfig;
9 import org.apache.commons.lang.StringUtils;
10
11 import javax.servlet.Filter;
12 import javax.servlet.FilterChain;
13 import javax.servlet.FilterConfig;
14 import javax.servlet.ServletException;
15 import javax.servlet.ServletRequest;
16 import javax.servlet.ServletResponse;
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpServletResponse;
19 import javax.ws.rs.core.UriBuilder;
20 import java.io.IOException;
21 import java.net.URI;
22 import java.util.Map;
23
24
25
26
27
28 class RestDelegatingServletFilter implements Filter
29 {
30
31
32
33 private final ServletContainer servletContainer;
34 private final ResourceConfigManager resourceConfigManager;
35
36 RestDelegatingServletFilter(OsgiPlugin plugin, RestApiContext restContextPath)
37 {
38 resourceConfigManager = new ResourceConfigManager(plugin, plugin.getBundle());
39 this.servletContainer = new JerseyOsgiServletContainer(plugin, restContextPath, resourceConfigManager);
40 }
41
42 public void init(FilterConfig config) throws ServletException
43 {
44 final ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
45 try
46 {
47 Thread.currentThread().setContextClassLoader(new ChainingClassLoader(RestModuleDescriptor.class.getClassLoader(), currentThreadClassLoader));
48 servletContainer.init(config);
49 }
50 finally
51 {
52 Thread.currentThread().setContextClassLoader(currentThreadClassLoader);
53 }
54 }
55
56 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
57 {
58 final ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
59 try
60 {
61 Thread.currentThread().setContextClassLoader(new ChainingClassLoader(RestModuleDescriptor.class.getClassLoader(), currentThreadClassLoader));
62 servletContainer.doFilter(request, response, chain);
63 }
64 finally
65 {
66 Thread.currentThread().setContextClassLoader(currentThreadClassLoader);
67 }
68 }
69
70 public void destroy()
71 {
72 servletContainer.destroy();
73 resourceConfigManager.destroy();
74 }
75
76
77
78
79 private static class JerseyOsgiServletContainer extends ServletContainer
80 {
81 private final OsgiPlugin plugin;
82 private final RestApiContext restApiContext;
83 private final ResourceConfigManager resourceConfigManager;
84
85 private static final String PARAM_EXTENSION_FILTER_EXCLUDES = "extension.filter.excludes";
86
87 public JerseyOsgiServletContainer(OsgiPlugin plugin, RestApiContext restApiContext, final ResourceConfigManager resourceConfigManager)
88 {
89 this.resourceConfigManager = Preconditions.checkNotNull(resourceConfigManager);
90 this.plugin = Preconditions.checkNotNull(plugin);
91 this.restApiContext = Preconditions.checkNotNull(restApiContext);
92 }
93
94 @Override
95 protected ResourceConfig getDefaultResourceConfig(Map<String, Object> props, WebConfig webConfig) throws ServletException
96 {
97
98 final String deprecatedName = "com.atlassian.plugins.rest.module.filter.ExtensionJerseyFilter" + "#excludes";
99 final String excludeParam = webConfig.getInitParameter(deprecatedName) != null ?
100 webConfig.getInitParameter(deprecatedName) : webConfig.getInitParameter(PARAM_EXTENSION_FILTER_EXCLUDES);
101
102 final String[] excludes = StringUtils.split(excludeParam, " ,;");
103
104 return resourceConfigManager.createResourceConfig(props, excludes, restApiContext.getPackages());
105 }
106
107 @Override
108 public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
109 throws IOException, ServletException
110 {
111
112 String baseUriPath;
113 if (request.getRequestURI().contains(restApiContext.getPathToLatest()))
114 {
115 baseUriPath = request.getContextPath() + restApiContext.getPathToLatest();
116 }
117 else
118 {
119 baseUriPath = request.getContextPath() + restApiContext.getPathToVersion();
120 }
121 final UriBuilder absoluteUriBuilder = UriBuilder.fromUri(request.getRequestURL().toString());
122
123 final URI baseUri = absoluteUriBuilder.replacePath(baseUriPath).path("/").build();
124
125 final URI requestUri = absoluteUriBuilder.replacePath(request.getRequestURI()).replaceQuery(
126 request.getQueryString()).build();
127
128 service(baseUri, requestUri, request, response);
129 }
130
131 @Override
132 protected void initiate(ResourceConfig resourceConfig, WebApplication webApplication)
133 {
134 webApplication.initiate(resourceConfig, new OsgiComponentProviderFactory(resourceConfig, plugin));
135 }
136 }
137 }