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