1 package com.atlassian.plugins.rest.module.servlet;
2
3 import static com.google.common.collect.Ordering.natural;
4
5 import com.atlassian.plugin.Plugin;
6 import com.atlassian.plugin.event.PluginEventManager;
7 import com.atlassian.plugin.servlet.DefaultServletModuleManager;
8 import com.atlassian.plugin.servlet.ServletModuleManager;
9 import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptor;
10 import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
11 import com.atlassian.plugin.servlet.filter.FilterDispatcherCondition;
12 import com.atlassian.plugin.servlet.filter.FilterLocation;
13 import com.atlassian.plugin.servlet.util.DefaultPathMapper;
14 import com.atlassian.plugin.servlet.util.PathMapper;
15 import com.atlassian.plugins.rest.module.RestApiContext;
16 import com.atlassian.plugins.rest.module.RestServletFilterModuleDescriptor;
17 import com.google.common.collect.Multimaps;
18 import com.google.common.collect.SortedSetMultimap;
19 import com.google.common.collect.TreeMultimap;
20
21 import org.apache.commons.lang.StringUtils;
22
23 import javax.servlet.Filter;
24 import javax.servlet.FilterConfig;
25 import javax.servlet.ServletConfig;
26 import javax.servlet.ServletContext;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServlet;
29
30 import java.util.Comparator;
31 import java.util.SortedSet;
32
33
34
35
36 public class DefaultRestServletModuleManager implements RestServletModuleManager {
37 private static final RestServletFilterModuleDescriptorComparator VALUE_COMPARATOR = new RestServletFilterModuleDescriptorComparator();
38
39
40
41
42 private final SortedSetMultimap<String, RestServletFilterModuleDescriptor> filterModuleDescriptors =
43 Multimaps.synchronizedSortedSetMultimap(TreeMultimap.<String, RestServletFilterModuleDescriptor>create(natural(), VALUE_COMPARATOR));
44
45 private final ServletModuleManager delegateModuleManager;
46 private final PathMapper filterPathMapper;
47 private final String path;
48
49 public DefaultRestServletModuleManager(PluginEventManager pluginEventManager, String path) {
50 this.filterPathMapper = new DefaultPathMapper();
51 this.delegateModuleManager = new DefaultServletModuleManager(pluginEventManager, new DefaultPathMapper(), filterPathMapper);
52 this.path = StringUtils.isNotBlank(path) ? path : "";
53 }
54
55 DefaultRestServletModuleManager(ServletModuleManager delegate, PathMapper filterPathMapper, String path) {
56 this.filterPathMapper = filterPathMapper;
57 this.delegateModuleManager = delegate;
58 this.path = StringUtils.isNotBlank(path) ? path : "";
59 }
60
61 @Override
62 public void addServlet(Plugin plugin, String servletName, String className) {
63 delegateModuleManager.addServlet(plugin, servletName, className);
64 }
65
66 @Override
67 public void addServlet(Plugin plugin, String servletName, HttpServlet servlet, ServletContext servletContext) {
68 delegateModuleManager.addServlet(plugin, servletName, servlet, servletContext);
69 }
70
71 @Override
72 public void addServletModule(ServletModuleDescriptor descriptor) {
73 delegateModuleManager.addServletModule(descriptor);
74 }
75
76 @Override
77 public HttpServlet getServlet(String path, ServletConfig servletConfig) throws ServletException {
78 return delegateModuleManager.getServlet(path, servletConfig);
79 }
80
81 @Override
82 public void removeServletModule(ServletModuleDescriptor descriptor) {
83 delegateModuleManager.removeServletModule(descriptor);
84 }
85
86 @Override
87 public void addFilterModule(ServletFilterModuleDescriptor descriptor) {
88 if (descriptor instanceof RestServletFilterModuleDescriptor) {
89 final RestServletFilterModuleDescriptor restServletFilterModuleDescriptor = (RestServletFilterModuleDescriptor) descriptor;
90 final RestServletFilterModuleDescriptor latest = getRestServletFilterModuleDescriptorForLatest(restServletFilterModuleDescriptor.getBasePath());
91 if (VALUE_COMPARATOR.compare(latest, restServletFilterModuleDescriptor) < 0) {
92 if (latest != null) {
93 filterPathMapper.put(latest.getCompleteKey(), null);
94 for (String path : latest.getPaths()) {
95 filterPathMapper.put(latest.getCompleteKey(), path);
96 }
97 }
98 filterPathMapper.put(descriptor.getCompleteKey(), getPathPattern(restServletFilterModuleDescriptor.getBasePath()));
99 }
100 filterModuleDescriptors.put(restServletFilterModuleDescriptor.getBasePath(), restServletFilterModuleDescriptor);
101 }
102 delegateModuleManager.addFilterModule(descriptor);
103 }
104
105 private RestServletFilterModuleDescriptor getRestServletFilterModuleDescriptorForLatest(String path) {
106 if (path == null) {
107 return null;
108 }
109
110 final SortedSet<RestServletFilterModuleDescriptor> moduleDescriptors = filterModuleDescriptors.get(path);
111 return moduleDescriptors.isEmpty() ? null : moduleDescriptors.last();
112 }
113
114 @Override
115 public Iterable<Filter> getFilters(FilterLocation location, String pathInfo, FilterConfig filterConfig) throws ServletException {
116 return delegateModuleManager.getFilters(location, pathInfo, filterConfig);
117 }
118
119 @Override
120 public Iterable<Filter> getFilters(FilterLocation location, String pathInfo, FilterConfig filterConfig, FilterDispatcherCondition filterDispatcherCondition) throws ServletException {
121 return delegateModuleManager.getFilters(location, StringUtils.removeStart(pathInfo, path), filterConfig, filterDispatcherCondition);
122 }
123
124 @Override
125 public void removeFilterModule(ServletFilterModuleDescriptor descriptor) {
126 if (descriptor instanceof RestServletFilterModuleDescriptor) {
127 final RestServletFilterModuleDescriptor restServletFilterModuleDescriptor = (RestServletFilterModuleDescriptor) descriptor;
128
129
130 RestServletFilterModuleDescriptor latest = getRestServletFilterModuleDescriptorForLatest(restServletFilterModuleDescriptor.getBasePath());
131 filterModuleDescriptors.remove(restServletFilterModuleDescriptor.getBasePath(), restServletFilterModuleDescriptor);
132
133 if (latest != null && latest.getCompleteKey().equals(descriptor.getCompleteKey())) {
134
135 latest = getRestServletFilterModuleDescriptorForLatest(restServletFilterModuleDescriptor.getBasePath());
136 if (latest != null) {
137 filterPathMapper.put(latest.getCompleteKey(), getPathPattern(latest.getBasePath()));
138 }
139 }
140 }
141
142
143 delegateModuleManager.removeFilterModule(descriptor);
144 }
145
146 String getPathPattern(String basePath) {
147 return basePath + RestApiContext.LATEST + RestApiContext.ANY_PATH_PATTERN;
148 }
149
150 private static final class RestServletFilterModuleDescriptorComparator implements Comparator<RestServletFilterModuleDescriptor> {
151 public int compare(RestServletFilterModuleDescriptor descriptor1, RestServletFilterModuleDescriptor descriptor2) {
152 if (descriptor1 == null) {
153 return -1;
154 }
155 if (descriptor2 == null) {
156 return +1;
157 }
158 return descriptor1.getVersion().compareTo(descriptor2.getVersion());
159 }
160 }
161 }