You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/12/08 23:32:06 UTC

svn commit: r888604 - in /myfaces/tomahawk/trunk: core/src/main/java/org/apache/myfaces/custom/tree/taglib/ core/src/main/java/org/apache/myfaces/renderkit/html/util/ core12/src/main/java/org/apache/myfaces/renderkit/html/util/

Author: lu4242
Date: Tue Dec  8 22:32:04 2009
New Revision: 888604

URL: http://svn.apache.org/viewvc?rev=888604&view=rev
Log:
fix compatibility with JDK 1.4

Added:
    myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/
    myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java
Modified:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/tree/taglib/AbstractTreeTag.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/tree/taglib/AbstractTreeTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/tree/taglib/AbstractTreeTag.java?rev=888604&r1=888603&r2=888604&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/tree/taglib/AbstractTreeTag.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/tree/taglib/AbstractTreeTag.java Tue Dec  8 22:32:04 2009
@@ -87,7 +87,7 @@
         int answer = super.doStartTag();
         HtmlTree tree = (HtmlTree) getComponentInstance();
 
-        if (getCreated() && Boolean.parseBoolean(expandRoot)) {
+        if (getCreated() && parseBoolean(expandRoot)) {
             // component was created, so expand the root node
             TreeModel model = tree.getModel(context);
 
@@ -100,6 +100,11 @@
         tree.addToModelListeners();
         return answer;
     }
+    
+    private boolean parseBoolean(String s)
+    {
+        return ((s != null) && s.equalsIgnoreCase("true"));
+    }
 
     public void release() {
         super.release();

Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java?rev=888604&r1=888603&r2=888604&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java Tue Dec  8 22:32:04 2009
@@ -230,7 +230,7 @@
         try {
             writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,false);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -239,7 +239,7 @@
             writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
                     myfacesCustomComponent, resourceName)),true,false);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -248,7 +248,7 @@
             writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
                     myfacesCustomComponent, resourceName)),true,true);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -256,7 +256,7 @@
         try {
             writeJavaScriptReference(context,getResourceUri(context,uri),true,false);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -264,7 +264,7 @@
         try {
             writeJavaScriptReference(context,getResourceUri(context,uri),true,true);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -284,7 +284,7 @@
         try {
             writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,defer);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -292,7 +292,7 @@
         try {
             writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)),false,false);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -300,7 +300,7 @@
         try {
             writeStyleReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)));
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -308,7 +308,7 @@
         try {
             writeStyleReference(context,getResourceUri(context,uri));
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -316,7 +316,7 @@
         try {
             writeStyleReference(context,getResourceUri(context,resourceHandler));
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -324,7 +324,7 @@
         try {
             writeInlineStylesheet(context.getResponseWriter(), inlineStyle);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 
@@ -332,7 +332,7 @@
         try {
             writeInlineScript(context.getResponseWriter(), inlineScript);
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new IllegalStateException(e.getMessage());
         }
     }
 

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java?rev=888604&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/util/NonBufferingAddResource.java Tue Dec  8 22:32:04 2009
@@ -0,0 +1,616 @@
+/*
+ * 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.config.MyfacesConfig;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlResponseWriterImpl;
+import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+/**
+ * @since 1.1.7
+ * @author Martin Marinschek
+ */
+public class NonBufferingAddResource implements AddResource {
+
+    protected static final String PATH_SEPARATOR = "/";
+    protected String _contextPath;
+
+    private static final String RESOURCES_CACHE_KEY = AddResource.class.getName() + ".CACHE_KEY";
+
+    private String resourceVirtualPath;
+
+    protected Log log = LogFactory.getLog(NonBufferingAddResource.class);
+
+    /**
+     * the context path for the web-app.<br />
+     * You can set the context path only once, every subsequent set will throw an SecurityException
+     */
+    public void setContextPath(String contextPath)
+    {
+        if (_contextPath != null)
+        {
+            throw new SecurityException("context path already set");
+        }
+
+        _contextPath = contextPath;
+    }
+
+    // Methods to add resources
+
+    /**
+     * Insert a [script src="url"] entry at the current location in the response.
+     * The resource is expected to be in the classpath, at the same location as the
+     * specified component + "/resource".
+     * <p/>
+     * Example: when customComponent is class example.Widget, and
+     * resourceName is script.js, the resource will be retrieved from
+     * "example/Widget/resource/script.js" in the classpath.
+     */
+    public void addJavaScriptHere(FacesContext context, Class myfacesCustomComponent,
+                                  String resourceName) throws IOException
+    {
+        addJavaScriptHere(context, new MyFacesResourceHandler(myfacesCustomComponent, resourceName));
+    }
+
+    /**
+     * Insert a [script src="url"] entry at the current location in the response.
+     *
+     * @param uri is the location of the desired resource, relative to the base
+     *            directory of the webapp (ie its contextPath).
+     */
+    public void addJavaScriptHere(FacesContext context, String uri) throws IOException
+    {
+        writeJavaScriptReference(context, getResourceUri(context, uri), true, false);
+    }
+
+    protected static void writeJavaScriptReference(FacesContext context, String resourceUri, boolean encoding, boolean defer) throws IOException{
+        ResponseWriter writer = context.getResponseWriter();
+
+        String src = null;
+        if(encoding) {
+            src=context.getExternalContext().encodeResourceURL(resourceUri);
+        }
+        else {
+            src = resourceUri;
+        }
+
+        writeJavaScriptReference(defer, writer, src);
+    }
+
+    protected static void writeJavaScriptReference(HttpServletResponse response, ResponseWriter writer, String resourceUri, boolean encoding, boolean defer) throws IOException {
+        String src = null;
+        if(encoding) {
+            src=response.encodeURL(resourceUri);
+        }
+        else {
+            src = resourceUri;
+        }
+
+        writeJavaScriptReference(defer, writer, src);
+    }
+
+    private static void writeJavaScriptReference(boolean defer, ResponseWriter writer, String src) throws IOException {
+        writer.startElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_ELEM, null);
+        writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
+
+        if(defer) {
+            writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_ELEM_DEFER_ATTR, "true", null);
+        }
+        writer.writeURIAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SRC_ATTR, src, null);
+        writer.endElement(HTML.SCRIPT_ELEM);
+    }
+
+    protected static void writeStyleReference(FacesContext context, String resourceUri) throws IOException {
+        ResponseWriter writer = context.getResponseWriter();
+        writer.startElement(HTML.LINK_ELEM, null);
+        writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.REL_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLESHEET_VALUE, null);
+        writer.writeAttribute(HTML.HREF_ATTR, context.getExternalContext().encodeResourceURL(resourceUri), null);
+        writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
+        writer.endElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.LINK_ELEM);
+    }
+
+    protected static void writeStyleReference(HttpServletResponse response, ResponseWriter writer,  String resourceUri) throws IOException {
+        writer.startElement(HTML.LINK_ELEM, null);
+        writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.REL_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLESHEET_VALUE, null);
+        writer.writeAttribute(HTML.HREF_ATTR, response.encodeURL(resourceUri), null);
+        writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
+        writer.endElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.LINK_ELEM);
+    }
+
+    protected static void writeInlineScript(ResponseWriter writer, String inlineScript) throws IOException {
+            writer.startElement(HTML.SCRIPT_ELEM, null);
+            writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
+            writer.writeText(inlineScript, null);
+            writer.endElement(HTML.SCRIPT_ELEM);
+    }
+
+    protected static  void writeInlineStylesheet(ResponseWriter writer, String inlineStyle) throws IOException {
+        writer.startElement(HTML.STYLE_ELEM, null);
+        writer.writeAttribute(HTML.REL_ATTR, HTML.STYLESHEET_VALUE, null);
+        writer.writeAttribute(HTML.TYPE_ATTR, HTML.STYLE_TYPE_TEXT_CSS, null);
+        writer.writeText(inlineStyle, null);
+        writer.endElement(HTML.STYLE_ELEM);
+    }
+
+    public void addJavaScriptHerePlain(FacesContext context, String uri) throws IOException
+    {
+        writeJavaScriptReference(context, getResourceUri(context, uri), false, false);
+    }
+
+    /**
+     * Insert a [script src="url"] entry at the current location in the response.
+     *
+     * @param context The current faces-context
+     * @param resourceHandler is an object which specifies exactly how to build the url
+     *                        that is emitted into the script tag. Code which needs to generate URLs in ways
+     *                        that this class does not support by default can implement a custom ResourceHandler.
+     * @throws IOException
+     */
+    public void addJavaScriptHere(FacesContext context, ResourceHandler resourceHandler)
+            throws IOException
+    {
+        validateResourceHandler(resourceHandler);
+        writeJavaScriptReference(context, getResourceUri(context, resourceHandler), true, false);
+    }
+
+    public void addResourceHere(FacesContext context, ResourceHandler resourceHandler)
+            throws IOException
+    {
+        validateResourceHandler(resourceHandler);
+
+        String path = getResourceUri(context, resourceHandler);
+        ResponseWriter writer = context.getResponseWriter();
+        writer.write(context.getExternalContext().encodeResourceURL(path));
+    }
+
+    /**
+     * Verify that the resource handler is acceptable. Null is not
+     * valid, and the getResourceLoaderClass method must return a
+     * Class object whose instances implements the ResourceLoader
+     * interface.
+     *
+     * @param resourceHandler handler to check
+     */
+    protected void validateResourceHandler(ResourceHandler resourceHandler)
+    {
+        if (resourceHandler == null)
+        {
+            throw new IllegalArgumentException("ResourceHandler is null");
+        }
+        validateResourceLoader(resourceHandler.getResourceLoaderClass());
+    }
+
+    /**
+     * Given a Class object, verify that the instances of that class
+     * implement the ResourceLoader interface.
+     *
+     * @param resourceloader loader to check
+     */
+    protected void validateResourceLoader(Class resourceloader)
+    {
+        if (!ResourceLoader.class.isAssignableFrom(resourceloader))
+        {
+            throw new FacesException("Class " + resourceloader.getName() + " must implement "
+                    + ResourceLoader.class.getName());
+        }
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,false);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
+                    myfacesCustomComponent, resourceName)),true,false);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName, boolean defer) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(
+                    myfacesCustomComponent, resourceName)),true,true);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, String uri) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,uri),true,false);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, String uri, boolean defer) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,uri),true,true);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     *
+     * @param context
+     * @param javascriptEventName
+     * @param addedJavaScript
+     *
+     * @deprecated
+     */
+    public void addJavaScriptToBodyTag(FacesContext context, String javascriptEventName, String addedJavaScript) {
+        throw new UnsupportedOperationException("not supported anymore - use javascript to register your body-event-handler directly");
+    }
+
+    public void addJavaScriptAtPosition(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler, boolean defer) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,resourceHandler),true,defer);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addJavaScriptAtPositionPlain(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
+        try {
+            writeJavaScriptReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)),false,false);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addStyleSheet(FacesContext context, ResourcePosition position, Class myfacesCustomComponent, String resourceName) {
+        try {
+            writeStyleReference(context,getResourceUri(context,new MyFacesResourceHandler(myfacesCustomComponent, resourceName)));
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addStyleSheet(FacesContext context, ResourcePosition position, String uri) {
+        try {
+            writeStyleReference(context,getResourceUri(context,uri));
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addStyleSheet(FacesContext context, ResourcePosition position, ResourceHandler resourceHandler) {
+        try {
+            writeStyleReference(context,getResourceUri(context,resourceHandler));
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addInlineStyleAtPosition(FacesContext context, ResourcePosition position, String inlineStyle) {
+        try {
+            writeInlineStylesheet(context.getResponseWriter(), inlineStyle);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void addInlineScriptAtPosition(FacesContext context, ResourcePosition position, String inlineScript) {
+        try {
+            writeInlineScript(context.getResponseWriter(), inlineScript);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public String getResourceUri(FacesContext context, Class myfacesCustomComponent,
+                                 String resource, boolean withContextPath)
+    {
+        return getResourceUri(context,
+                new MyFacesResourceHandler(myfacesCustomComponent, resource), withContextPath);
+    }
+
+    public String getResourceUri(FacesContext context, Class myfacesCustomComponent, String resource)
+    {
+        return getResourceUri(context, new MyFacesResourceHandler(myfacesCustomComponent, resource));
+    }
+
+
+    /**
+     * Get the Path used to retrieve an resource.
+     */
+    public String getResourceUri(FacesContext context, ResourceHandler resourceHandler)
+    {
+        String uri = resourceHandler.getResourceUri(context);
+        if (uri == null)
+        {
+            return getResourceUri(context, resourceHandler.getResourceLoaderClass(), true);
+        }
+        return getResourceUri(context, resourceHandler.getResourceLoaderClass(), true) + uri;
+    }
+
+    /**
+     * Get the Path used to retrieve an resource.
+     */
+    public String getResourceUri(FacesContext context, ResourceHandler resourceHandler,
+                                 boolean withContextPath)
+    {
+        String uri = resourceHandler.getResourceUri(context);
+        if (uri == null)
+        {
+            return getResourceUri(context, resourceHandler.getResourceLoaderClass(),
+                    withContextPath);
+        }
+        return getResourceUri(context, resourceHandler.getResourceLoaderClass(), withContextPath)
+                + uri;
+    }
+
+    /**
+     * Get the Path used to retrieve an resource.
+     */
+    public String getResourceUri(FacesContext context, String uri)
+    {
+        return getResourceUri(context, uri, true);
+    }
+
+    /**
+     * Get the Path used to retrieve an resource.
+     */
+    public String getResourceUri(FacesContext context, String uri, boolean withContextPath)
+    {
+        if (withContextPath)
+        {
+            return context.getApplication().getViewHandler().getResourceURL(context, uri);
+        }
+        return uri;
+    }
+
+    /**
+     * Get the Path used to retrieve an resource.
+     * @param context current faces-context
+     * @param resourceLoader resourceLoader
+     * @param withContextPath use the context-path of the web-app when accessing the resources
+     *
+     * @return the URI of the resource
+     */
+    protected String getResourceUri(FacesContext context, Class resourceLoader,
+                                    boolean withContextPath)
+    {
+        StringBuffer sb = new StringBuffer(200);
+        sb.append(MyfacesConfig.getCurrentInstance(context.getExternalContext()).getResourceVirtualPath());
+        sb.append(PATH_SEPARATOR);
+        sb.append(resourceLoader.getName());
+        sb.append(PATH_SEPARATOR);
+        sb.append(getCacheKey(context));
+        sb.append(PATH_SEPARATOR);
+        return getResourceUri(context, sb.toString(), withContextPath);
+    }
+
+    /**
+     * Return a value used in the {cacheKey} part of a generated URL for a
+     * resource reference.
+     * <p/>
+     * Caching in browsers normally works by having files served to them
+     * include last-modified and expiry-time http headers. Until the expiry
+     * time is reached, a browser will silently use its cached version. After
+     * the expiry time, it will send a "get if modified since {time}" message,
+     * where {time} is the last-modified header from the version it has cached.
+     * <p/>
+     * Unfortunately this scheme only works well for resources represented as
+     * plain files on disk, where the webserver can easily and efficiently see
+     * the last-modified time of the resource file. When that query has to be
+     * processed by a servlet that doesn't scale well, even when it is possible
+     * to determine the resource's last-modified date from servlet code.
+     * <p/>
+     * Fortunately, for the AddResource class a static resource is only ever
+     * accessed because a URL was embedded by this class in a dynamic page.
+     * This makes it possible to implement caching by instead marking every
+     * resource served with a very long expiry time, but forcing the URL that
+     * points to the resource to change whenever the old cached version becomes
+     * invalid; the browser effectively thinks it is fetching a different
+     * resource that it hasn't seen before. This is implemented by embedding
+     * a "cache key" in the generated URL.
+     * <p/>
+     * Rather than using the actual modification date of a resource as the
+     * cache key, we simply use the webapp deployment time. This means that all
+     * data cached by browsers will become invalid after a webapp deploy (all
+     * the urls to the resources change). It also means that changes that occur
+     * to a resource <i>without</i> a webapp redeploy will not be seen by browsers.
+     *
+     * @param context the current faces-context
+     *
+     * @return the key for caching
+     */
+    protected long getCacheKey(FacesContext context)
+    {
+        // cache key is hold in application scope so it is recreated on redeploying the webapp.
+        Map applicationMap = context.getExternalContext().getApplicationMap();
+        Long cacheKey = (Long) applicationMap.get(RESOURCES_CACHE_KEY);
+        if (cacheKey == null)
+        {
+            cacheKey = new Long(System.currentTimeMillis() / 100000);
+            applicationMap.put(RESOURCES_CACHE_KEY, cacheKey);
+        }
+        return cacheKey.longValue();
+    }
+
+    public boolean isResourceUri(ServletContext servletContext, HttpServletRequest request)
+    {
+
+        String path;
+        if (_contextPath != null)
+        {
+            path = _contextPath + getResourceVirtualPath(servletContext);
+        }
+        else
+        {
+            path = getResourceVirtualPath(servletContext);
+        }
+
+        //fix for TOMAHAWK-660; to be sure this fix is backwards compatible, the
+        //encoded context-path is only used as a first option to check for the prefix
+        //if we're sure this works for all cases, we can directly return the first value
+        //and not double-check.
+        try
+        {
+            if(request.getRequestURI().startsWith(URLEncoder.encode(path,"UTF-8")))
+                return true;
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            log.error("Unsupported encoding UTF-8 used",e);
+
+        }
+
+        return request.getRequestURI().startsWith(path);
+    }
+
+    private String getResourceVirtualPath(ServletContext servletContext)
+    {
+        if(resourceVirtualPath == null)
+        {
+            resourceVirtualPath = servletContext.getInitParameter(MyfacesConfig.INIT_PARAM_RESOURCE_VIRTUAL_PATH);
+
+            if(resourceVirtualPath == null)
+            {
+                resourceVirtualPath = MyfacesConfig.INIT_PARAM_RESOURCE_VIRTUAL_PATH_DEFAULT;
+            }
+        }
+
+        return resourceVirtualPath;
+    }
+
+    private Class getClass(String className) throws ClassNotFoundException
+    {
+        Class clazz = ClassUtils.classForName(className);
+        validateResourceLoader(clazz);
+        return clazz;
+    }
+
+    public void serveResource(ServletContext context, HttpServletRequest request,
+                              HttpServletResponse response) throws IOException
+    {
+        String pathInfo = request.getPathInfo();
+        String uri = request.getContextPath() + request.getServletPath()
+                + (pathInfo == null ? "" : pathInfo);
+        String classNameStartsAfter = getResourceVirtualPath(context) + '/';
+
+        int posStartClassName = uri.indexOf(classNameStartsAfter) + classNameStartsAfter.length();
+        int posEndClassName = uri.indexOf(PATH_SEPARATOR, posStartClassName);
+        String className = uri.substring(posStartClassName, posEndClassName);
+        int posEndCacheKey = uri.indexOf(PATH_SEPARATOR, posEndClassName + 1);
+        String resourceUri = null;
+        if (posEndCacheKey + 1 < uri.length())
+        {
+            resourceUri = uri.substring(posEndCacheKey + 1);
+        }
+        try
+        {
+            Class resourceLoader = getClass(className);
+            validateResourceLoader(resourceLoader);
+            ((ResourceLoader) resourceLoader.newInstance()).serveResource(context, request,
+                    response, resourceUri);
+
+            // Do not call response.flushBuffer buffer here. There is no point, as if there
+            // ever were header data to write, this would fail as we have already written
+            // the response body. The only point would be to flush the output stream, but
+            // that will happen anyway when the servlet container closes the socket.
+            //
+            // In addition, flushing could fail here; it appears that Microsoft IE
+            // hasthe habit of hard-closing its socket as soon as it has received a complete
+            // gif file, rather than letting the server close it. The container will hopefully
+            // silently ignore exceptions on close.
+        }
+        catch (ResourceLoader.ClosedSocketException e)
+        {
+            // The ResourceLoader was unable to send the data because the client closed
+            // the socket on us; just ignore.
+        }
+        catch (ClassNotFoundException e)
+        {
+            log.error("Could not find class for name: " + className, e);
+            response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                    "Could not find resourceloader class for name: " + className);
+        }
+        catch (InstantiationException e)
+        {
+            log.error("Could not instantiate class for name: " + className, e);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Could not instantiate resourceloader class for name: " + className);
+        }
+        catch (IllegalAccessException e)
+        {
+            log.error("Could not access class for name: " + className, e);
+            response.sendError(HttpServletResponse.SC_FORBIDDEN,
+                    "Could not access resourceloader class for name: " + className);
+        }
+        catch (Throwable e)
+        {
+            log.error("Error while serving resource: " + resourceUri + ", message : " + e.getMessage(), e);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    public void parseResponse(HttpServletRequest request, String bufferedResponse, HttpServletResponse response) throws IOException {
+        throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
+    }
+
+    public void writeMyFacesJavascriptBeforeBodyEnd(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
+    }
+
+    public void writeWithFullHeader(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
+    }
+
+    public void writeResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        throw new UnsupportedOperationException("non-buffering add resource is not buffering.");
+    }
+
+    public boolean requiresBuffer() {
+        return false;
+    }
+
+    public void responseStarted() {
+    }
+
+    public void responseFinished() {
+    }
+
+    public boolean hasHeaderBeginInfos() {
+        return false;
+    }
+}