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 }