myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From we...@apache.org
Subject svn commit: r370903 - /myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java
Date Fri, 20 Jan 2006 21:52:08 GMT
Author: werpu
Date: Fri Jan 20 13:51:56 2006
New Revision: 370903

URL: http://svn.apache.org/viewcvs?rev=370903&view=rev
Log: (empty)

Added:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java
URL: http://svn.apache.org/viewcvs/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java?rev=370903&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java
(added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/util/MyFacesResourceLoader.java
Fri Jan 20 13:51:56 2006
@@ -0,0 +1,233 @@
+/*
+ /*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * 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.apache.myfaces.component.html.util;
+
+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 org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.renderkit.html.HTML;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 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$
+ */
+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.
+     * <p>
+     * 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.
+     * <p>
+     * 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.error("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.
+     * <p>
+     * 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}.
+     * <p>
+     * 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.
+     * <p>
+     * @see org.apache.myfaces.component.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;
+        }
+        resource = "resource/" + resource;
+
+        InputStream is = componentClass.getResourceAsStream(resource);
+        if (is == null)
+        {
+            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
+        {
+            defineContentHeaders(request, response, resource);
+            defineCaching(request, response, resource);
+            writeResource(request, response, is);
+        }
+    }
+
+    /**
+     * 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.
+     * <p>
+     * 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)
+    {
+        response.setDateHeader("Last-Modified", getLastModified());
+
+        Calendar expires = Calendar.getInstance();
+        expires.add(Calendar.DAY_OF_YEAR, 7);
+        response.setDateHeader("Expires", expires.getTimeInMillis());
+    }
+
+    /**
+     * 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)
+    {
+        if (resource.endsWith(".js"))
+            response.setContentType(HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT);
+        else if (resource.endsWith(".css"))
+            response.setContentType(HTML.STYLE_TYPE_TEXT_CSS);
+        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 Thread.currentThread().getContextClassLoader().loadClass(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);
+        }
+    }
+}
\ No newline at end of file



Mime
View raw message