PageRenderTime 2640ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/servlet/src/com/google/inject/servlet/ServletModule.java

https://gitlab.com/metamorphiccode/guice
Java | 357 lines | 86 code | 24 blank | 247 comment | 4 complexity | 164cf4c437a29d1fd4c3975f01a52a2d MD5 | raw file
  1. /**
  2. * Copyright (C) 2006 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.inject.servlet;
  17. import static com.google.common.base.Preconditions.checkState;
  18. import com.google.common.collect.ImmutableList;
  19. import com.google.inject.AbstractModule;
  20. import com.google.inject.Key;
  21. import java.util.Map;
  22. import javax.servlet.Filter;
  23. import javax.servlet.ServletContext;
  24. import javax.servlet.http.HttpServlet;
  25. /**
  26. * Configures the servlet scopes and creates bindings for the servlet API
  27. * objects so you can inject the request, response, session, etc.
  28. *
  29. * <p>
  30. * You should subclass this module to register servlets and
  31. * filters in the {@link #configureServlets()} method.
  32. *
  33. * @author crazybob@google.com (Bob Lee)
  34. * @author dhanji@gmail.com (Dhanji R. Prasanna)
  35. */
  36. public class ServletModule extends AbstractModule {
  37. @Override
  38. protected final void configure() {
  39. checkState(filtersModuleBuilder == null, "Re-entry is not allowed.");
  40. checkState(servletsModuleBuilder == null, "Re-entry is not allowed.");
  41. filtersModuleBuilder = new FiltersModuleBuilder(binder());
  42. servletsModuleBuilder = new ServletsModuleBuilder(binder());
  43. try {
  44. // Install common bindings (skipped if already installed).
  45. install(new InternalServletModule());
  46. // Install local filter and servlet bindings.
  47. configureServlets();
  48. } finally {
  49. filtersModuleBuilder = null;
  50. servletsModuleBuilder = null;
  51. }
  52. }
  53. /**
  54. * <h3>Servlet Mapping EDSL</h3>
  55. *
  56. * <p> Part of the EDSL builder language for configuring servlets
  57. * and filters with guice-servlet. Think of this as an in-code replacement for web.xml.
  58. * Filters and servlets are configured here using simple java method calls. Here is a typical
  59. * example of registering a filter when creating your Guice injector:
  60. *
  61. * <pre>
  62. * Guice.createInjector(..., new ServletModule() {
  63. *
  64. * {@literal @}Override
  65. * protected void configureServlets() {
  66. * <b>serve("*.html").with(MyServlet.class)</b>
  67. * }
  68. * }
  69. * </pre>
  70. *
  71. * This registers a servlet (subclass of {@code HttpServlet}) called {@code MyServlet} to service
  72. * any web pages ending in {@code .html}. You can also use a path-style syntax to register
  73. * servlets:
  74. *
  75. * <pre>
  76. * <b>serve("/my/*").with(MyServlet.class)</b>
  77. * </pre>
  78. *
  79. * Every servlet (or filter) is required to be a singleton. If you cannot annotate the class
  80. * directly, you should add a separate {@code bind(..).in(Singleton.class)} rule elsewhere in
  81. * your module. Mapping a servlet that is bound under any other scope is an error.
  82. *
  83. * <p>
  84. * <h4>Dispatch Order</h4>
  85. * You are free to register as many servlets and filters as you like this way. They will
  86. * be compared and dispatched in the order in which the filter methods are called:
  87. *
  88. * <pre>
  89. *
  90. * Guice.createInjector(..., new ServletModule() {
  91. *
  92. * {@literal @}Override
  93. * protected void configureServlets() {
  94. * filter("/*").through(MyFilter.class);
  95. * filter("*.css").through(MyCssFilter.class);
  96. * filter("*.jpg").through(new MyJpgFilter());
  97. * // etc..
  98. *
  99. * serve("*.html").with(MyServlet.class);
  100. * serve("/my/*").with(MyServlet.class);
  101. * serve("*.jpg").with(new MyServlet());
  102. * // etc..
  103. * }
  104. * }
  105. * </pre>
  106. * This will traverse down the list of rules in lexical order. For example, a url
  107. * "{@code /my/file.js}" (after it runs through the matching filters) will first
  108. * be compared against the servlet mapping:
  109. *
  110. * <pre>
  111. * serve("*.html").with(MyServlet.class);
  112. * </pre>
  113. * And failing that, it will descend to the next servlet mapping:
  114. *
  115. * <pre>
  116. * serve("/my/*").with(MyServlet.class);
  117. * </pre>
  118. *
  119. * Since this rule matches, Guice Servlet will dispatch to {@code MyServlet}. These
  120. * two mapping rules can also be written in more compact form using varargs syntax:
  121. *
  122. * <pre>
  123. * serve(<b>"*.html", "/my/*"</b>).with(MyServlet.class);
  124. * </pre>
  125. *
  126. * This way you can map several URI patterns to the same servlet. A similar syntax is
  127. * also available for filter mappings.
  128. *
  129. * <p>
  130. * <h4>Regular Expressions</h4>
  131. * You can also map servlets (or filters) to URIs using regular expressions:
  132. * <pre>
  133. * <b>serveRegex("(.)*ajax(.)*").with(MyAjaxServlet.class)</b>
  134. * </pre>
  135. *
  136. * This will map any URI containing the text "ajax" in it to {@code MyAjaxServlet}. Such as:
  137. * <ul>
  138. * <li>http://www.google.com/ajax.html</li>
  139. * <li>http://www.google.com/content/ajax/index</li>
  140. * <li>http://www.google.com/it/is_totally_ajaxian</li>
  141. * </ul>
  142. *
  143. *
  144. * <h3>Initialization Parameters</h3>
  145. *
  146. * Servlets (and filters) allow you to pass in init params
  147. * using the {@code <init-param>} tag in web.xml. You can similarly pass in parameters to
  148. * Servlets and filters registered in Guice-servlet using a {@link java.util.Map} of parameter
  149. * name/value pairs. For example, to initialize {@code MyServlet} with two parameters
  150. * ({@code name="Dhanji", site="google.com"}) you could write:
  151. *
  152. * <pre>
  153. * Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
  154. * params.put("name", "Dhanji");
  155. * params.put("site", "google.com");
  156. *
  157. * ...
  158. * serve("/*").with(MyServlet.class, <b>params</b>)
  159. * </pre>
  160. *
  161. * <p>
  162. * <h3>Binding Keys</h3>
  163. *
  164. * You can also bind keys rather than classes. This lets you hide
  165. * implementations with package-local visbility and expose them using
  166. * only a Guice module and an annotation:
  167. *
  168. * <pre>
  169. * ...
  170. * filter("/*").through(<b>Key.get(Filter.class, Fave.class)</b>);
  171. * </pre>
  172. *
  173. * Where {@code Filter.class} refers to the Servlet API interface and {@code Fave.class} is a
  174. * custom binding annotation. Elsewhere (in one of your own modules) you can bind this
  175. * filter's implementation:
  176. *
  177. * <pre>
  178. * bind(Filter.class)<b>.annotatedWith(Fave.class)</b>.to(MyFilterImpl.class);
  179. * </pre>
  180. *
  181. * See {@link com.google.inject.Binder} for more information on binding syntax.
  182. *
  183. * <p>
  184. * <h3>Multiple Modules</h3>
  185. *
  186. * It is sometimes useful to capture servlet and filter mappings from multiple different
  187. * modules. This is essential if you want to package and offer drop-in Guice plugins that
  188. * provide servlet functionality.
  189. *
  190. * <p>
  191. * Guice Servlet allows you to register several instances of {@code ServletModule} to your
  192. * injector. The order in which these modules are installed determines the dispatch order
  193. * of filters and the precedence order of servlets. For example, if you had two servlet modules,
  194. * {@code RpcModule} and {@code WebServiceModule} and they each contained a filter that mapped
  195. * to the same URI pattern, {@code "/*"}:
  196. *
  197. * <p>
  198. * In {@code RpcModule}:
  199. * <pre>
  200. * filter("/*").through(RpcFilter.class);
  201. * </pre>
  202. *
  203. * In {@code WebServiceModule}:
  204. * <pre>
  205. * filter("/*").through(WebServiceFilter.class);
  206. * </pre>
  207. *
  208. * Then the order in which these filters are dispatched is determined by the order in which
  209. * the modules are installed:
  210. *
  211. * <pre>
  212. * <b>install(new WebServiceModule());</b>
  213. * install(new RpcModule());
  214. * </pre>
  215. *
  216. * In the case shown above {@code WebServiceFilter} will run first.
  217. *
  218. * @since 2.0
  219. */
  220. protected void configureServlets() {
  221. }
  222. private FiltersModuleBuilder filtersModuleBuilder;
  223. private ServletsModuleBuilder servletsModuleBuilder;
  224. private FiltersModuleBuilder getFiltersModuleBuilder() {
  225. checkState(filtersModuleBuilder != null,
  226. "This method can only be used inside configureServlets()");
  227. return filtersModuleBuilder;
  228. }
  229. private ServletsModuleBuilder getServletModuleBuilder() {
  230. checkState(servletsModuleBuilder != null,
  231. "This method can only be used inside configureServlets()");
  232. return servletsModuleBuilder;
  233. }
  234. /**
  235. * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
  236. * @since 2.0
  237. */
  238. protected final FilterKeyBindingBuilder filter(String urlPattern, String... morePatterns) {
  239. return getFiltersModuleBuilder()
  240. .filter(ImmutableList.<String>builder().add(urlPattern).add(morePatterns).build());
  241. }
  242. /**
  243. * @param urlPatterns Any Servlet-style patterns. examples: /*, /html/*, *.html, etc.
  244. * @since 5.0
  245. */
  246. protected final FilterKeyBindingBuilder filter(Iterable<String> urlPatterns) {
  247. return getFiltersModuleBuilder().filter(ImmutableList.copyOf(urlPatterns));
  248. }
  249. /**
  250. * @param regex Any Java-style regular expression.
  251. * @since 2.0
  252. */
  253. protected final FilterKeyBindingBuilder filterRegex(String regex, String... regexes) {
  254. return getFiltersModuleBuilder()
  255. .filterRegex(ImmutableList.<String>builder().add(regex).add(regexes).build());
  256. }
  257. /**
  258. * @param regexes Any Java-style regular expressions.
  259. * @since 5.0
  260. */
  261. protected final FilterKeyBindingBuilder filterRegex(Iterable<String> regexes) {
  262. return getFiltersModuleBuilder().filterRegex(ImmutableList.copyOf(regexes));
  263. }
  264. /**
  265. * @param urlPattern Any Servlet-style pattern. examples: /*, /html/*, *.html, etc.
  266. * @since 2.0
  267. */
  268. protected final ServletKeyBindingBuilder serve(String urlPattern, String... morePatterns) {
  269. return getServletModuleBuilder()
  270. .serve(ImmutableList.<String>builder().add(urlPattern).add(morePatterns).build());
  271. }
  272. /**
  273. * @param urlPatterns Any Servlet-style patterns. examples: /*, /html/*, *.html, etc.
  274. * @since 5.0
  275. */
  276. protected final ServletKeyBindingBuilder serve(Iterable<String> urlPatterns) {
  277. return getServletModuleBuilder().serve(ImmutableList.copyOf(urlPatterns));
  278. }
  279. /**
  280. * @param regex Any Java-style regular expression.
  281. * @since 2.0
  282. */
  283. protected final ServletKeyBindingBuilder serveRegex(String regex, String... regexes) {
  284. return getServletModuleBuilder()
  285. .serveRegex(ImmutableList.<String>builder().add(regex).add(regexes).build());
  286. }
  287. /**
  288. * @param regexes Any Java-style regular expressions.
  289. * @since 5.0
  290. */
  291. protected final ServletKeyBindingBuilder serveRegex(Iterable<String> regexes) {
  292. return getServletModuleBuilder().serveRegex(ImmutableList.copyOf(regexes));
  293. }
  294. /**
  295. * This method only works if you are using the {@linkplain GuiceServletContextListener} to
  296. * create your injector. Otherwise, it returns null.
  297. * @return The current servlet context.
  298. * @since 3.0
  299. */
  300. protected final ServletContext getServletContext() {
  301. return GuiceFilter.getServletContext();
  302. }
  303. /**
  304. * See the EDSL examples at {@link ServletModule#configureServlets()}
  305. *
  306. * @since 2.0
  307. */
  308. public static interface FilterKeyBindingBuilder {
  309. void through(Class<? extends Filter> filterKey);
  310. void through(Key<? extends Filter> filterKey);
  311. /** @since 3.0 */
  312. void through(Filter filter);
  313. void through(Class<? extends Filter> filterKey, Map<String, String> initParams);
  314. void through(Key<? extends Filter> filterKey, Map<String, String> initParams);
  315. /** @since 3.0 */
  316. void through(Filter filter, Map<String, String> initParams);
  317. }
  318. /**
  319. * See the EDSL examples at {@link ServletModule#configureServlets()}
  320. *
  321. * @since 2.0
  322. */
  323. public static interface ServletKeyBindingBuilder {
  324. void with(Class<? extends HttpServlet> servletKey);
  325. void with(Key<? extends HttpServlet> servletKey);
  326. /** @since 3.0 */
  327. void with(HttpServlet servlet);
  328. void with(Class<? extends HttpServlet> servletKey, Map<String, String> initParams);
  329. void with(Key<? extends HttpServlet> servletKey, Map<String, String> initParams);
  330. /** @since 3.0 */
  331. void with(HttpServlet servlet, Map<String, String> initParams);
  332. }
  333. }