View Javadoc

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  }