/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: PortletAppAddResource.java 2612 2007-11-12 09:39:10Z drmlipp $
*
* $Log$
* Revision 1.12 2007/03/27 21:59:44 mlipp
* Fixed lots of checkstyle warnings.
*
* Revision 1.11 2007/01/18 15:07:11 drmlipp
* Made JavaScript loading synchronous in IE.
*
* Revision 1.10 2007/01/17 12:52:41 drmlipp
* Fixed problem with "defer" always being set.
*
* Revision 1.9 2006/11/01 16:18:51 mlipp
* Make our bridge depend on core only.
*
* Revision 1.8 2006/10/06 15:26:51 drmlipp
* Improved.
*
* Revision 1.7 2006/09/29 12:32:11 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.6 2006/09/14 13:33:46 drmlipp
* Removed superfluous code.
*
* Revision 1.5 2006/09/12 12:55:39 drmlipp
* Added event handler registration and did some cleanup.
*
* Revision 1.4 2006/09/12 05:56:26 mlipp
* Fixed attribute name.
*
* Revision 1.3 2006/09/11 15:29:28 drmlipp
* Improved portlet support.
*
* Revision 1.2 2006/09/11 10:50:22 drmlipp
* Portal specific implementation.
*
* Revision 1.1 2006/09/08 14:08:06 drmlipp
* Started handling of MyFaces resource loading.
*
*/
package de.danet.an.util.jsf;
import java.io.IOException;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.myfaces.renderkit.html.util.AddResource;
import org.apache.myfaces.renderkit.html.util.MyFacesResourceHandler;
import org.apache.myfaces.renderkit.html.util.ResourceHandler;
import org.apache.myfaces.renderkit.html.util.ResourceLoader;
import org.apache.myfaces.renderkit.html.util.ResourcePosition;
import org.apache.myfaces.shared_impl.renderkit.html.HTML;
import org.apache.myfaces.shared_impl.util.ClassUtils;
/**
* This class provides an adapted <code>AddResource</code> implementation.
*
* @author Michael Lipp
*
*/
public class PortletAppAddResource implements AddResource {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory
.getLog(PortletAppAddResource.class);
private static final String PATH_SEPARATOR = "/";
private static final String RESOURCE_VIRTUAL_PATH
= "/faces/myFacesExtensionResource";
private static final String COND_ADD_FUNCTIONS_ADDED
= PortletAppAddResource.class.getName() + "_COND_ADD_FUNCTIONS_ADDED";
private static final String RESOURCES_CACHE_KEY
= PortletAppAddResource.class.getName() + ".CACHE_KEY";
private String contextPath = null;
/**
* 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.
*/
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();
}
/**
* 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 {
doAddJavaScriptHere(context, getResourceUri(context, uri));
}
public void addJavaScriptHerePlain(FacesContext context, String uri)
throws IOException {
addJavaScriptHere(context, uri);
}
/**
* Insert a [script src="url"] entry at the current location in the
* response.
*
* @param 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);
doAddJavaScriptHere(context, getResourceUri(context, resourceHandler));
}
private void doAddJavaScriptHere
(FacesContext context, String resourceUrl) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.SCRIPT_ELEM, null);
writer.writeAttribute
(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
String src
= context.getExternalContext().encodeResourceURL(resourceUrl);
writer.writeURIAttribute(HTML.SRC_ATTR, src, null);
writer.endElement(HTML.SCRIPT_ELEM);
}
/**
* Adds the given Javascript resource to the document header at the
* specified document positioy by supplying a resourcehandler instance. <p/>
* Use this method to have full control about building the reference url to
* identify the resource and to customize how the resource is written to the
* response. In most cases, however, one of the convenience methods on this
* class can be used without requiring a custom ResourceHandler to be
* provided. <p/>
* If the script has already been referenced, it's added only
* once. <p/>
* Note that this method <i>queues</i> the javascript for
* insertion, and that the script is inserted into the buffered response by
* the ExtensionsFilter after the page is complete.
*/
public void addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, ResourceHandler resourceHandler) {
addJavaScriptAtPosition(context, position, resourceHandler, false);
}
/**
* Insert a [script src="url"] entry into the document header at the
* specified document position. If the script has already been referenced,
* it's added only once. <p/>
* 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 addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, Class myfacesCustomComponent,
String resourceName) {
addJavaScriptAtPosition(context, position, new MyFacesResourceHandler(
myfacesCustomComponent, resourceName));
}
public void addJavaScriptAtPositionPlain(FacesContext context,
ResourcePosition position, Class myfacesCustomComponent,
String resourceName) {
addJavaScriptAtPosition(context, position, new MyFacesResourceHandler(
myfacesCustomComponent, resourceName), false);
}
/**
* Insert a [script src="url"] entry into the document header at the
* specified document position. If the script has already been referenced,
* it's added only once.
*
* @param defer
* specifies whether the html attribute "defer" is set on the
* generated script tag. If this is true then the browser will
* continue processing the html page without waiting for the
* specified script to load and be run.
*/
public void addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, Class myfacesCustomComponent,
String resourceName, boolean defer) {
addJavaScriptAtPosition(context, position, new MyFacesResourceHandler(
myfacesCustomComponent, resourceName), defer);
}
/**
* Insert a [script src="url"] entry into the document header at the
* specified document position. If the script has already been referenced,
* it's added only once.
*
* @param uri
* is the location of the desired resource, relative to the base
* directory of the webapp (ie its contextPath).
*/
public void addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, String uri) {
addJavaScriptAtPosition(context, position, uri, false);
}
/**
* Adds the given Javascript resource at the specified document position. If
* the script has already been referenced, it's added only once.
*/
public void addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, String uri, boolean defer) {
doAddJavaScriptAtPosition
(context, position, getResourceUri(context, uri), defer);
}
public void addJavaScriptToBodyTag
(FacesContext context, String javascriptEventName,
String addedJavaScript) {
try {
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.SCRIPT_ELEM, null);
writer.writeAttribute
(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
writer.write("de_danet_an_util_jsf_addBodyHandler(\""
+ javascriptEventName + "\", " + addedJavaScript + "\");\n");
writer.endElement(HTML.SCRIPT_ELEM);
} catch (IOException e) {
throw (IllegalStateException)
(new IllegalStateException (e.getMessage())).initCause(e);
}
}
/**
* Adds the given Javascript resource at the specified document position. If
* the script has already been referenced, it's added only once.
*/
public void addJavaScriptAtPosition(FacesContext context,
ResourcePosition position, ResourceHandler resourceHandler,
boolean defer) {
validateResourceHandler(resourceHandler);
doAddJavaScriptAtPosition
(context, position, getResourceUri(context, resourceHandler),
defer);
}
private void doAddJavaScriptAtPosition
(FacesContext context, ResourcePosition position,
String uri, boolean defer) {
addCondAddFunctions(context);
try {
uri = context.getExternalContext().encodeResourceURL(uri);
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.SCRIPT_ELEM, null);
writer.writeAttribute
(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
writer.write("de_danet_an_util_jsf_condAddScript(\"" + uri + "\", "
+ Boolean.toString(defer).toLowerCase() + ");\n");
writer.endElement(HTML.SCRIPT_ELEM);
} catch (IOException e) {
throw (IllegalStateException)
(new IllegalStateException (e.getMessage())).initCause(e);
}
}
/**
* @param context
*/
private void addCondAddFunctions(FacesContext context) {
if (context.getExternalContext()
.getRequestMap().containsKey(COND_ADD_FUNCTIONS_ADDED)) {
return;
}
try {
ResponseWriter writer = context.getResponseWriter();
// Dummy for function ...addBodyHandler below
writer.startElement(HTML.DIV_ELEM, null);
writer.writeAttribute
(HTML.ID_ATTR, "de_danet_an_util_jsf_eventTypeDummy", null);
writer.writeAttribute(HTML.STYLE_ATTR, "visibility:hidden", null);
writer.writeAttribute(HTML.ONCLICK_ATTR, "alert(\"Don't!\")", null);
writer.endElement(HTML.DIV_ELEM);
writer.startElement(HTML.SCRIPT_ELEM, null);
writer.writeAttribute
(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
// Adding JavaScript
writer.write ("function de_danet_an_util_jsf_condAddScript (uri, defer) {\n");
writer.write (" if (window.de_danet_an_util_jsf_condAddScript.loaded == undefined) {\n");
writer.write (" window.de_danet_an_util_jsf_condAddScript.loaded = {};\n");
writer.write (" }\n");
writer.write (" if (window.de_danet_an_util_jsf_condAddScript.loaded[uri]) {\n");
writer.write (" return;\n");
writer.write (" }\n");
writer.write (" if (navigator.appName == \"Microsoft Internet Explorer\") {\n");
writer.write (" var ajaxRequest = null;\n");
writer.write (" try {\n");
writer.write (" ajaxRequest = new ActiveXObject(\"Msxml2.XMLHTTP\");\n");
writer.write (" } catch (e) {\n");
writer.write (" try {\n");
writer.write (" ajaxRequest = new ActiveXObject(\"Microsoft.XMLHTTP\");\n");
writer.write (" } catch (e) {\n");
writer.write (" }\n");
writer.write (" }\n");
writer.write (" if (ajaxRequest != null) {\n");
writer.write (" ajaxRequest.open(\"GET\", uri, false);\n");
writer.write (" ajaxRequest.send(null);\n");
writer.write (" if (ajaxRequest.status == 200) {\n");
writer.write (" window.execScript(ajaxRequest.responseText, \"javascript\");\n");
writer.write (" window.de_danet_an_util_jsf_condAddScript.loaded[uri] = true;\n");
writer.write (" return;\n");
writer.write (" }\n");
writer.write (" }\n");
writer.write (" }\n");
writer.write (" var scriptRef = document.createElement(\"script\");\n");
writer.write (" scriptRef.setAttribute (\"type\", \"text/javascript\")\n");
writer.write (" scriptRef.setAttribute (\"src\", uri)\n");
writer.write (" if (defer) {\n");
writer.write (" scriptRef.setAttribute (\"defer\", \"defer\")\n");
writer.write (" }\n");
writer.write (" var head = document.getElementsByTagName(\"head\")[0];\n");
writer.write (" head.appendChild (scriptRef);\n");
writer.write (" window.de_danet_an_util_jsf_condAddScript.loaded[uri] = true;\n");
writer.write ("}\n");
writer.write ("\n");
// Adding style
writer.write ("function de_danet_an_util_jsf_condAddStyle (uri) {\n");
writer.write (" if (!document.getElementsByTagName(\"head\")) {\n");
writer.write (" return;\n");
writer.write (" }\n");
writer.write (" var head = document.getElementsByTagName(\"head\")[0];\n");
writer.write (" var links = head.getElementsByTagName(\"link\");\n");
writer.write (" var found = false;\n");
writer.write (" for (i = 0; i < links.length; i++) {\n");
writer.write (" var child = links[i];\n");
writer.write (" if (child.nodeType == 1 "
+ "&& child.getAttribute(\"rel\") == \"stylesheet\" "
+ "&& child.getAttribute(\"type\") == \"text/css\" "
+ "&& child.getAttribute(\"src\") == uri) {\n");
writer.write (" found = true;\n");
writer.write (" break;\n");
writer.write (" }\n");
writer.write (" }\n");
writer.write (" if(!found) {\n");
writer.write (" var styleRef = document.createElement(\"link\");\n");
writer.write (" styleRef.setAttribute (\"rel\", \"stylesheet\");\n");
writer.write (" styleRef.setAttribute (\"type\", \"text/css\");\n");
writer.write (" styleRef.setAttribute (\"href\", uri);\n");
writer.write (" head.appendChild (styleRef);\n");
writer.write (" }\n");
writer.write ("}\n");
writer.write ("\n");
// Adding to event
writer.write ("function de_danet_an_util_jsf_addBodyHandler(event, script) {\n");
writer.write (" var dummy=document.getElementById(\"de_danet_an_util_jsf_eventTypeDummy\");\n");
writer.write (" var handlersAreFunctions = (typeof dummy.getAttribute(\"onclick\") == 'function');\n");
writer.write (" var body = document.getElementsByTagName(\"body\")[0];\n");
writer.write (" var oldHandler = body.getAttribute(event);\n");
writer.write (" if (handlersAreFunctions) {\n");
writer.write (" body.setAttribute(event, function() {\n");
writer.write (" if (oldHandler) {\n");
writer.write (" oldHandler();\n");
writer.write (" }\n");
writer.write (" eval(script);\n");
writer.write (" });\n");
writer.write (" } else {\n");
writer.write (" if (oldHandler) {\n");
writer.write (" body.setAttribute(event, oldHandler + \";\" + script);\n");
writer.write (" } else {\n");
writer.write (" body.setAttribute(event, script);\n");
writer.write (" }\n");
writer.write (" }\n");
writer.write ("}\n");
writer.endElement(HTML.SCRIPT_ELEM);
context.getExternalContext()
.getRequestMap().put(COND_ADD_FUNCTIONS_ADDED, Boolean.TRUE);
} catch (IOException e) {
throw (IllegalStateException)
(new IllegalStateException (e.getMessage())).initCause(e);
}
}
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));
}
/**
* Adds the given Style Sheet at the specified document position. If the
* style sheet has already been referenced, it's added only once.
*/
public void addStyleSheet(FacesContext context, ResourcePosition position,
Class myfacesCustomComponent, String resourceName) {
addStyleSheet(context, position, new MyFacesResourceHandler(
myfacesCustomComponent, resourceName));
}
/**
* Adds the given Style Sheet at the specified document position. If the
* style sheet has already been referenced, it's added only once.
*/
public void addStyleSheet(FacesContext context, ResourcePosition position,
String uri) {
doAddStyleSheet(context, getResourceUri(context, uri));
}
/**
* Adds the given Style Sheet at the specified document position. If the
* style sheet has already been referenced, it's added only once.
*/
public void addStyleSheet(FacesContext context, ResourcePosition position,
ResourceHandler resourceHandler) {
validateResourceHandler(resourceHandler);
doAddStyleSheet(context, getResourceUri(context, resourceHandler));
}
private void doAddStyleSheet (FacesContext context, String uri) {
addCondAddFunctions(context);
try {
uri = context.getExternalContext().encodeResourceURL(uri);
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.SCRIPT_ELEM, null);
writer.writeAttribute
(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
writer.write("de_danet_an_util_jsf_condAddStyle(\"" + uri + "\");\n");
writer.endElement(HTML.SCRIPT_ELEM);
} catch (IOException e) {
throw (IllegalStateException)
(new IllegalStateException (e.getMessage())).initCause(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.
*/
protected String getResourceUri(FacesContext context, Class resourceLoader,
boolean withContextPath) {
StringBuffer sb = new StringBuffer(200);
sb.append(RESOURCE_VIRTUAL_PATH);
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);
}
/**
* 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
*/
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
*/
protected void validateResourceLoader(Class resourceloader) {
if (!ResourceLoader.class.isAssignableFrom(resourceloader)) {
throw new FacesException("Class " + resourceloader.getName()
+ " must implement " + ResourceLoader.class.getName());
}
}
/**
* Adds the given Inline Style at the specified document position.
*/
public void addInlineStyleAtPosition(FacesContext context,
ResourcePosition position, String inlineStyle) {
logger.warn ("Adding inline style at " + position + " not supported");
}
/**
* Adds the given Inline Script at the specified document position.
*/
public void addInlineScriptAtPosition(FacesContext context,
ResourcePosition position, String inlineScript) {
logger.warn ("Adding inline script at " + position + " not supported");
}
/*
* (non-Javadoc)
*
* @see org.apache.myfaces.renderkit.html.util.AddResource#hasHeaderBeginInfos()
*/
public boolean hasHeaderBeginInfos() {
return false;
}
/*
* (non-Javadoc)
*
* @see org.apache.myfaces.renderkit.html.util.AddResource#isResourceUri
*/
public boolean isResourceUri(HttpServletRequest request) {
String path;
if (contextPath != null) {
path = contextPath + RESOURCE_VIRTUAL_PATH;
} else {
path = RESOURCE_VIRTUAL_PATH;
}
return request.getRequestURI().startsWith(path);
}
/*
* (non-Javadoc)
*
* @see org.apache.myfaces.renderkit.html.util.AddResource#parseResponse
* java.lang.String, javax.servlet.http.HttpServletResponse)
*/
public void parseResponse
(HttpServletRequest request, String bufferedResponse,
HttpServletResponse response) throws IOException {
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#requiresBuffer()
*/
public boolean requiresBuffer() {
return false;
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#responseFinished()
*/
public void responseFinished() {
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#responseStarted()
*/
public void responseStarted() {
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#serveResource
*/
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 = RESOURCE_VIRTUAL_PATH + '/';
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 = ClassUtils.classForName(className);
validateResourceLoader(resourceLoader);
((ResourceLoader)resourceLoader.newInstance())
.serveResource(context, request, response, resourceUri);
response.flushBuffer();
} catch (ClassNotFoundException e) {
logger.error("Could not find class for name: " + className, e);
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Could not find resource loader class for name: "
+ className);
} catch (InstantiationException e) {
logger.error
("Could not instantiate class for name: " + className, e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Could not instantiate resource loader class for name: "
+ className);
} catch (IllegalAccessException e) {
logger.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) {
logger.error("Error while serving resource: " + resourceUri
+ ", message : " + e.getMessage(), e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#setContextPath
*/
public void setContextPath(String contextPath) {
this.contextPath = contextPath;
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#writeMyFacesJavascriptBeforeBodyEnd
*/
public void writeMyFacesJavascriptBeforeBodyEnd
(HttpServletRequest request, HttpServletResponse response)
throws IOException {
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#writeResponse
*/
public void writeResponse
(HttpServletRequest request, HttpServletResponse response)
throws IOException {
}
/* (non-Javadoc)
* @see org.apache.myfaces.renderkit.html.util.AddResource#writeWithFullHeader(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void writeWithFullHeader
(HttpServletRequest request, HttpServletResponse response)
throws IOException {
}
public void processAppendices
(RenderRequest request, RenderResponse response,
FacesContext facesContext) throws IOException {
// Some components seem to use a deprecated mechnism
String myFacesJavascript = (String) request
.getAttribute("org.apache.myfaces.myFacesJavascript");
if (myFacesJavascript != null) {
response.getWriter().println(myFacesJavascript);
}
}
/* (non-Javadoc)
* Comment copied from interface or superclass.
*/
public boolean isResourceUri
(ServletContext request, HttpServletRequest response) {
return true;
}
}