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

org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader Maven / Gradle / Ivy

Go to download

JSF components and utilities that can be used with any JSF implementation. This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to offer some additional benefits.

There is a newer version: 1.1.14
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.myfaces.renderkit.html.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.shared_tomahawk.util.ClassUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.ResourceBundle;
import java.net.HttpURLConnection;

/**
 * A ResourceLoader capable of fetching resources from the classpath,
 * but only for classes under package org.apache.myfaces.custom.
 *
 * @author Mathias Broekelmann (latest modification by $Author$)
 * @version $Revision$ $Date$
 */
public class MyFacesResourceLoader implements ResourceLoader
{
    protected static final Log log = LogFactory.getLog(MyFacesResourceLoader.class);

    static final String ORG_APACHE_MYFACES_CUSTOM = "org.apache.myfaces.custom";

    private static long lastModified = 0;

    /**
     * Get the last-modified time of the resource.
     * 

* Unfortunately this is not possible with files inside jars. Instead, the * MyFaces build process ensures that there is a file AddResource.properties * which has the datestamp of the time the build process was run. This method * simply gets that value and returns it. *

* Note that this method is not related to the generation of "cache key" * values by the AddResource class, nor does it affect the caching behaviour * of web browsers. This value simply goes into the http headers as the * last-modified time of the specified resource. */ private static long getLastModified() { if (lastModified == 0) { final String format = "yyyy-MM-dd HH:mm:ss Z"; // Must match the one used in the build file final String bundleName = AddResource.class.getName(); ResourceBundle resources = ResourceBundle.getBundle(bundleName); String sLastModified = resources.getString("lastModified"); try { lastModified = new SimpleDateFormat(format).parse(sLastModified).getTime(); } catch (ParseException e) { lastModified = new Date().getTime(); log.warn("Unparsable lastModified : " + sLastModified); } } return lastModified; } /** * Given a URI of form "{partial.class.name}/{resourceName}", locate the * specified file within the current classpath and write it to the * response object. *

* The partial class name has "org.apache.myfaces.custom." prepended * to it to form the fully qualified classname. This class object is * loaded, and Class.getResourceAsStream is called on it, passing * a uri of "resource/" + {resourceName}. *

* The data written to the response stream includes http headers * which define the mime content-type; this is deduced from the * filename suffix of the resource. *

* @see org.apache.myfaces.renderkit.html.util.ResourceLoader#serveResource(javax.servlet.ServletContext, * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) */ public void serveResource(ServletContext context, HttpServletRequest request, HttpServletResponse response, String resourceUri) throws IOException { String[] uriParts = resourceUri.split("/", 2); String component = uriParts[0]; if (component == null || component.trim().length() == 0) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid request"); log.error("Could not find parameter for component to load a resource."); return; } Class componentClass; String className = ORG_APACHE_MYFACES_CUSTOM + "." + component; try { componentClass = loadComponentClass(className); } catch (ClassNotFoundException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); log.error("Could not find the class for component " + className + " to load a resource."); return; } String resource = uriParts[1]; if (resource == null || resource.trim().length() == 0) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No resource defined"); log.error("No resource defined component class " + className); return; } InputStream is = null; try { // is = componentClass.getResourceAsStream(resource); //if (is == null) ResourceProvider resourceProvider; if (ResourceProvider.class.isAssignableFrom(componentClass)) { try { resourceProvider = (ResourceProvider) componentClass.newInstance(); } catch (InstantiationException e) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Unable to instantiate resource provider for resource " + resource + " for component " + component); log.error("Unable to instantiate resource provider for resource " + resource + " for component " + component, e); return; } catch (IllegalAccessException e) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Unable to instantiate resource provider for resource " + resource + " for component " + component); log.error("Unable to instantiate resource provider for resource " + resource + " for component " + component, e); return; } } else { resourceProvider = new DefaultResourceProvider(componentClass); } if (!resourceProvider.exists(context, resource)) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Unable to find resource " + resource + " for component " + component + ". Check that this file is available " + "in the classpath in sub-directory " + "/resource of the package-directory."); log.error("Unable to find resource " + resource + " for component " + component + ". Check that this file is available " + "in the classpath in sub-directory " + "/resource of the package-directory."); } else { // URLConnection con = url.openConnection(); long lastModified = resourceProvider.getLastModified(context, resource); if (lastModified < 1) { // fallback lastModified = getLastModified(); } long browserDate = request.getDateHeader("If-Modified-Since"); if (browserDate > -1) { // normalize to seconds - this should work with any os lastModified = (lastModified / 1000) * 1000; browserDate = (browserDate / 1000) * 1000; if (lastModified == browserDate) { // the browser already has the correct version response.setStatus(HttpURLConnection.HTTP_NOT_MODIFIED); return; } } int contentLength = resourceProvider.getContentLength(context, resource); String contentEncoding = resourceProvider.getEncoding(context, resource); is = resourceProvider.getInputStream(context, resource); defineContentHeaders(request, response, resource, contentLength, contentEncoding); defineCaching(request, response, resource, lastModified); writeResource(request, response, is); } } finally { if(is!=null) is.close(); } } /** * Copy the content of the specified input stream to the servlet response. */ protected void writeResource(HttpServletRequest request, HttpServletResponse response, InputStream in) throws IOException { ServletOutputStream out = response.getOutputStream(); try { byte[] buffer = new byte[1024]; for (int size = in.read(buffer); size != -1; size = in.read(buffer)) { out.write(buffer, 0, size); } } finally { out.close(); } } /** * Output http headers telling the browser (and possibly intermediate caches) how * to cache this data. *

* The expiry time in this header info is set to 7 days. This is not a problem as * the overall URI contains a "cache key" that changes whenever the webapp is * redeployed (see AddResource.getCacheKey), meaning that all browsers will * effectively reload files on webapp redeploy. */ protected void defineCaching(HttpServletRequest request, HttpServletResponse response, String resource, long lastModified) { response.setDateHeader("Last-Modified", lastModified); Calendar expires = Calendar.getInstance(); expires.add(Calendar.DAY_OF_YEAR, 7); response.setDateHeader("Expires", expires.getTimeInMillis()); //12 hours: 43200 = 60s * 60 * 12 response.setHeader("Cache-Control", "max-age=43200"); response.setHeader("Pragma", ""); } /** * Output http headers indicating the mime-type of the content being served. * The mime-type output is determined by the resource filename suffix. */ protected void defineContentHeaders(HttpServletRequest request, HttpServletResponse response, String resource, int contentLength, String contentEncoding) { String charset = ""; if (contentEncoding != null) { charset = "; charset=" + contentEncoding; } if (contentLength > -1) { response.setContentLength(contentLength); } if (resource.endsWith(".js")) response.setContentType( org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT + charset); else if (resource.endsWith(".css")) response.setContentType( org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLE_TYPE_TEXT_CSS + charset); else if (resource.endsWith(".gif")) response.setContentType("image/gif"); else if (resource.endsWith(".png")) response.setContentType("image/png"); else if (resource.endsWith(".jpg") || resource.endsWith(".jpeg")) response.setContentType("image/jpeg"); else if (resource.endsWith(".xml") || resource.endsWith(".xsl")) response.setContentType("text/xml"); // XSL has to be served as XML. } protected Class loadComponentClass(String componentClass) throws ClassNotFoundException { return ClassUtils.classForName(componentClass); } // NOTE: This method is not being used. Perhaps it can be removed? protected void validateCustomComponent(Class myfacesCustomComponent) { if (!myfacesCustomComponent.getName().startsWith(ORG_APACHE_MYFACES_CUSTOM + ".")) { throw new IllegalArgumentException( "expected a myfaces custom component class in package " + ORG_APACHE_MYFACES_CUSTOM); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy