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