View Javadoc

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   * <p>Servlet module manager to handle REST servlets.</p>
32   */
33  public class DefaultRestServletModuleManager implements RestServletModuleManager
34  {
35      private static final RestServletFilterModuleDescriptorComparator VALUE_COMPARATOR = new RestServletFilterModuleDescriptorComparator();
36  
37      /**
38       * Multimap of filter module descriptors, the key is the "api path" of the REST module descriptor.
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             // check if it was the latest, before removing from the MultiMap
127             RestServletFilterModuleDescriptor latest = getRestServletFilterModuleDescriptorForLatest(restServletFilterModuleDescriptor.getBasePath());
128             filterModuleDescriptors.remove(restServletFilterModuleDescriptor.getBasePath(), restServletFilterModuleDescriptor);
129 
130             if (latest != null && latest.getCompleteKey().equals(descriptor.getCompleteKey()))
131             {
132                 // latest has changed as we have removed an item from the multimap
133                 latest = getRestServletFilterModuleDescriptorForLatest(restServletFilterModuleDescriptor.getBasePath());
134                 if (latest != null)
135                 {
136                     filterPathMapper.put(latest.getCompleteKey(), getPathPattern(latest.getBasePath()));
137                 }
138             }
139         }
140 
141         // remaing mapping of the descriptor will be removed by this call.
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 }