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

org.omnifaces.resourcehandler.CDNResourceHandler Maven / Gradle / Ivy

There is a newer version: 4.4.1
Show newest version
/*
 * Copyright 2012 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.
 */
package org.omnifaces.resourcehandler;

import static org.omnifaces.util.Faces.evaluateExpressionGet;
import static org.omnifaces.util.Faces.getInitParameter;
import static org.omnifaces.util.Utils.isEmpty;

import java.util.HashMap;
import java.util.Map;

import javax.faces.application.Resource;
import javax.faces.application.ResourceDependency;
import javax.faces.application.ResourceHandler;

/**
 * 

* This {@link ResourceHandler} implementation allows the developer to provide external (CDN) URLs instead of the * default local URLs for JSF resources. This also works on auto-included resources provided as * {@link ResourceDependency} by the JSF implementation and/or component libraries. For example, JSF's own * javax.faces:jsf.js resource or PrimeFaces' primefaces:jquery/jquery.js resource could be * pointed to a CDN. *

* For non-JSF resources, you can just keep using plain HTML <script> and <link> * elements referring the external URL. * *

Installation

*

* To get it to run, this handler needs be registered as follows in faces-config.xml: *

 * <application>
 *     <resource-handler>org.omnifaces.resourcehandler.CDNResourceHandler</resource-handler>
 * </application>
 * 
* *

Standard configuration

*

* To configure the CDN URLs, a {@value org.omnifaces.resourcehandler.CDNResourceHandler#PARAM_NAME_CDN_RESOURCES} * context parameter has to be provided wherein the CDN resources are been specified as a comma separated string of * libraryName:resourceName=http://cdn.example.com/url key=value pairs. The key represents the default * JSF resource identifier and the value represents the full CDN URL, including the scheme. The CDN URL is not validated * by this resource handler, so you need to make absolutely sure yourself that it is valid. Here's an example: *

 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
 *     <param-value>
 *         js/script1.js=http://cdn.example.com/js/script1.js,
 *         somelib:js/script2.js=http://cdn.example.com/somelib/js/script2.js,
 *         otherlib:style.css=http://cdn.example.com/otherlib/style.css,
 *         somelib:images/logo.png=http://cdn.example.com/somelib/logo.png
 *     </param-value>
 * </context-param>
 * 
*

* With the above configuration, the following resources: *

 * <h:outputScript name="js/script1.js" />
 * <h:outputScript library="somelib" name="js/script2.js" />
 * <h:outputStylesheet library="otherlib" name="style.css" />
 * <h:graphicImage library="somelib" name="images/logo.png" />
 * 
*

* Will be rendered as: *

 * <script type="text/javascript" src="http://cdn.example.com/js/script1.js"></script>
 * <script type="text/javascript" src="http://cdn.example.com/somelib/js/script2.js"></script>
 * <link type="text/css" rel="stylesheet" href="http://cdn.example.com/otherlib/style.css" />
 * <img src="http://cdn.example.com/logo.png" />
 * 
* *

Wildcard configuration

*

* You can also use the wildcard syntax to map every single resource of a specific library to a common CDN URL. To * achieve that, just use * as the sole resource name and make sure that the CDN URL ends with * /*. Here's an example: *

 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
 *     <param-value>jquery-cdn:*=http://code.jquery.com/*</param-value>
 * </context-param>
 * 
* With the above configuration, the following resources: *
 * <h:outputScript library="jquery-cdn" name="jquery-1.9.1.js" />
 * <h:outputScript library="jquery-cdn" name="ui/1.10.3/jquery-ui.js" />
 * 
*

* Will be rendered as: *

 * <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
 * <script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
 * 
* *

EL expressions

*

The CDN resource handler supports evaluating EL expessions in the CDN URL. Here's an example:

*
 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
 *     <param-value>jquery-cdn:*=http://#{settings.jqueryCDN}/*</param-value>
 * </context-param>
 * 
*

The EL expression is resolved on a per-request basis.

* *

Conditionally disable CDN resource handler

*

* If you'd like to supply a context parameter which conditionally disables the CDN resource handler, then set the * context parameter {@value org.omnifaces.resourcehandler.CDNResourceHandler#PARAM_NAME_CDN_DISABLED} accordingly. *

 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_DISABLED</param-name>
 *     <param-value>true</param-value>
 * </context-param>
 * <!-- or -->
 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_DISABLED</param-name>
 *     <param-value>#{facesContext.application.projectStage eq 'Development'}</param-value>
 * </context-param>
 * <!-- or -->
 * <context-param>
 *     <param-name>org.omnifaces.CDN_RESOURCE_HANDLER_DISABLED</param-name>
 *     <param-value>#{someBean.someBooleanProperty}</param-value>
 * </context-param>
 * 
*

The EL expression is resolved on a per-request basis.

* *

CombinedResourceHandler

*

* If you're also using the {@link CombinedResourceHandler}, then you need to understand that CDN resources can * simply not be combined, as that would defeat the CDN purpose. The {@link CombinedResourceHandler} will therefore * automatically exclude all CDN resources from combining. * * @author Bauke Scholtz * @since 1.2 * @see RemappedResource * @see DefaultResourceHandler */ public class CDNResourceHandler extends DefaultResourceHandler { // Constants ------------------------------------------------------------------------------------------------------ /** The context parameter name to specify CDN URLs for the given resource identifiers. */ public static final String PARAM_NAME_CDN_RESOURCES = "org.omnifaces.CDN_RESOURCE_HANDLER_URLS"; /** The context parameter name to conditionally disable CDN resource handler. @since 2.0 */ public static final String PARAM_NAME_CDN_DISABLED = "org.omnifaces.CDN_RESOURCE_HANDLER_DISABLED"; private static final String ERROR_MISSING_INIT_PARAM = "Context parameter '" + PARAM_NAME_CDN_RESOURCES + "' is missing in web.xml or web-fragment.xml."; private static final String ERROR_INVALID_INIT_PARAM = "Context parameter '" + PARAM_NAME_CDN_RESOURCES + "' is in invalid syntax." + " It must follow 'resourceId=URL,resourceId=URL,resourceId=URL' syntax."; private static final String ERROR_INVALID_WILDCARD = "Context parameter '" + PARAM_NAME_CDN_RESOURCES + "' is in invalid syntax." + " Wildcard can only represent entire resource name '*' and URL suffix '/*' as in" + " 'libraryName:*=http://cdn.example.com/*'."; // Properties ----------------------------------------------------------------------------------------------------- private String disabledParam; private Map cdnResources; // Constructors --------------------------------------------------------------------------------------------------- /** * Creates a new instance of this CDN resource handler which wraps the given resource handler. The CDN resources * will be initialized based on the {@value org.omnifaces.resourcehandler.CDNResourceHandler#PARAM_NAME_CDN_RESOURCES} * context parameter. * @param wrapped The resource handler to be wrapped. * @throws IllegalArgumentException When the context parameter is missing or is in invalid format. */ public CDNResourceHandler(ResourceHandler wrapped) { super(wrapped); disabledParam = getInitParameter(PARAM_NAME_CDN_DISABLED); cdnResources = initCDNResources(); if (cdnResources == null) { throw new IllegalArgumentException(ERROR_MISSING_INIT_PARAM); } } // Actions -------------------------------------------------------------------------------------------------------- /** * If the given resource is not null and the CDN resource handler is not (conditionally) disabled for * the current request, then the CDN resources will be consulted if any CDN URL is available for the given resource. * If there is none, then just return the JSF default resource, otherwise return a wrapped resource whose * {@link Resource#getRequestPath()} returns the CDN URL as is been set in the * {@value org.omnifaces.resourcehandler.CDNResourceHandler#PARAM_NAME_CDN_RESOURCES} context parameter. */ @Override public Resource decorateResource(Resource resource) { if (resource == null || (disabledParam != null && Boolean.valueOf(String.valueOf(evaluateExpressionGet(disabledParam))))) { return resource; } String requestPath = null; if (cdnResources != null) { String libraryName = resource.getLibraryName(); String resourceName = resource.getResourceName(); requestPath = cdnResources.get(new ResourceIdentifier(libraryName, resourceName)); if (requestPath == null) { requestPath = cdnResources.get(new ResourceIdentifier(libraryName, "*")); if (requestPath != null) { requestPath = requestPath.substring(0, requestPath.length() - 1) + resourceName; } } } if (requestPath == null) { return resource; } String evaluatedRequestPath = evaluateExpressionGet(requestPath); return new RemappedResource(resource, evaluatedRequestPath); } // Helpers -------------------------------------------------------------------------------------------------------- /** * Initialize the CDN resources. * @return The CDN resources, or null if the context parameter has not been set. * @throws IllegalArgumentException When the context parameter value is in invalid format. */ static Map initCDNResources() { String cdnResourcesParam = getInitParameter(PARAM_NAME_CDN_RESOURCES); if (isEmpty(cdnResourcesParam)) { return null; } Map cdnResources = new HashMap(); for (String cdnResource : cdnResourcesParam.split("\\s*,\\s*")) { String[] cdnResourceIdAndURL = cdnResource.split("\\s*=\\s*", 2); if (cdnResourceIdAndURL.length != 2) { throw new IllegalArgumentException(ERROR_INVALID_INIT_PARAM); } ResourceIdentifier id = new ResourceIdentifier(cdnResourceIdAndURL[0]); if (id.getName().contains("*") && (!id.getName().equals("*") || !cdnResourceIdAndURL[1].endsWith("/*"))) { throw new IllegalArgumentException(ERROR_INVALID_WILDCARD); } cdnResources.put(id, cdnResourceIdAndURL[1]); } return cdnResources; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy