1 package com.atlassian.plugin.descriptors.servlet;
2
3 import java.util.Iterator;
4
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletRequestWrapper;
7
8 /**
9 * A request wrapper for requests bound for servlets declared in plugins. Does the necessary path
10 * munging for requests so that they look like they are
11 */
12 public class PluginHttpRequestWrapper extends HttpServletRequestWrapper
13 {
14 private final String basePath;
15
16 public PluginHttpRequestWrapper(HttpServletRequest request, ServletModuleDescriptor descriptor)
17 {
18 super(request);
19 this.basePath = findBasePath(descriptor);
20 }
21
22 public String getServletPath()
23 {
24 String servletPath = super.getServletPath();
25 if (basePath != null)
26 {
27 servletPath += basePath;
28 }
29 return servletPath;
30 }
31
32 public String getPathInfo()
33 {
34 String pathInfo = super.getPathInfo();
35 if (pathInfo != null && basePath != null)
36 return pathInfo.substring(basePath.length());
37 return pathInfo;
38 }
39
40 /**
41 * A <a href="http://bluxte.net/blog/2006-03/29-40-33.html">commenter</a> based on the
42 * <a href="http://java.sun.com/products/servlet/2.1/html/introduction.fm.html#1499">servlet mapping spec</a>
43 * defined the mapping processing as:
44 *
45 * <ol>
46 * <li>A string beginning with a '/' character and ending with a '/*' postfix is used for path mapping.</li>
47 * <li>A string beginning with a'*.' prefix is used as an extension mapping.</li>
48 * <li>A string containing only the '/' character indicates the "default" servlet of the application. In this
49 * case the servlet path is the request URI minus the context path and the path info is null.</li>
50 * <li>All other strings are used for exact matches only.</li>
51 * </ol>
52 *
53 * To find the base path we're really only interested in the first case. Everything else will just get a null
54 * base path. So we'll iterate through the list of paths specified and for the ones that match (1) above, check if
55 * the path info returned by the super class matches. If it does, we return that base path, otherwise we move onto
56 * the next one.
57 */
58 private String findBasePath(ServletModuleDescriptor descriptor)
59 {
60 String pathInfo = super.getPathInfo();
61 if (pathInfo != null)
62 {
63 for (Iterator pathIterator = descriptor.getPaths().iterator(); pathIterator.hasNext(); )
64 {
65 String basePath = (String) pathIterator.next();
66 if (isPathMapping(basePath) && pathInfo.startsWith(getMappingRootPath(basePath)))
67 {
68 return getMappingRootPath(basePath);
69 }
70 }
71 }
72 return null;
73 }
74
75 private boolean isPathMapping(String path)
76 {
77 return path.startsWith("/") && path.endsWith("/*");
78 }
79
80 private String getMappingRootPath(String pathMapping)
81 {
82 return pathMapping.substring(0, pathMapping.length() - 2);
83 }
84 }