View Javadoc
1   package com.atlassian.plugin.servlet;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptor;
5   import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
6   import com.atlassian.plugin.servlet.filter.FilterDispatcherCondition;
7   import com.atlassian.plugin.servlet.filter.FilterLocation;
8   import com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter;
9   
10  import javax.servlet.DispatcherType;
11  import javax.servlet.Filter;
12  import javax.servlet.FilterConfig;
13  import javax.servlet.Servlet;
14  import javax.servlet.ServletConfig;
15  import javax.servlet.ServletContext;
16  import javax.servlet.ServletContextListener;
17  import javax.servlet.ServletException;
18  import javax.servlet.http.HttpServlet;
19  
20  /**
21   * The ServletModuleManager is responsible for servlets and filters - and their servlet contexts - defined in plugins.
22   * It is used by instances of the {@link ServletModuleContainerServlet} and {@link ServletFilterModuleContainerFilter}
23   * to lookup, create and wrap the filters and servlets defined in plugins.
24   * <p/>
25   * When the first {@link Filter} or {@link Servlet} is first accessed in a plugin, a new {@link ServletContext} is
26   * created for all the modules in the plugin to share.  This is done by wrapping the applications
27   * {@link ServletContext}, creating a map of attributes that are local to the plugin that are shadowed by the
28   * applications {@link ServletContext} attributes, merging any servlet context init parameters from the plugin and the
29   * application, and then running through any {@link ServletContextListener}s defined by the plugin has calling their
30   * contextInitialized() methods.
31   * <p/>
32   * The shadowing of the the plugins {@link ServletContext}s attributes are shadowed by the applications attributes
33   * means that if an attribute does not exist in the plugin local attribute map, the applications attributes will be
34   * returned.  The plugin is thereby prevented from modifying the base applications context attributes on an application
35   * wide scope and can instead only change them, but not remove them, on a local scope.
36   * <p/>
37   * The init parameters in the plugin will override parameters from the base applications servlet
38   * init parameters that have the same name.
39   * <p/>
40   * During the creation of Filters and Servlets, the {@link FilterConfig} and {@link ServletConfig} provided to
41   * Filters and Servlets contain the plugin local {@link ServletContext}, as described above,
42   * and provides access to the init parameters defined in the plugin xml for the Filter or Servlet.
43   * <p/>
44   * After being created, the filters and servlets are wrapped to ensure the the init(), service(), doFilter(),
45   * and destroy() methods and other methods defined in the Filter and Servlet interfaces are executed in the plugins
46   * {@link ClassLoader}.
47   * <p/>
48   * The plugins {@link ServletContext} is not destroyed until the plugin is disabled.  It is also at this time that any
49   * {@link ServletContextListener}s will have their contextDestroyed() methods called.
50   */
51  public interface ServletModuleManager {
52      /**
53       * Register a new servlet plugin module.
54       *
55       * @param descriptor Details of what the servlet class is and the path it should serve.
56       */
57      void addServletModule(ServletModuleDescriptor descriptor);
58  
59      /**
60       * Return an instance of the HttpServlet that should be used to serve content matching the provided url path.
61       *
62       * @param path          Path of the incoming request to serve.
63       * @param servletConfig ServletConfig given to the delegating servlet.
64       * @return HttpServlet that has been registered to serve up content matching the passed in path.
65       * @throws ServletException Thrown if there is a problem initializing the servlet to be returned.
66       */
67      HttpServlet getServlet(String path, final ServletConfig servletConfig) throws ServletException;
68  
69      /**
70       * Remove a previously registered servlet plugin module.  Requests that come in on the path described in the
71       * descriptor will no longer be served.
72       *
73       * @param descriptor Details of what servlet module to remove.
74       */
75      void removeServletModule(ServletModuleDescriptor descriptor);
76  
77      /**
78       * Register a new filter plugin module.
79       *
80       * @param descriptor Details of what the filter class is and the path it should serve.
81       */
82      void addFilterModule(ServletFilterModuleDescriptor descriptor);
83  
84      /**
85       * Returns the filters that have been registered to filter requests at the specified path matching the location
86       * in the filter stack.  The filter dispatcher condition will be set to REQUEST.
87       *
88       * @param location     Place in the applications filter stack the filters should be applied.
89       * @param pathInfo     Path of the incoming request to filter.
90       * @param filterConfig FilterConfig given to the delegating filter.
91       * @return List of filters to be applied, already sorted by weight
92       * @throws ServletException Thrown if there is a problem initializing one of the filters to apply.
93       * @deprecated Since 2.5.0, use {@link #getFilters(FilterLocation, String, FilterConfig, FilterDispatcherCondition)} instead
94       */
95      @Deprecated
96      Iterable<Filter> getFilters(FilterLocation location, String pathInfo, FilterConfig filterConfig) throws ServletException;
97  
98      /**
99       * Returns the filters that have been registered to filter requests at the specified path matching the location
100      * in the filter stack and registered for the specific dispatcher condition.
101      * <p/>
102      *
103      * @param location     Place in the applications filter stack the filters should be applied.
104      * @param pathInfo     Path of the incoming request to filter.
105      * @param filterConfig FilterConfig given to the delegating filter.
106      * @param condition    The dispatcher tag that filters have been registered to.  Cannot be null.
107      * @return List of filters to be applied, already sorted by weight
108      * @throws ServletException Thrown if there is a problem initializing one of the filters to apply.
109      * @since 2.5.0
110      * @deprecated since 4.6.0. Use {@link #getFilters(FilterLocation, String, FilterConfig, DispatcherType)} instead.
111      */
112     @Deprecated
113     Iterable<Filter> getFilters(FilterLocation location, String pathInfo, FilterConfig filterConfig, FilterDispatcherCondition condition) throws ServletException;
114 
115     /**
116      * Returns the filters that have been registered to filter requests at the specified path matching the location
117      * in the filter stack and registered for the specific dispatcher condition.
118      * <p/>
119      *
120      * @param location     Place in the applications filter stack the filters should be applied.
121      * @param pathInfo     Path of the incoming request to filter.
122      * @param filterConfig FilterConfig given to the delegating filter.
123      * @param dispatcher   The dispatcher that filters have been registered to.  Cannot be null.
124      * @return List of filters to be applied, already sorted by weight
125      * @since 4.6.0
126      */
127     Iterable<Filter> getFilters(FilterLocation location, String pathInfo, FilterConfig filterConfig, DispatcherType dispatcher);
128 
129     /**
130      * Remove a previously registered filter plugin module.  Requests that come in on the path described in the
131      * descriptor will no longer be served.
132      *
133      * @param descriptor Details of what filter module to remove.
134      */
135     void removeFilterModule(ServletFilterModuleDescriptor descriptor);
136 
137     /**
138      * To be invoked by {@link com.atlassian.plugin.servlet.PluginServletContextWrapper#addServlet(String, String)} and
139      * {@link com.atlassian.plugin.servlet.PluginServletContextWrapper#addServlet(String, Class)}.
140      * <p/>
141      * Module containing the servlet will use <code>servletName</code> for:
142      * <ul>
143      * <li>key, with "-servlet" appended</li>
144      * <li>name, with "Servlet" appended</li>
145      * <li>url-pattern, with "/" prepended</li>
146      * </ul>
147      * <p/>
148      * An instance of <code>className</code> will be instantiated and initialised on first use.
149      *
150      * @param plugin      mandatory
151      * @param servletName mandatory
152      * @param className   mandatory
153      */
154     void addServlet(Plugin plugin, String servletName, String className);
155 
156     /**
157      * To be invoked by {@link com.atlassian.plugin.servlet.PluginServletContextWrapper#addServlet(String, javax.servlet.Servlet)}.
158      * <p/>
159      * Module containing the servlet will use <code>servletName</code> for:
160      * <ul>
161      * <li>key, with "-servlet" appended</li>
162      * <li>name, with "Servlet" appended</li>
163      * <li>url-pattern, with "/" prepended</li>
164      * </ul>
165      * <p/>
166      * <code>servlet</code> will be initialised on first use.
167      *
168      * @param plugin         mandatory
169      * @param servletName    mandatory
170      * @param servlet        mandatory
171      * @param servletContext mandatory
172      */
173     void addServlet(Plugin plugin, String servletName, HttpServlet servlet, ServletContext servletContext);
174 }