You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2007/11/23 18:35:24 UTC

svn commit: r597707 - in /myfaces/core/trunk_1.2.x/impl/src: main/java/org/apache/myfaces/application/ main/java/org/apache/myfaces/webapp/ test/java/org/apache/myfaces/application/

Author: matzew
Date: Fri Nov 23 09:35:13 2007
New Revision: 597707

URL: http://svn.apache.org/viewvc?rev=597707&view=rev
Log:
MYFACES-1694
Big thanks to Bernhard Huemer for providing the patch

Modified:
    myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/application/DefaultViewHandlerSupport.java
    myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java
    myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/DefaultViewHandlerSupportTest.java

Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/application/DefaultViewHandlerSupport.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/application/DefaultViewHandlerSupport.java?rev=597707&r1=597706&r2=597707&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/application/DefaultViewHandlerSupport.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/application/DefaultViewHandlerSupport.java Fri Nov 23 09:35:13 2007
@@ -20,31 +20,40 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.myfaces.shared_impl.webapp.webxml.ServletMapping;
-import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
 
 import javax.faces.application.ViewHandler;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
-import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * A ViewHandlerSupport implementation for use with standard Java Servlet engines,
  * ie an engine that supports javax.servlet, and uses a standard web.xml file.
- * 
+ *
  * @author Mathias Broekelmann (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
 public class DefaultViewHandlerSupport implements ViewHandlerSupport
 {
-    private static final String SERVLET_MAPPING = DefaultViewHandlerSupport.class.getName() + ".ServletMapping";
+    /**
+     * Identifies the FacesServlet mapping in the current request map.
+     */
+    private static final String CACHED_SERVLET_MAPPING = 
+        DefaultViewHandlerSupport.class.getName() + ".CACHED_SERVLET_MAPPING";
+	
+	/**
+     * A RegEx pattern to determine if an extension is available in the given
+     * path.
+     */
+    private static final Pattern EXTENSION_PATTERN = Pattern.compile("(\\..*)");
 
     private static final Log log = LogFactory.getLog(DefaultViewHandlerSupport.class);
 
     public String calculateViewId(FacesContext context, String viewId)
     {
-        ServletMapping mapping = calculateServletMapping(context);
+        FacesServletMapping mapping = getFacesServletMapping(context);
         if (mapping == null || mapping.isExtensionMapping())
         {
             viewId = applyDefaultSuffix(context, viewId);
@@ -61,7 +70,7 @@
         if (viewId == null || !viewId.startsWith("/"))
             throw new IllegalArgumentException("ViewId must start with a '/': " + viewId);
 
-        ServletMapping mapping = calculateServletMapping(context);
+        FacesServletMapping mapping = getFacesServletMapping(context);
         ExternalContext externalContext = context.getExternalContext();
         String contextPath = externalContext.getRequestContextPath();
         StringBuilder builder = new StringBuilder(contextPath);
@@ -97,79 +106,75 @@
         }
         return calculatedActionURL;
     }
-
+    
     /**
      * Read the web.xml file that is in the classpath and parse its internals to
      * figure out how the FacesServlet is mapped for the current webapp.
      */
-    protected ServletMapping calculateServletMapping(FacesContext context)
+    protected FacesServletMapping getFacesServletMapping(FacesContext context)
     {
-        ExternalContext externalContext = context.getExternalContext();
-        Map<String, Object> requestMap = externalContext.getRequestMap();
-        ServletMapping mapping = null;
-        if (requestMap.containsKey(externalContext))
+        Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
+
+        // Has the mapping already been determined during this request?
+        if (!requestMap.containsKey(CACHED_SERVLET_MAPPING))
         {
-            mapping = (ServletMapping) requestMap.get(SERVLET_MAPPING);
+            ExternalContext externalContext = context.getExternalContext();
+            FacesServletMapping mapping = 
+                calculateFacesServletMapping(
+                    externalContext.getRequestServletPath(), 
+                    externalContext.getRequestPathInfo());
+
+            requestMap.put(CACHED_SERVLET_MAPPING, mapping);
+        }
+
+        return (FacesServletMapping) requestMap.get(CACHED_SERVLET_MAPPING);
+    }
+	
+	/**
+     * Determines the mapping of the FacesServlet in the web.xml configuration
+     * file. However, there is no need to actually parse this configuration file
+     * as runtime information is sufficient.
+     * 
+     * @param servletPath
+     *            The servletPath of the current request
+     * @param pathInfo
+     *            The pathInfo of the current request
+     * 
+     * @return the mapping of the FacesServlet in the web.xml configuration file
+     */
+    protected static FacesServletMapping calculateFacesServletMapping(
+            String servletPath, String pathInfo)
+    {
+        if (pathInfo != null)
+        {
+            // If there is a "extra path", it's definitely no extension mapping.
+            // Now we just have to determine the path which has been specified 
+            // in the url-pattern, but that's easy as it's the same as the
+            // current servletPath. It doesn't even matter if "/*" has been used
+            // as in this case the servletPath is just an empty string according
+            // to the Servlet Specification (SRV 4.4).
+            return FacesServletMapping.createPrefixMapping(servletPath);
         }
         else
         {
-            String servletPath = externalContext.getRequestServletPath();
-            String requestPathInfo = externalContext.getRequestPathInfo();
-
-            WebXml webxml = WebXml.getWebXml(externalContext);
-            List mappings = webxml.getFacesServletMappings();
-
-            if (requestPathInfo == null)
+            // In the case of extension mapping, no "extra path" is available.
+            // Still it's possible that prefix-based mapping has been used. 
+            // Actually, if there was an exact match no "extra path" 
+            // is available (e.g. if the url-pattern is "/faces/*" 
+            // and the request-uri is "/context/faces").
+            Matcher extensionMatcher = EXTENSION_PATTERN.matcher(servletPath);
+            if (extensionMatcher.find())
             {
-                // might be extension mapping
-                for (int i = 0, size = mappings.size(); i < size && mapping == null; i++)
-                {
-                    ServletMapping servletMapping = (ServletMapping) mappings.get(i);
-                    String urlpattern = servletMapping.getUrlPattern();
-                    String extension = urlpattern.substring(1, urlpattern.length());
-                    if (servletPath.endsWith(extension))
-                    {
-                        mapping = servletMapping;
-                    }
-                    else if (servletPath.equals(urlpattern))
-                    {
-                        // path mapping with no pathInfo for the current request
-                        mapping = servletMapping;
-                    }
-                }
+                String extension = extensionMatcher.group(1);
+                return FacesServletMapping.createExtensionMapping(extension);
             }
             else
             {
-                // path mapping
-                for (int i = 0, size = mappings.size(); i < size && mapping == null; i++)
-                {
-
-                    ServletMapping servletMapping = (ServletMapping) mappings.get(i);
-                    String urlpattern = servletMapping.getUrlPattern();
-                    urlpattern = urlpattern.substring(0, urlpattern.length() - 2);
-                    // servletPath starts with "/" except in the case where the
-                    // request is matched with the "/*" pattern, in which case
-                    // it is the empty string (see Servlet Sepc 2.3 SRV4.4)
-                    if (servletPath.equals(urlpattern))
-                    {
-                        mapping = servletMapping;
-                    }
-                }
-            }
-
-            // handle cases as best possible where servletPath is not a faces servlet,
-            // such as when coming through struts-faces
-            if (mapping == null && mappings.size() > 0)
-            {
-                mapping = (ServletMapping) mappings.get(0);
+                // There is no extension in the given servletPath and therefore 
+                // we assume that it's an exact match using prefix-based mapping.
+                return FacesServletMapping.createPrefixMapping(servletPath);
             }
-
-            if (mapping == null && log.isWarnEnabled())
-                log.warn("no faces servlet mappings found");
-
-            requestMap.put(SERVLET_MAPPING, mapping);
         }
-        return mapping;
     }
 
     protected String getContextSuffix(FacesContext context)
@@ -216,5 +221,139 @@
             }
         }
         return viewId;
+    }
+    
+    /**
+     * Represents a mapping entry of the FacesServlet in the web.xml
+     * configuration file.
+     * 
+     */
+    protected static class FacesServletMapping
+    {
+
+        /**
+         * The path ("/faces", for example) which has been specified in the
+         * url-pattern of the FacesServlet mapping.
+         */
+        private String prefix;
+
+        /**
+         * The extension (".jsf", for example) which has been specified in the
+         * url-pattern of the FacesServlet mapping.
+         */
+        private String extension;
+
+        /**
+         * Creates a new FacesServletMapping object using prefix mapping.
+         * 
+         * @param path
+         *            The path ("/faces", for example) which has been specified
+         *            in the url-pattern of the FacesServlet mapping.
+         * 
+         * @return a newly created FacesServletMapping
+         */
+        public static FacesServletMapping createPrefixMapping(String path)
+        {
+            FacesServletMapping mapping = new FacesServletMapping();
+            mapping.setPrefix(path);
+            return mapping;
+        }
+
+        /**
+         * Creates a new FacesServletMapping object using extension mapping.
+         * 
+         * @param path
+         *            The extension (".jsf", for example) which has been
+         *            specified in the url-pattern of the FacesServlet mapping.
+         * 
+         * @return a newly created FacesServletMapping
+         */
+        public static FacesServletMapping createExtensionMapping(
+                String extension)
+        {
+            FacesServletMapping mapping = new FacesServletMapping();
+            mapping.setExtension(extension);
+            return mapping;
+        }
+
+        /**
+         * Returns the path ("/faces", for example) which has been specified in
+         * the url-pattern of the FacesServlet mapping. If this mapping is based
+         * on an extension, <code>null</code> will be returned. Note that this
+         * path is not the same as the specified url-pattern as the trailing
+         * "/*" is omitted.
+         * 
+         * @return the path which has been specified in the url-pattern
+         */
+        public String getPrefix()
+        {
+            return prefix;
+        }
+
+        /**
+         * Sets the path ("/faces/", for example) which has been specified in
+         * the url-pattern.
+         * 
+         * @param path
+         *            The path which has been specified in the url-pattern
+         */
+        public void setPrefix(String path)
+        {
+            this.prefix = path;
+        }
+
+        /**
+         * Returns the extension (".jsf", for example) which has been specified
+         * in the url-pattern of the FacesServlet mapping. If this mapping is
+         * not based on an extension, <code>null</code> will be returned.
+         * 
+         * @return the extension which has been specified in the url-pattern
+         */
+        public String getExtension()
+        {
+            return extension;
+        }
+
+        /**
+         * Sets the extension (".jsf", for example) which has been specified in
+         * the url-pattern of the FacesServlet mapping.
+         * 
+         * @param extension
+         *            The extension which has been specified in the url-pattern
+         */
+        public void setExtension(String extension)
+        {
+            this.extension = extension;
+        }
+
+        /**
+         * Indicates whether this mapping is based on an extension (e.g.
+         * ".jsp").
+         * 
+         * @return <code>true</code>, if this mapping is based is on an
+         *         extension, <code>false</code> otherwise
+         */
+        public boolean isExtensionMapping()
+        {
+            return extension != null;
+        }
+
+        /**
+         * Returns the url-pattern entry for this servlet mapping.
+         * 
+         * @return the url-pattern entry for this servlet mapping
+         */
+        public String getUrlPattern()
+        {
+            if (isExtensionMapping())
+            {
+                return "*" + extension;
+            }
+            else
+            {
+                return prefix + "/*";
+            }
+        }
+
     }
 }

Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java?rev=597707&r1=597706&r2=597707&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java Fri Nov 23 09:35:13 2007
@@ -66,19 +66,10 @@
             // Load the configuration
             ExternalContext externalContext = new ServletExternalContextImpl(servletContext, null, null);
 
-            // parse web.xml
-            WebXml webXml = WebXml.getWebXml(externalContext);
-            if(webXml==null)
-            {
-                log.warn("Couldn't find web.xml. Abort initializing MyFaces.");
+            boolean validWebXml = validateWebXml(externalContext);
+            if (!validWebXml) {
                 return;
             }
-            if(webXml.getFacesServletMappings().isEmpty())
-            {
-                log.warn("No mappings of FacesServlet found. Abort initializing MyFaces.");
-                return;
-            }
-
 
             // TODO: this Class.forName will be removed when Tomcat fixes a bug
             // also, we should then be able to remove jasper.jar from the deployment
@@ -126,7 +117,7 @@
             log.error("Error initializing MyFaces: " + ex.getMessage(), ex);
         }
     }
-
+    
     protected JspFactory getJspFactory()
     {
         if (_jspFactory == null)
@@ -164,6 +155,34 @@
         {
             factory.getLifecycle(iter.next()).addPhaseListener(resolverForJSPInitializer);
         }
+    }
+    
+    /**
+     * Validates the web.xml configuration file, i.e it checks if a FacesServlet
+     * mapping is found.
+     * 
+     * @param context
+     *            The current ExternalContext
+     * 
+     * @return <code>true</code>, if the web.xml configuration file is valid,
+     *         <code>false</code> otherwise
+     */
+    protected boolean validateWebXml(ExternalContext context)
+    {
+        // parse web.xml
+        WebXml webXml = WebXml.getWebXml(context);
+        if (webXml == null)
+        {
+            log.warn("Couldn't find web.xml. Abort initializing MyFaces.");
+            return false;
+        }
+        if (webXml.getFacesServletMappings().isEmpty())
+        {
+            log.warn("No mappings of FacesServlet found. Abort initializing MyFaces.");
+            return false;
+        }
+        
+        return true;
     }
 
     protected void validateFacesConfigIfNecessary(ServletContext servletContext, ExternalContext externalContext)

Modified: myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/DefaultViewHandlerSupportTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/DefaultViewHandlerSupportTest.java?rev=597707&r1=597706&r2=597707&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/DefaultViewHandlerSupportTest.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/application/DefaultViewHandlerSupportTest.java Fri Nov 23 09:35:13 2007
@@ -24,12 +24,11 @@
 
 import javax.faces.application.ViewHandler;
 import javax.faces.context.FacesContext;
-import javax.faces.webapp.FacesServlet;
 
 import org.apache.myfaces.Assert;
 import org.apache.myfaces.FacesTestCase;
 import org.apache.myfaces.TestRunner;
-import org.apache.myfaces.shared_impl.webapp.webxml.ServletMapping;
+import org.apache.myfaces.application.DefaultViewHandlerSupport.FacesServletMapping;
 
 /**
  * @author Mathias Broekelmann (latest modification by $Author$)
@@ -48,31 +47,31 @@
      */
     public void testCalculateViewId() throws Exception
     {
-        assertCalculateViewId("xx.jsp", "*.faces", ".jsp", "xx.faces");
-        assertCalculateViewId("xx.jspx", "*.faces", ".jspx", "xx.faces");
-        assertCalculateViewId("xx.jsp", "*.jsf", ".jsp", "xx.jsf");
-        assertCalculateViewId("xx.jspx", "*.jsf", ".jspx", "xx.jsf");
-        assertCalculateViewId("xx.jsp", "/faces/*", ".jsp", "xx.jsp");
-        assertCalculateViewId("xx.xyz", "/faces/*", ".jsp", "xx.xyz");
-        assertCalculateViewId(null, "/faces/*", ".jsp", null);
-        assertCalculateViewId(null, "/xyz", ".jsp", null);
-    }
-
-    private void assertCalculateViewId(String expectedViewId, String urlPattern, String contextSuffix, String viewId)
-            throws Exception
-    {
-        ServletMapping servletMapping = new ServletMapping("servletName", FacesServlet.class, urlPattern);
-        DefaultViewHandlerSupport testImpl = _mocksControl.createMock(DefaultViewHandlerSupport.class, new Method[] {
-                DefaultViewHandlerSupport.class.getDeclaredMethod("calculateServletMapping",
-                        new Class[] { FacesContext.class }),
-                DefaultViewHandlerSupport.class.getDeclaredMethod("getContextSuffix",
-                        new Class[] { FacesContext.class }) });
-        expect(testImpl.getContextSuffix(same(_facesContext))).andReturn(contextSuffix);
-        expect(testImpl.calculateServletMapping(same(_facesContext))).andReturn(servletMapping);
-        expect(_facesContext.getExternalContext()).andReturn(_externalContext).anyTimes();
-        _mocksControl.replay();
-        assertEquals(expectedViewId, testImpl.calculateViewId(_facesContext, viewId));
-        _mocksControl.reset();
+        // extension mapping
+        assertCalculateViewId("xx.jsp", "/xx.faces", null, ".jsp", "xx.faces");
+        assertCalculateViewId("xx.jspx", "/xx.faces", null, ".jspx", "xx.faces");
+        assertCalculateViewId("xx.jsp", "/xx.jsf", null, ".jsp", "xx.jsf");
+        assertCalculateViewId("xx.jspx", "/xx.jsf", null, ".jspx", "xx.jsf");
+
+        // path mapping
+        assertCalculateViewId("xx.jsp", "/faces", "/xx.jsp", ".jsp", "xx.jsp");
+        assertCalculateViewId("xx.xyz", "/faces", "/xx.xyz", ".jsp", "xx.xyz");
+    }
+    
+    private void assertCalculateViewId(
+    		String expectedViewId, String servletPath, String pathInfo, 
+    			String contextSuffix, String viewId) throws Exception
+    {
+    	DefaultViewHandlerSupport support = createdMockedViewHandlerSupport();
+    	
+    	expect(support.getContextSuffix(same(_facesContext))).andReturn(contextSuffix);
+    	expect(support.getFacesServletMapping(same(_facesContext))).andReturn(
+    			DefaultViewHandlerSupport.calculateFacesServletMapping(servletPath, pathInfo));
+    	expect(_facesContext.getExternalContext()).andReturn(_externalContext).anyTimes();
+    	
+    	_mocksControl.replay();
+    	assertEquals(expectedViewId, support.calculateViewId(_facesContext, viewId));
+    	_mocksControl.reset();
     }
 
     /**
@@ -100,30 +99,107 @@
                 new DefaultViewHandlerSupport().calculateActionURL(_facesContext, "xxx");
             }
         });
-        assertActionUrl("/context/testViewId.jsx", "/*", "/context", "/testViewId.jsx");
-        assertActionUrl("/context/faces/testViewId.jsp", "/faces/*", "/context", "/testViewId.jsp");
-        assertActionUrl("/context/faces/testViewId.faces", "*.faces", "/context", "/faces/testViewId" + DEFAULT_SUFFIX);
-        assertActionUrl("/ctx/faces/testViewId.jsf", "*.jsf", "/ctx", "/faces/testViewId" + DEFAULT_SUFFIX);
-    }
-
-    private void assertActionUrl(String expectedActionURL, String urlPattern, String contextPath, String viewId)
-            throws Exception
-    {
-        ServletMapping servletMapping = new ServletMapping("servletName", FacesServlet.class, urlPattern);
-        DefaultViewHandlerSupport testImpl = _mocksControl.createMock(DefaultViewHandlerSupport.class, new Method[] {
-                DefaultViewHandlerSupport.class.getDeclaredMethod("calculateServletMapping",
-                        new Class[] { FacesContext.class }),
-                DefaultViewHandlerSupport.class.getDeclaredMethod("getContextSuffix",
-                        new Class[] { FacesContext.class }) });
-        expect(testImpl.getContextSuffix(same(_facesContext))).andReturn(DEFAULT_SUFFIX);
-        expect(testImpl.calculateServletMapping(same(_facesContext))).andReturn(servletMapping);
-        expect(_facesContext.getExternalContext()).andReturn(_externalContext).anyTimes();
-        expect(_externalContext.getRequestContextPath()).andReturn(contextPath);
-        _mocksControl.replay();
-        assertEquals(expectedActionURL, testImpl.calculateActionURL(_facesContext, viewId));
-        _mocksControl.reset();
+
+        // extension mapping
+        assertActionUrl("/context/faces/testViewId.faces", "/context", "/testViewId.faces", null, "/faces/testViewId.jsp");
+        assertActionUrl("/ctx/faces/testViewId.jsf", "/ctx",  "/faces/testViewId.jsf", null, "/faces/testViewId.jsp");
+
+        // path mapping
+        assertActionUrl("/context/testViewId.jsx", "/context", "", "/testViewId.jsx", "/testViewId.jsx");
+        assertActionUrl("/context/faces/testViewId.jsp", "/context", "/faces", "/testViewId.jsp", "/testViewId.jsp");
     }
+    
+    private void assertActionUrl(
+    		String expectedActionUrl, String contextPath, String servletPath, 
+    			String pathInfo, String viewId) throws Exception 
+    {
+    	DefaultViewHandlerSupport support = createdMockedViewHandlerSupport();
+    	
+    	expect(support.getContextSuffix(same(_facesContext))).andReturn(DEFAULT_SUFFIX);
+    	expect(support.getFacesServletMapping(same(_facesContext))).andReturn(
+    			DefaultViewHandlerSupport.calculateFacesServletMapping(servletPath, pathInfo));
+    	expect(_facesContext.getExternalContext()).andReturn(_externalContext).anyTimes();
+    	expect(_externalContext.getRequestContextPath()).andReturn(contextPath);
+    	
+    	_mocksControl.replay();
+    	assertEquals(expectedActionUrl, support.calculateActionURL(_facesContext, viewId));
+    	_mocksControl.reset();
+    }
+
+    private DefaultViewHandlerSupport createdMockedViewHandlerSupport() throws Exception
+    {
+        Class<DefaultViewHandlerSupport> supportClass = DefaultViewHandlerSupport.class;
+        Class<?>[] parameterTypes = new Class[] { FacesContext.class };
 
+        DefaultViewHandlerSupport support = _mocksControl.createMock(
+            supportClass, new Method[] {
+                // the methods "getFacesServletMapping" and "getContextSuffix" will be mocked
+                supportClass.getDeclaredMethod("getFacesServletMapping", parameterTypes),
+                supportClass.getDeclaredMethod("getContextSuffix", parameterTypes) 
+            }
+        );
+
+        return support;
+    }
+    
+    /**
+     * Test method for
+     * {@link org.apache.myfaces.application.DefaultViewHandlerSupport#calculateFacesServletMapping(String, String)}.
+     */
+	public void testCalculateFacesServletMapping() throws Exception
+    {
+        assertExtensionMapping(".jsf", "/index.jsf", null);
+        assertExtensionMapping(".jsf", "/secure/login.jsf", null);
+
+        assertPathBasedMapping("/faces", "/faces", null);
+        assertPathBasedMapping("/faces", "/faces", "/index.jsp");
+        assertPathBasedMapping("/faces", "/faces", "/secure/login.jsp");
+    }
+
+    /**
+     * Convenience method that tests if the ViewHandlerSupport object knows that
+     * the "given request" has been handled by a FacesServlet being postfix
+     * mapped. Extract the path elements of a Request-URI according to the
+     * Servlet specification and pass the servletPath and pathInfo element.
+     * 
+     * @param extension
+     *            expected extension
+     * @param servletPath
+     *            servletPath of the "current request" (e.g. "/faces")
+     * @param pathInfo
+     *            <code>null</code>
+     */
+    private void assertExtensionMapping(
+            String extension, String servletPath, String pathInfo)
+    {
+		FacesServletMapping mapping = 
+		    DefaultViewHandlerSupport.calculateFacesServletMapping(servletPath, pathInfo);
+        assertTrue(mapping.isExtensionMapping());
+        assertEquals(extension, mapping.getExtension());
+    }
+	
+	/**
+     * Convenience method that tests if the ViewHandlerSupport object knows that
+     * the "given request" has been handled by a FacesServlet being prefix
+     * mapped. Extract the path elements of a Request-URI according to the
+     * Servlet specification and pass the servletPath and pathInfo element.
+     * 
+     * @param prefix
+     *            expected prefix
+     * @param servletPath
+     *            servletPath of the "current request" (e.g. "/faces")
+     * @param pathInfo
+     *            infoPath of the "current request" (e.g. "/login.jsp")
+     */
+    private void assertPathBasedMapping(
+            String prefix, String servletPath, String pathInfo)
+    {
+		FacesServletMapping mapping = 
+		    DefaultViewHandlerSupport.calculateFacesServletMapping(servletPath, pathInfo);
+        assertFalse(mapping.isExtensionMapping());
+        assertEquals(prefix, mapping.getPrefix());
+	}
+    
     /**
      * Test method for
      * {@link org.apache.myfaces.application.DefaultViewHandlerSupport#getContextSuffix(javax.faces.context.FacesContext)}.