All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.faces.application.ResourceHandler Maven / Gradle / Ivy

Go to download

This is the master POM file for Oracle's Implementation of the JSF 2.3 Specification.

There is a newer version: 2.3-pfd
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package javax.faces.application;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

import javax.faces.context.FacesContext;


/**
 * 

ResourceHandler is the run-time API by * which {@link javax.faces.component.UIComponent} and {@link * javax.faces.render.Renderer} instances, and the {@link * javax.faces.view.ViewDeclarationLanguage} can reference {@link * Resource} instances. An implementation of this class must be * thread-safe.

* *
* *

Packaging Resources

* *
* *

ResourceHandler defines a path based packaging convention for * resources. The default implementation of * ResourceHandler must support packaging resources in the * classpath or in the web application root. See section JSF.2.6.1 of the * spec prose document linked in the * overview summary for the normative specification of packaging * resources.

*

Briefly, The default implementation must support packaging * resources in the web application root under the path

* *

resources/<resourceIdentifier>

* *

relative to the web app root. "resources" is the default location, but * this location can be changed by the value of the {@link * #WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} * <context-param>.

* *

For the default implementation, resources packaged in the * classpath must reside under the JAR entry name

*

META-INF/resources/<resourceIdentifier>

*
*

In the case of Faces Flows packaged * within jar files, resources packaged in the classpath must reside * under the jar entry name

*

META-INF/flows/<resourceIdentifier>

*
*

<resourceIdentifier> consists of several * segments, specified as follows.

*

[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]

*

None of the segments in the * resourceIdentifier may be relative paths, such as * ‘../otherLibraryName’. The implementation is not * required to support the libraryVersion and * resourceVersion segments for the JAR packaging case.

*

Note that resourceName is the only required segment.

* *
* *

Encoding Resources

* *
* *

During the handling of view requests, the JSF run-time may be * called upon to encode a resource in such a way as to instruct the * user-agent to make a subsequent resource request. This behavior is * orchestrated by one of the resource renderers * (ScriptRenderer, StylesheetRenderer, * ImageRenderer), which all call {@link Resource#getRequestPath} * to obtain the encoded URI for the resource. See {@link * Resource#getRequestPath} and the Standard HTML RenderKit specification for * the complete specification.

*

This usage of resources does not apply * for resources that correspond to VDL resources.

* *
* *

Decoding Resources

* *
* *

During the handling of resource requests, the JSF run-time will * be called upon to decode a resource in such a way as to serve up * the bytes of the resource to the user-agent. This behavior is * orchestrated by {@link #handleResourceRequest}, which calls {@link * Resource#getInputStream} to obtain bytes of the resource. See * {@link #handleResourceRequest} for the complete specification.

*

This usage of resources does not apply * for resources that correspond to VDL resources.

*
* *
* * @since 2.0 */ public abstract class ResourceHandler { /** *

{@link Resource#getRequestPath} returns the * value of this constant as the prefix of the URI. {@link * #handleResourceRequest(javax.faces.context.FacesContext)} looks for the value of this constant * within the request URI to determine if the request is a resource * request or a view request.

*/ public static final String RESOURCE_IDENTIFIER = "/javax.faces.resource"; /** *

* Resource name of JSF script resource. *

* * @since 2.3 */ public static final String JSF_SCRIPT_RESOURCE_NAME = "jsf.js"; /** *

* Library name of JSF script resource. *

* * @since 2.3 */ public static final String JSF_SCRIPT_LIBRARY_NAME = "javax.faces"; /** *

This file must * be located in * META-INF/contracts/<contractName>/ in a jar * file that contains a resource library contract, where * <contractName> is the name of the contract. If * the jar file contains multiple contracts, the marker file must be * present in each one. See “constant field values” for * the name of the file that must be placed at that location.

* @since 2.2 */ public static final String RESOURCE_CONTRACT_XML = "javax.faces.contract.xml"; /** *

If a * <context-param> with the param name equal to * the value of {@link #WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} * exists, the runtime must interpret its value as a path, relative * to the web app root, where resources are to be located. This * param value must not start with a "/", though it may contain "/" * characters. If no such <context-param> exists, or * its value is invalid, the value "resources", without the quotes, * must be used by the runtime as the value.

* * @since 2.2 */ public static final String WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME = "javax.faces.WEBAPP_RESOURCES_DIRECTORY"; /** *

If a * <context-param> with the param name equal to * the value of {@link #WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME} * exists, the runtime must interpret its value as a path, relative * to the web app root, where resource library contracts are to be located. This * param value must not start with a "/", though it may contain "/" * characters. If no such <context-param> exists, or * its value is invalid, the value "contracts", without the quotes, * must be used by the runtime as the value.

* * @since 2.2 */ public static final String WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME = "javax.faces.WEBAPP_CONTRACTS_DIRECTORY"; /** *

The name of a key within the * application message bundle named by the return from {@link * Application#getMessageBundle} whose value is the locale prefix * used to find a packaged resource to return from {@link * #createResource} (or one of its variants). */ public static final String LOCALE_PREFIX = "javax.faces.resource.localePrefix"; /** *

The ServletContext init * parameter consulted by the {@link #handleResourceRequest} to tell * which kinds of resources must never be served up in response to a * resource request. The value of this parameter is a single space * separated list of file extensions, including the leading '.' * character (without the quotes). If not specified, the default * value given in the value of the {@link * #RESOURCE_EXCLUDES_DEFAULT_VALUE} constant is used. If manually * specified, the given value entirely overrides the default one and * does not supplement it.

*/ public static final String RESOURCE_EXCLUDES_PARAM_NAME = "javax.faces.RESOURCE_EXCLUDES"; /** *

The default value for the {@link * #RESOURCE_EXCLUDES_PARAM_NAME} init param.

*/ public static final String RESOURCE_EXCLUDES_DEFAULT_VALUE = ".class .jsp .jspx .properties .xhtml .groovy"; // ---------------------------------------------------------- Public Methods /** *

Create an instance of * ViewResource given the argument * resourceName. The content-type of the resource is * derived by passing the resourceName to {@link * javax.faces.context.ExternalContext#getMimeType}

*
*

The algorithm specified in section JSF.2.6.1.4 of the spec * prose document linked in * the overview summary must be executed to create the * Resource. New * requirements were introduced in version 2.2 of the specification. * For historical reasons, this method operate correctly when the * argument {@code resourceName} is of the form * {@code libraryName/resourceName}, even when {@code resourceName} * contains '/' characters.

*
* @param resourceName the name of the resource. * * @throws NullPointerException if resourceName is * null. * * @return a newly created Resource instance, suitable * for use in encoding or decoding the named resource. */ public abstract Resource createResource(String resourceName); /** *

Create an instance of Resource * given the argument resourceName, which may contain "/" * characters. The {@link javax.faces.view.ViewDeclarationLanguage} calls * this method when it needs to load a view from a persistent store, such as * a filesystem. This method is functionality equivalent to * {@link #createResource(java.lang.String)}, but all callsites that need * to load VDL views must use this method so that classes that want to * decorate the ResourceHandler in order to only affect the * loading of views may do so without affecting the processing of other * kinds of resources, such as scripts and stylesheets. * A {@link javax.faces.context.FacesContext} must be present * before calling this method. To preserve compatibility with prior revisions of the * specification, a default implementation must be provided that calls * {@link #createResource(java.lang.String)}.

* *
* *

The default implementation must look for the resource in the * following places, in this order.

* *
    * *
  • Considering resource library contracts (at the locations * specified in the spec prose document section Resource Library * Contracts in the Request Processing Lifecycle * chapter).

  • * *
  • Considering the web app root.

  • * *
  • Considering faces flows (at the locations specified in * the spec prose document section Faces Flows in the * Using JSF in Web Applications chapter).

  • * *
* *

Call {@link FacesContext#getResourceLibraryContracts}. If the * result is non-{@code null} and not empty, for each value in the * list, treat the value as the name of a resource library contract. * If the argument {@code resoureName} exists as a resource in the * resource library contract, return it. Otherwise, return the * resource (not in the resource library contract), if found. * Otherwise, return {@code null}.

*
* * @param context the {@link FacesContext} for this request. * @param resourceName the name of the resource to be interpreted as a view * by the {@link javax.faces.view.ViewDeclarationLanguage}. * * @throws NullPointerException if resourceName is * {@code null}. * * @return a newly created {@link ViewResource} instance, suitable * for use by the {@link javax.faces.view.ViewDeclarationLanguage}. * * @since 2.2 */ public ViewResource createViewResource(FacesContext context, String resourceName) { return context.getApplication().getResourceHandler().createResource(resourceName); } /** *

* Return a {@code Stream} possibly lazily populated by walking the resource tree * rooted at a given initial path. The resource tree is traversed breadth-first, * the elements in the stream are view resource names that would yield a {@code ViewResource} when * passed into {@link ResourceHandler#createViewResource} as the {@code resourceName} parameter. *

* *

* The {@code maxDepth} parameter is the maximum depth of directory levels to visit * beyond the initial path, which is always visited. The value is relative to the root * ({@code /}), not to the given initial path. E.g. given {@code maxDepth} = {@code 3} and initial * path {@code /foo/}, visiting will proceed up to {@code /foo/bar/}, where {@code /} counts as depth * {@code 1}, {@code /foo/} as depth {@code 2} and {@code /foo/bar/} as depth {@code 3}. * A value lower or equal to the depth of the initial path means that only the initial path * is visited. A value of {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all * levels should be visited. * * @param facesContext The {@link FacesContext} for this request. * @param path The initial path from which to start looking for view resources * @param maxDepth The absolute maximum depth of nested directories to visit counted from the root ({@code /}). * @param options The options to influence the traversal. See {@link ResourceVisitOption} for details on those. * * @return the {@link Stream} of view resource names * * @since 2.3 */ public Stream getViewResources(FacesContext facesContext, String path, int maxDepth, ResourceVisitOption... options) { return Stream.empty(); } /** *

* Return a {@code Stream} possibly lazily populated by walking the resource tree * rooted at a given initial path. The resource tree is traversed breadth-first, * the elements in the stream are view resource names that would yield a {@code ViewResource} when * passed into {@link ResourceHandler#createViewResource} as the {@code resourceName} parameter. *

* *

* This method works as if invoking it were equivalent to evaluating the expression: *

     * getViewResources(facesContext, start, Integer.MAX_VALUE, options)
     * 
* Put differently, it visits all levels of the resource tree. * * @param facesContext The {@link FacesContext} for this request. * @param path The initial path from which to start looking for view resources * @param options The options to influence the traversal. See {@link ResourceVisitOption} for details on those. * * @return the {@link Stream} of view resource names * * @since 2.3 */ public Stream getViewResources(FacesContext facesContext, String path, ResourceVisitOption... options) { return Stream.empty(); } /** *

Create an instance of * Resource given the argument * resourceId. The content-type of the resource is * derived by passing the resourceName to {@link * javax.faces.context.ExternalContext#getMimeType}

* *
* *

The resource must be identified according to the specification * in JSF.2.6.1.3 of the spec prose document linked in * the overview summary. New requirements were introduced in * version 2.2 of the specification.

* *
* * @param resourceId the resource identifier of the resource. * * @throws NullPointerException if resourceId is * null. * * @return a newly created Resource instance, suitable * for use in encoding or decoding the named resource. * * @since 2.2 */ public Resource createResourceFromId(String resourceId) { return null; } /** *

Create an instance of * Resource with a resourceName given by the value of * the argument resourceName that is a member of the * library named by the argument libraryName. The * content-type of the resource is derived by passing the * resourceName to {@link * javax.faces.context.ExternalContext#getMimeType}.

* *
* *

The algorithm specified in section JSF.2.6.1.4 of the spec * prose document linked in * the overview summary must be executed to create the * Resource. New * requirements were introduced in version 2.2 of the * specification.

* *
* * @param resourceName the name of the resource. * * @param libraryOrContractName the * name of the library (or contract) in which this resource * resides, may be null. If there is a conflict between * the name of a resource library and a resource library contract, * the resource library takes precedence. May not include relative * paths, such as "../". * * @throws NullPointerException if * resourceName is null * * @return a newly created Resource instance, suitable * for use in encoding or decoding the named resource. */ public abstract Resource createResource(String resourceName, String libraryOrContractName); /** *

Create an instance of * Resource with a resourceName given by the * value of the argument resourceName that is a member * of the library named by the argument libraryName * that claims to have the content-type given by the argument * content-type.

* *
* *

The algorithm specified in section JSF.2.6.1.4 of the spec * prose document linked in * the overview summary must be executed to create the * Resource. New * requirements were introduced in version 2.2 of the * specification.

* *
* * @param resourceName the name of the resource. * * @param libraryName the name of the library in which this resource * resides, may be null. May not include relative * paths, such as "../". * * @param contentType the mime content that this * Resource instance will return from {@link * Resource#getContentType}. If the value is null, The * content-type of the resource is derived by passing the * resourceName to {@link * javax.faces.context.ExternalContext#getMimeType} * * @throws NullPointerException if * resourceName is null. * * @return a newly created Resource instance, suitable * for use in encoding or decoding the named resource. */ public abstract Resource createResource(String resourceName, String libraryName, String contentType); /** *

Return true if * the resource library named by the argument * libraryName can be found. If there is a localePrefix * for this application, as defined in {@link #LOCALE_PREFIX}, first * look for the library with the prefix. If no such library is * found, look for the library without the prefix. This allows * developers to avoid duplication of files. For example, consider * the case where the developer wants to have a resource library * containing a localized image resource and a non-localized script * resource. By checking both locations for the existence of the * library, along with other spec changes in section 2.6.1.4, this * scenario is enabled.

* * @param libraryName the library name. * @return true if the library exists, false otherwise. * @since 2.0 * */ public abstract boolean libraryExists(String libraryName); /** *

This method specifies the contract * for satisfying resource requests. This method is called from * {@link javax.faces.webapp.FacesServlet#service} after that method * determines the current request is a resource request by calling * {@link #isResourceRequest}. Thus, handleResourceRequest * may assume that the current request is a resource request.

* *
* *

The default implementation must implement an algorithm * semantically identical to the following algorithm.

* * For discussion, in all cases when a status code is to be set, * this spec talks only using the Servlet API, but it is understood * that in a portlet environment the appropriate equivalent API must * be used. * *
    * *
  • If the resourceIdentifier ends with any of the * extensions listed in the value of the {@link * #RESOURCE_EXCLUDES_PARAM_NAME} init parameter, * HttpServletRequest.SC_NOT_FOUND must be passed to * HttpServletResponse.setStatus(), then * handleResourceRequest must immediately return.

  • * *
  • Extract the resourceName from the * resourceIdentifier by taking the substring of * resourceIdentifier that starts at {@link * #RESOURCE_IDENTIFIER}.length() + 1 and goes to the end of * resourceIdentifier. If no resourceName can be * extracted, HttpServletRequest.SC_NOT_FOUND must be * passed to HttpServletResponse.setStatus(), then * handleResourceRequest must immediately return.

  • * *
  • Extract the libraryName from the request by * looking in the request parameter map for an entry under the key * "ln", without the quotes. If found, use its value as the * libraryName.

  • * *
  • If resourceName and libraryName are * present, call {@link #createResource(String, String)} to create * the Resource. If only resourceName is * present, call {@link #createResource(String)} to create the * Resource. If the Resource cannot be * successfully created, * HttpServletRequest.SC_NOT_FOUND must be passed to * HttpServletResponse.setStatus(), then * handleResourceRequest must immediately return.

  • * *
  • Call {@link Resource#userAgentNeedsUpdate}. If this * method returns false, * HttpServletRequest.SC_NOT_MODIFIED must be passed to * HttpServletResponse.setStatus(), then * handleResourceRequest must immediately return.

  • * *
  • Pass the result of {@link Resource#getContentType} to * HttpServletResponse.setContentType.

  • * *
  • Call {@link Resource#getResponseHeaders}. For each entry * in this Map, call * HttpServletResponse.setHeader(), passing the key as * the first argument and the value as the second argument.

  • * *
  • Call {@link Resource#getInputStream} and serve up the * bytes of the resource to the response.

  • * *
  • Call HttpServletResponse.setContentLength() * passing the byte count of the resource.

  • * *
  • If an IOException is thrown during any of the * previous steps, log a descriptive, localized message, including * the resourceName and libraryName (if present). * Then, HttpServletRequest.SC_NOT_FOUND must be passed * to HttpServletResponse.setStatus(), then * handleResourceRequest must immediately return.

  • * *
  • In all cases in this method, any streams, channels, * sockets, or any other IO resources must be closed before this * method returns.

  • * *
* *
* * @param context the {@link javax.faces.context.FacesContext} for this * request * @throws IOException when an I/O error occurs. */ public abstract void handleResourceRequest(FacesContext context) throws IOException; /** *

Return true if the * current request is a resource request. This method is called by * {@link javax.faces.webapp.FacesServlet#service} to determine if * this request is a view request or a resource * request.

* * @param context the {@link javax.faces.context.FacesContext} for this * request * @return true if the current request is a resource * request, false otherwise. */ public abstract boolean isResourceRequest(FacesContext context); /** *

Return {@code true} if the argument {@code url} * contains the string given by the value of the constant * {@link ResourceHandler#RESOURCE_IDENTIFIER}, false otherwise.

* * @param url the url to inspect for the presence of {@link ResourceHandler#RESOURCE_IDENTIFIER}. * @return true if this is a resource URL, false otherwise. * @throws NullPointerException if the argument url is {@code null}. */ public boolean isResourceURL(String url) { boolean result = false; if (null == url) { throw new NullPointerException("null url"); } result = url.contains(RESOURCE_IDENTIFIER); return result; } /** *

Return the renderer-type for a * {@link javax.faces.render.Renderer} that is capable of rendering this * resource. The default implementation must return values according to the * following table. If no renderer-type can be determined, * null must be returned.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
resource name to renderer-type mapping
example resource namerenderer-type
mycomponent.jsjavax.faces.resource.Script
mystyle.cssjavax.faces.resource.Stylesheet
* * @param resourceName the resource name. * @return the renderer type. */ public abstract String getRendererTypeForResourceName(String resourceName); /** *

* Mark the resource as identified by given resource and library name as rendered. The default implementation must * ensure that {@link #isResourceRendered(FacesContext, String, String)} will return true when the * resource has already been rendered during the render response phase of the current view. *

* @param context The {@link FacesContext} for this request. * @param resourceName The name of the resource. * @param libraryName The name of the library in which the resource resides, may be null. * @since 2.3 */ @SuppressWarnings("unchecked") public void markResourceRendered(FacesContext context, String resourceName, String libraryName) { String resourceIdentifier = libraryName + ":" + resourceName; Set resourceIdentifiers = (Set) context.getAttributes().computeIfAbsent(RESOURCE_IDENTIFIER, k -> new HashSet<>()); resourceIdentifiers.add(resourceIdentifier); } /** *

* Returns whether the resource as identified by given resource and library name has been rendered. The default * implementation must during the render response phase of the current view return true when the * resource has been marked as rendered via {@link #markResourceRendered(FacesContext, String, String)}. *

* @param context The {@link FacesContext} for this request. * @param resourceName The name of the resource. * @param libraryName The name of the library in which this resource resides, may be null. * @return Whether the resource as identified by given resource and library name has been rendered. * @since 2.3 */ @SuppressWarnings("unchecked") public boolean isResourceRendered(FacesContext context, String resourceName, String libraryName) { String resourceIdentifier = libraryName + ":" + resourceName; Set resourceIdentifiers = (Set) context.getAttributes().get(RESOURCE_IDENTIFIER); return resourceIdentifiers != null && resourceIdentifiers.contains(resourceIdentifier); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy