/*
* Copyright 2017 OmniFaces
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
/**
* <p>
* This package contains the classes for the OmniFaces FacesViews feature.
*
* <h3>Introduction</h3>
*
* <p>
* FacesViews is a feature where a special dedicated directory (<code>/WEB-INF/faces-views</code>), or optionally one or
* more user specified directories, can be used to store Facelets source files.
*
* <p>
* All files found in these directories are automatically mapped as Facelets files and made available using both their
* original extension as well as without an extension (extensionless). Optionally scanning can be restricted to include
* only certain extensions.
*
* <p>
* With FacesViews, there is thus no need to list all Facelets views that should be accessed without an extension in
* some configuration file. Additionally, it thus automatically maps Facelets files to their original file extension,
* which prevents exposing the source code of those Facelets that happens with the default JSF mapping.
*
* <p>
* Scanning is done automatically and thus no further configuration is needed. The feature is compatible with
* applications that don't have <code>web.xml</code> or <code>faces-config.xml</code> configuration files. As such, it
* can be used as an alternative to declaring the {@link javax.faces.webapp.FacesServlet} in <code>web.xml</code> for
* the <code>.xhtml</code> to <code>.xhtml</code> mapping.
*
* <h4>Example 1:</h4>
*
* <p>
* Consider the following file structure and assume no further configuration has been done:
*
* <pre>
* /WEB-INF/faces-views/index.xhtml
* /WEB-INF/faces-views/users/add.xhtml
* /normal.xhtml
* </pre>
*
* <p>
* This will make the Facelets available via the following URLs
* (given a root deployment on domain <code>example.com</code>):
*
* <pre>
* example.com/index
* example.com/users/add
* example.com/index.xhtml (will redirect to /index by default)
* example.com/users/add.xhtml (will redirect to /users/add by default)
* example.com/normal.xhtml
* </pre>
*
* <p>
* Note that although the directory outside <code>/WEB-INF/faces-views</code> is not scanned, the
* {@link javax.faces.webapp.FacesServlet} <em>is</em> mapped on all extensions found in
* <code>/WEB-INF/faces-views</code>, so this will also affect files outside this directory. In the above example
* <code>normal.xhtml</code> is thus also available via the <code>.xhtml</code> extension, since the whole FacesServlet
* is mapped on this.
*
* <p>
* Also note that the extension variants of the scanned views will redirect to the extensionless variants. This behavior
* can be changed (see below), so that these views are either directly available (no redirect) or are not available at
* all.
*
* <h4>Example 2:</h4>
*
* <p>
* Consider the following <code>web.xml</code>:
*
* <pre>
* <context-param>
* <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name>
* <param-value>/*.xhtml</param-value>
* </context-param>
* </pre>
*
* <p>
* And this file structure:
*
* <pre>
* /page1.xhtml
* /foo/page2.xhtml
* /WEB-INF/resources/template.xhtml
* /script.js
* </pre>
*
* <p>
* This will make the Facelets available via the following URLs
* (given a root deployment on domain <code>example.com</code>):
*
* <pre>
* example.com/page1
* example.com/foo/page2
* example.com/page1.xhtml (will redirect to /page1 by default)
* example.com/foo/page2.xhtml (will redirect to /foo/page2 by default)
* </pre>
*
* <p>
* Note that in the above example, <code>/WEB-INF</code> was NOT scanned and thus <code>template.xhtml</code> is not
* made publicly available. Likewise <code>/script.js</code> was also not scanned since it doesn't have the configured
* extension (<code>.xhtml</code>). Finally, although a <code>web.xml</code> was used, there does not need to be a
* mapping for the <code>FacesServlet</code> in it.
*
* <h4>Example 3:</h4>
*
* <p>
* Consider the following <code>web.xml</code>:
*
* <pre>
* <context-param>
* <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name>
* <param-value>/*.xhtml/*</param-value>
* </context-param>
* </pre>
*
* <p>
* And this file structure:
*
* <pre>
* /page1.xhtml
* /foo/page2.xhtml
* </pre>
*
* <p>
* This will make the Facelets available via the following URLs
* (given a root deployment on domain <code>example.com</code>):
*
* <pre>
* example.com/page1
* example.com/foo/page2
* example.com/page1/foo/bar (will forward to /page1 with dynamic path parameters "foo" and "bar")
* example.com/foo/page2/bar (will forward to /foo/page2 with dynamic path parameter "bar")
* example.com/page1.xhtml (will redirect to /page1 by default)
* example.com/foo/page2.xhtml (will redirect to /foo/page2 by default)
* </pre>
*
* <p>
* The path parameters are injectable via <code>@</code>{@link org.omnifaces.cdi.Param} in the managed bean
* associated with the page. Below example shows how they are injected in the managed bean associated with /page1.xhtml.
*
* <pre>
* @Inject @Param(pathIndex=0)
* private String foo;
*
* @Inject @Param(pathIndex=1)
* private String bar;
* </pre>
*
* <p>
* The support for this feature was added in OmniFaces 2.5 and is not available in older versions.
*
*
* <h3>Welcome files</h3>
*
* <p>
* If a <code><welcome-file></code> is defined in <code>web.xml</code> that's scanned by FacesViews
* <strong>AND</strong> <code>REDIRECT_TO_EXTENSIONLESS</code> is used (which is the default, see below), it's necessary
* to define an extensionless welcome file to prevent a request to <code>/</code> being redirected to
* <code>/[welcome file]</code>. E.g. without this <code>http://example.com</code> will redirect to say
* <code>http://example.com/index</code>.
*
* <p>
* For example:
*
* <pre>
* <welcome-file-list>
* <welcome-file>index</welcome-file>
* </welcome-file-list>
* </pre>
*
* <h3>Dispatch methods</h3>
*
* <p>
* JSF normally inspects the request URI to derive a logical view id from it. It assumes the FacesServlet is either
* mapped on a prefix path or an extension, and will get confused when an extensionless "exactly mapped" request is
* encountered. To counter this, FacesViews makes use of a filter that intercepts each request and makes it appear to
* JSF that the request was a normal extension mapped one.
*
* <p>
* In order to do this dispatching, two methods are provided; forwarding, and wrapping the request and continuing the
* filter chain. For the last method to work, the FacesServlet is programmatically mapped to every individual resource
* (page/view) that is encountered. By default the filter is automatically registered and is inserted <b>after</b> all
* filters that are declared in <code>web.xml</code>.
*
* <p>
* These internal details are important for users to be aware of, since they greatly influence how extensionless
* requests interact with other filter based functionality such as security filters, compression filters, file upload
* filters, etc.
*
* <p>
* With the forwarding method, filters typically have to be set to dispatch type <code>FORWARD</code> as well. If the
* FacesViews filter is the first in the chain other filters that are set to dispatch type <code>REQUEST</code> will
* <strong>NOT</strong> be invoked at all (the chain is ended). If the FacesViews filter is set to be the last, other
* filters will be invoked, but they should not modify the response (a forward clears the response buffer till so far
* if not committed).
*
* <p>
* No such problems appear to exist when the FacesViews filter simply continues the filtering chain. However, since it
* wraps the requess there might be unforeseen problems with containers or other filters that get confused when the
* request URI changes in the middle of the chain. Continuing the chain has been tested with JBoss EAP 6.0.1, GlassFish
* 3.1.2.2, WebLogic 12.1.1 and TomEE 1.5.2-snapshot and thus with both Mojarra and MyFaces. However, since it's a new
* method for OmniFaces 1.4 we kept the existing forward as an alternative.
*
* <p>
* The configuration options below provide more details about the dispatch methods and the filter position which can be
* used for tweaking FacesViews for interoperability with other filters.
*
* <h3>Configuration</h3>
*
* <p>
* The following context parameters are available.
*
* <table summary="All available context parameters" border="1" cellspacing="0">
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_ENABLED_PARAM_NAME}</code></td>
* <td>Used to completely switch scanning off.
* <br>Allowed values: {<code>true</code>,<code>false</code>}
* <br>Default value: <code>true</code>
* <br>(note that if no <code>/WEB-INF/faces-views</code> directory is present and no explicit paths have been configured, no scanning will be done either)</td>
* </tr>
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCAN_PATHS_PARAM_NAME}</code></td>
* <td>A comma separated list of paths that are to be scanned in addition to <code>/WEB-INF/faces-views</code>.
* <br>Allowed values: any path relative to the web root, including the root path (<code>/</code>) and <code>/WEB-INF</code>.
* A wildcard can be added to the path, which will cause only files with the given extension te be scanned.
* <br>Examples:
* <br>- Scan all files in both folder1 and folder2: <code>/folder1, /folder2</code>
* <br>- Scan only .xhtml files in the root: <code>/*.xhtml</code>
* <br>Note that when the root path is given, all its sub paths are also scanned EXCEPT <code>WEB-INF</code>, <code>META-INF</code> and <code>resources</code>.
* If those have to be scanned as well, they can be added to the list of paths explicitly.
* <br>Default value: <code>/WEB-INF/faces-views</code> (note when this value is set, those paths will be in addition to the default <code>/WEB-INF/faces-views</code>)
* </td>
* </tr>
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCANNED_VIEWS_EXTENSIONLESS_PARAM_NAME}</code></td>
* <td>Used to set how scanned views should be rendered in JSF controlled links.
* With this setting set to <code>false</code>, it depends on whether the request URI uses an extension or not.
* If it doesn't, links are also rendered without one, otherwise they are rendered with an extension.
* When set to <code>true</code> links are always rendered without an extension.
* <br>Default value: <code>true</code>
* </td>
* </tr>
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_EXTENSION_ACTION_PARAM_NAME}</code></td>
* <td>Determines the action that is performed whenever a resource is requested WITH extension that's also available without an extension.
* <br>Allowed values are enumerated in {@link org.omnifaces.facesviews.ExtensionAction}, which have the following meaning:
* <br>- <code>REDIRECT_TO_EXTENSIONLESS</code>: Send a 301 (permanent) redirect to the same URL, but with the extension removed. E.g. <code>/foo.xhtml</code> redirects to <code>/foo</code>.
* <br>- <code>SEND_404</code>: Send a 404 (not found), makes it look like e.g. <code>/foo.xhtml</code> never existed and there's only <code>/foo</code>.
* <br>- <code>PROCEED</code>: No special action is taken. Both <code>/foo.xhtml</code> and <code>/foo</code> are processed as-if they were separate views (with same content).
* <br>Default value: <code>REDIRECT_TO_EXTENSIONLESS</code>
* </td>
* </tr>
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_PATH_ACTION_PARAM_NAME}</code></td>
* <td>Determines the action that is performed whenever a resource is requested in a public path that has been used for scanning views by faces views
* (e.g. the paths set by <code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_SCAN_PATHS_PARAM_NAME}</code>, but excluding the root path /).
* <br>Allowed values are enumerated in {@link org.omnifaces.facesviews.PathAction}, which have the following meaning:
* <br>- <code>SEND_404</code>: Send a 404 (not found), makes it look like e.g. <code>/path/foo.xhtml</code> never existed and there's only <code>/foo</code> and optionally <code>/foo.xhtml</code>.
* <br>- <code>REDIRECT_TO_SCANNED_EXTENSIONLESS</code>: Send a 301 (permanent) redirect to the resource corresponding with the one that was scanned. E.g. <code>/path/foo.xml</code> redirects to <code>/foo</code>.
* <br>- <code>PROCEED</code>: No special action is taken. <code>/path/foo.xml</code> and <code>/foo</code> (and optionally <code>/foo.xhtml</code>) will be accessible.
* <br>Default value: <code>SEND_404</code>
* </td>
* </tr>
*
* <tr>
* <td class="colFirst"><code>{@value org.omnifaces.facesviews.FacesViews#FACES_VIEWS_FILTER_AFTER_DECLARED_FILTERS_PARAM_NAME}</code></td>
* <td>Used to set whether the {@link org.omnifaces.facesviews.FacesViewsForwardingFilter} should match before declared filters (<code>false</code>) or
* after declared filters (<code>true</code>).
* <br>Default value: <code>false</code> (the FacesViews forwarding filter is the first in the filter chain)
* </td>
* </tr>
*
* </table>
*
* <h3>Servlet 2.5 compatibility</h3>
*
* <p>
* Since OmniFaces 2.0, Servlet 2.5 compatibility has been dropped. Servlet 2.5 users are advised to either upgrade to
* Servlet 3.0+, or keep using OmniFaces 1.x.
*
*
* <h3>OmniFaces 1.3 compatibility</h3>
*
* <p>
* In OmniFaces 1.4, a major overhaul was done for FacesViews and several things are done differently from how they were
* done in 1.3
*
* <p>
* Most notably is that the FacesServlet dispatch changed from forwarding to continuing the chain, the FacesViews filter
* moved from being the first in the chain to being the last, links are always rendered as their extensionless variant
* independent of the request using an extension or not, and when a request with an extension is used anyway (e.g. by
* typing it directly into the address bar) it's now redirected to the extensionless variant.
*
* <p>
* By putting the following settings in <code>web.xml</code> a behavior that most closely resembles 1.3 can be obtained:
*
* <pre>
* <context-param>
* <param-name>org.omnifaces.FACES_VIEWS_DISPATCH_METHOD</param-name>
* <param-value>FORWARD</param-value>
* </context-param>
* <context-param>
* <param-name>org.omnifaces.FACES_VIEWS_SCANNED_VIEWS_ALWAYS_EXTENSIONLESS</param-name>
* <param-value>false</param-value>
* </context-param>
* <context-param>
* <param-name>org.omnifaces.FACES_VIEWS_EXTENSION_ACTION</param-name>
* <param-value>PROCEED</param-value>
* </context-param>
* </pre>
*
*
* @author Arjan Tijms
*/
package org.omnifaces.facesviews;