/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 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.io.InputStream;
import java.net.URL;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.servlet.ServletRegistration;
/**
* <p class="changed_added_2_0">
* <span class="changed_modified_2_1 changed_modified_2_2 changed_modified_2_3">An</span> instance
* of <code>Resource</code> is a Java object representation of the artifact that is served up in
* response to a <i>resource request</i> from the client. Instances of <code>Resource</code> are
* normally created and initialized via calls to {@link ResourceHandler#createResource}. See the
* documentation for {@link ResourceHandler} for more information.
* </p>
*
* <div class="changed_added_2_0"> </div>
*
* @since 2.0
*/
public abstract class Resource extends ViewResource {
/**
* <p class="changed_added_2_0">
* This constant is used as the key in the component attribute map of a composite component to
* associate the component with its <code>Resource</code> instance. The value for this key is
* the actual <code>Resource</code> instance.
* </p>
*
*/
public static final String COMPONENT_RESOURCE_KEY = "javax.faces.application.Resource.ComponentResource";
private String contentType;
private String libraryName;
private String resourceName;
// ---------------------------------------------------------- Public Methods
/**
* <p class="changed_added_2_0">
* Return the MIME content-type for this resource.
* </p>
*
* @return the MIME content-type for this resource.
*/
public String getContentType() {
return contentType;
}
/**
*
* <p class="changed_added_2_0">
* Set the MIME content-type for this resource. The default implementation performs no
* validation on the argument.
* </p>
*
* @param contentType the MIME content-type for this resource. The default implementation must
* accept <code>null</code> as a parameter.
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* <p class="changed_added_2_0">
* Return the libraryName for this resource. May be <code>null</code>. The libraryName for a
* resource is an optional String that indicates membership in a "resource library". All
* resources with the same libraryName belong to the same "resource library". The "resource
* library" concept allows disambiguating resources that have the same resourceName. See
* {@link ResourceHandler} for more information.
* </p>
*
* @return Return the libraryName for this resource. May be <code>null</code>.
*/
public String getLibraryName() {
return libraryName;
}
/**
* <p class="changed_added_2_0">
* Set the libraryName for this resource.
* </p>
*
* @param libraryName the libraryName for this resource. The default implementation must accept
* <code>null</code> for the <em>libraryName</em>.
*/
public void setLibraryName(String libraryName) {
this.libraryName = libraryName;
}
/**
* <p class="changed_added_2_0">
* Return the resourceName for this resource. Will never be null. All <code>Resource</code>
* instances must have a resourceName.
* </p>
*
* @return Return the resourceName for this resource. Will never be null.
*/
public String getResourceName() {
return resourceName;
}
/**
* <p class="changed_added_2_0">
* Set the resourceName for this resource.
* </p>
*
* @param resourceName a non-null String.
*
* @throws NullPointerException if argument <code>resourceName</code> is null.
*/
public void setResourceName(String resourceName) {
if (resourceName == null) {
throw new NullPointerException("All resources must have a non-null resourceName.");
}
this.resourceName = resourceName;
}
/**
* <p class="changed_added_2_0">
* <span class="changed_modified_2_1">If</span> the current request is a resource request, (that
* is, {@link ResourceHandler#isResourceRequest} returns <code>true</code>), return an
* <code>InputStream</code> containing the bytes of the resource. Otherwise, throw an
* <code>IOException</code>.
* </p>
*
* @return an <code>InputStream</code> containing the bytes of the resource.
*
* <p class="changed_modified_2_1">
* Any EL expressions present in the resource must be evaluated before serving the bytes
* of the resource. Note that due to browser and server caching, EL expressions in a
* resource file will generally only be evaluated once, when the resource is first
* served up. Therefore, using EL expressions that refer to per-request data is not
* advisable since this data can become stale.
* </p>
*
* @throws IOException if the current request is not a resource request.
*/
public abstract InputStream getInputStream() throws IOException;
/**
* <p class="changed_added_2_0">
* Returns a mutable <code>Map<String, String></code> whose entries will be sent as
* response headers during {@link ResourceHandler#handleResourceRequest}. The entries in this
* map must not persist beyond the scope of a single request. Any modifications made to the map
* after the resource has been served will be ignored by the run-time.
* </p>
*
* @return a mutable <code>Map<String, String></code> of headers that will be included
* with the response.
*/
public abstract Map<String, String> getResponseHeaders();
/**
* <p class="changed_added_2_0">
* <span class="changed_modified_2_2 changed_modified_2_3">Return</span> a path to this resource
* such that, when the browser resolves it against the base URI for the view that includes the
* resource, and issues a GET request to the resultant fully qualified URL, the bytes of the
* resource are returned in response.
* </p>
*
* <div class="changed_added_2_0">
*
* <p>
* The default implementation must implement the following algorithm. For discussion, the return
* result from this method will be called <em>result</em>.
* </p>
*
* <ul>
*
* <li>
* <p>
* Get the context-root for this web application, not ending in slash. For discussion this will
* be called <em>contextRoot</em>.
* </p>
* </li>
*
* <li>
* <p class="changed_modified_2_3">
* Discover if the <code>FacesServlet</code> is prefix (path) mapped, extension mapped, or exact
* mapped (as defined by Servlet.12.2.) and the value of the mapping (including the leading '.'
* in the case of extension mapping). For discussion, this will be <em>facesServletMapping</em>.
* </p>
*
* <div class="changed_added_2_3">
* <p>
* If exact mapped, <em>result</em> must be the following if and only if the FacesServlet is
* mapped to the exact URL pattern {@link ResourceHandler#RESOURCE_IDENTIFIER} +
* {@link #getResourceName}
* </p>
*
* <blockquote>
* <p>
* <code>result = <em>contextRoot</em> + {@link
* ResourceHandler#RESOURCE_IDENTIFIER} + {@link #getResourceName}</code>
* </p>
* </blockquote>
*
* <p>
* If exact mapped, and the FacesServlet is <em>not</em> mapped to the exact URL pattern
* {@link ResourceHandler#RESOURCE_IDENTIFIER} + {@link #getResourceName} do the following:
* </p>
*
* <p>
* Retrieve the existing mappings of the FacesServlet, e.g. using
* {@link ServletRegistration#getMappings()}, and from those pick any prefix mapping or
* extension mapping. If no such mapping is found, throw an {@link IllegalStateException}. If
* such mapping is found remove the <code>*</code> character from that mapping, take that as the
* new <em>facesServletMapping</em> and continue with evaluating this mapping as specified below
* for <em>if prefix mapped</em> and for <em>if extension mapped</em> </div>
*
* <p>
* If prefix mapped, <em>result</em> must be
* </p>
*
* <blockquote>
* <p>
* <code>result = <em>contextRoot</em> + '/' +
* <em>facesServletMapping</em> + {@link
* ResourceHandler#RESOURCE_IDENTIFIER} + '/' + {@link
* #getResourceName}</code>
* </p>
* </blockquote>
*
* <p>
* If extension mapped, <em>result</em> must be
* </p>
*
* <blockquote>
* <p>
* <code>result = <em>contextRoot</em> + {@link
* ResourceHandler#RESOURCE_IDENTIFIER} + {@link #getResourceName} +
* <em>facesServletMapping</em></code>
* </p>
* </blockquote>
*
* </li>
*
* <li class="changed_modified_2_2">
* <p>
* Build up a string, called <em>resourceMetaData</em> which is an & separated string of
* name=value pairs suitable for inclusion in a URL query string.
* </p>
*
* <blockquote>
*
* <p>
* If {@link #getLibraryName} returns non-<code>null</code>, <code>resourceMetaData</code> must
* include "ln=" + the return from {@link #getLibraryName}
* </p>
*
* <p class="changed_added_2_2">
* If there is a <code>localePrefix</code> for this application, as defined in
* {@link ResourceHandler#LOCALE_PREFIX}, <code>resourceMetaData</code> must include "loc=" +
* the <code>localePrefix</code>.
* </p>
*
*
* <p class="changed_added_2_2">
* If this resource is contained in a resource library contract, <code>resourceMetaData</code>
* must include "con=" + the name of the resource library contract.
* </p>
*
* </blockquote>
*
* <p>
* Append "?" + <em>resourceMetaData</em> to <em>result</em>.
* </p>
*
* </li>
*
* <li>
* <p>
* Make it portlet safe by passing the result through {@link ViewHandler#getResourceURL}.
* </p>
* </li>
*
* </ul>
*
* </div>
*
* @return the path to this resource, intended to be included in the encoded view that is sent
* to the browser when sending a faces response.
*/
public abstract String getRequestPath();
/**
* <p class="changed_added_2_0">
* Return an actual <code>URL</code> instance that refers to this resource instance.
* </p>
*
* @return Return an actual <code>URL</code> instance that refers to this resource instance.
*/
@Override
public abstract URL getURL();
/**
* <p class="changed_added_2_0">
* Call through to {@link #getRequestPath} and return the result.
* </p>
*
* @return Call through to {@link #getRequestPath} and return the result.
*/
@Override
public String toString() {
return getRequestPath();
}
/**
* <p class="changed_added_2_0">
* <span class="changed_modified_2_2">Return</span> <code>true</code> if the user-agent
* requesting this resource needs an update. <span class="changed_added_2_2">If the
* {@code If-Modified-Since} HTTP header is available for this request, its value must be
* consulted, as specified in Section 14.25 of IETF RFC 2616, to determine the result.</span>
* Returns <code>false</code> if the user-agent does not need an update for this resource.
* </p>
*
* @param context the Faces context.
* @return <code>true</code> or <code>false</code> depending on whether or not the user-agent
* needs an update of this resource.
*/
public abstract boolean userAgentNeedsUpdate(FacesContext context);
}