You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/06/24 13:19:44 UTC
svn commit: r671131 - in
/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet:
AbstractStylesheet.java StylesheetRenderer.java TextResourceFilter.java
TextResourceFilterProvider.java
Author: skitching
Date: Tue Jun 24 04:19:43 2008
New Revision: 671131
URL: http://svn.apache.org/viewvc?rev=671131&view=rev
Log:
TOMAHAWK-1266. Report an exception if an absolute path is used together with "inline" or "filtered" options.
Also add more documentation.
Modified:
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/AbstractStylesheet.java
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/StylesheetRenderer.java
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilter.java
myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilterProvider.java
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/AbstractStylesheet.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/AbstractStylesheet.java?rev=671131&r1=671130&r2=671131&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/AbstractStylesheet.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/AbstractStylesheet.java Tue Jun 24 04:19:43 2008
@@ -44,6 +44,16 @@
/**
* URL for CSS-file.
+ * <p>
+ * If this path starts with a slash, then the webapp context path will be prepended to it.
+ * This makes it simple to reference stylesheets at an absolute path within the webapp.
+ * A value like "/styles/style.css" becomes "/webappname/styles/style.css".
+ * <p>
+ * If this path does not start with a slash, then it is output unaltered. This supports
+ * absolute urls ("http://host/path/style.css"). It also supports having css files relative
+ * to the current page ("style.css" or "styles/style.css") but this needs to be used with
+ * care as the standard JSF postback/internal-forward navigation style can cause browsers
+ * to use an inappropriate base url when resolving relative references.
*
* @JSFProperty
* required="true"
@@ -51,23 +61,29 @@
public abstract String getPath();
/**
- * Inline the stylesheet file content as in contrast to referencing it as .
+ * Inline the stylesheet file content as in contrast to referencing it as a link.
+ * <p>
+ * The file referenced by the path attribute is loaded, and its content is written
+ * to the page wrapped in an <script> tag.
+ * <p>
+ * When this option is enabled, the path property must contain an absolute path
+ * within the current webapp. External urls ("http://*") and paths relative to the
+ * current page are not supported.
*
* @JSFProperty
* defaultValue = "false"
- * @return true if the styles are inlined to the jsp file
*/
public abstract boolean isInline();
/**
- * true|false. When true, any EL expression in the stylesheet will
- * be evaluated and replaced by its string representation on the
- * first access. The stylesheet will be processed only once.
- * Every subsequent request will get a cached view.
+ * Cause EL expressions in the stylesheet to be evaluated.
+ * <p>
+ * When true, any EL expression in the stylesheet will be evaluated and replaced
+ * by its string representation on the first access. The stylesheet will be
+ * processed only once. Every subsequent request will get a cached view.
*
* @JSFProperty
* defaultValue = "false"
- * @return true if the stylesheet should be filtered before sending to the browser
*/
public abstract boolean isFiltered();
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/StylesheetRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/StylesheetRenderer.java?rev=671131&r1=671130&r2=671131&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/StylesheetRenderer.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/StylesheetRenderer.java Tue Jun 24 04:19:43 2008
@@ -20,6 +20,7 @@
import java.io.IOException;
+import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@@ -41,7 +42,7 @@
public class StylesheetRenderer extends HtmlRenderer
{
public void encodeEnd(FacesContext context, UIComponent component)
- throws IOException
+ throws IOException, FacesException
{
if ((context == null) || (component == null))
@@ -50,43 +51,41 @@
}
Stylesheet stylesheet = (Stylesheet) component;
ResponseWriter writer = context.getResponseWriter();
-
- //A path starting with / or not is the same for this component,
- //because ctx.getExternalContext().getResourceAsStream(file);
- //or ServletContext.getResourceAsStream() specifies that
- //ALL resources must start with '/'
- String path = stylesheet.getPath();
- if (path.startsWith("/"))
- {
- path = path.substring(1);
- }
+
+ String path = stylesheet.getPath();
if (stylesheet.isInline())
{
//include as inline css
+
+ if (!path.startsWith("/"))
+ {
+ throw new FacesException("Inline stylesheets require absolute resource path");
+ }
+
writer.startElement("style", component);
writer.writeAttribute("type", "text/css", null);
if (stylesheet.getMedia() != null)
{
writer.writeAttribute("media", stylesheet.getMedia(), null);
}
- //writer.writeText("<!--\n", null);
Object text;
if (stylesheet.isFiltered())
{
+ // Load, filter and cache the resource. Then return the cached data.
ResourceInfo info = TextResourceFilter.getInstance(context).getOrCreateFilteredResource(context, path);
text = info.getText();
}
else
{
- text = RendererUtils.loadResourceFile(context,'/'+ path);
+ // Just load the data (not cached)
+ text = RendererUtils.loadResourceFile(context, path);
}
if (text != null)
{
writer.writeText(text, null);
}
- //writer.writeText("\n-->", null);
writer.endElement("style");
}
else
@@ -103,8 +102,32 @@
String stylesheetPath;
if (stylesheet.isFiltered())
{
+ if (!path.startsWith("/"))
+ {
+ throw new FacesException("Filtered stylesheets require absolute resource path");
+ }
+
+ // Load, filter and cache the resource
TextResourceFilter.getInstance(context).getOrCreateFilteredResource(context, path);
- stylesheetPath = AddResourceFactory.getInstance(context).getResourceUri(context, TextResourceFilterProvider.class, path, true);
+
+ // Compute a URL that goes via the tomahawk ExtensionsFilter and the
+ // TextResourceFilterProvider to fetch the resource from the cache.
+ //
+ // Unfortunately the getResourceUri(context, Class, String, bool) api below is
+ // really meant for serving resources out of the Tomahawk jarfile, relative to
+ // some class that the resource belongs to. So it only expects to receive
+ // relative paths. We are abusing it here to serve resources out of the
+ // webapp, specified by an absolute path. So here, the leading slash is
+ // stripped off and in the TextResourceFilterProvider a matching hack
+ // puts it back on again. A better solution would be to write a custom
+ // ResourceHandler class and pass that to the getResourceUri method...
+ // TODO: fixme
+ String nastyPathHack = path.substring(1);
+ stylesheetPath = AddResourceFactory.getInstance(context).getResourceUri(
+ context,
+ TextResourceFilterProvider.class,
+ nastyPathHack,
+ true);
}
else
{
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilter.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilter.java?rev=671131&r1=671130&r2=671131&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilter.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilter.java Tue Jun 24 04:19:43 2008
@@ -37,7 +37,9 @@
/**
* Loads, filters and then caches any resource available to the webapp.
* <p>
- * The resource can then be retrieved from the cache when desired.
+ * The resource can then be retrieved from the cache when desired. In
+ * particular, it can be retrieved via a URL that invokes the Tomahawk
+ * ExtensionsFilter and TextResourceFilterProvider classes.
* <p>
* The "filtering" process looks for any strings of form #{...} in the
* resource, and executes it as an EL expression. The original expression
@@ -139,6 +141,9 @@
* <p>
* If the resource is not already in the cache (due to an earlier call to
* getOrCreateFilteredResource) then null is returned.
+ * <p>
+ * The path param is a simple key that must match the value passed to
+ * an earlier call to getOrCreateFilteredResource.
*/
public ResourceInfo getFilteredResource(String path)
{
@@ -155,14 +160,16 @@
* <p>
* Note: This method is not synchronized for performance reasons (the map is).
* The worst case is that we filter a resource twice the first time which is not
- * a problem
+ * a problem.
+ * <P>
+ * The path param must start with a slash, and is interpreted as a path relative
+ * to the webapp root (not the current page).
*/
public ResourceInfo getOrCreateFilteredResource(FacesContext context, String path) throws IOException
{
- if (path.startsWith("/"))
+ if (!path.startsWith("/"))
{
- // the resource loader do not use the leading "/", so strip it here
- path = path.substring(1);
+ throw new IllegalArgumentException("Path must start with a slash, but was: " + path);
}
ResourceInfo filteredResource = getFilteredResource(path);
@@ -174,7 +181,7 @@
//Tomcat ASF Bugzilla � Bug 43241
//ServletContext.getResourceAsStream() does not follow API spec
//ALL resources must start with '/'
- String text = RendererUtils.loadResourceFile(context,'/' + path);
+ String text = RendererUtils.loadResourceFile(context, path);
if (text == null)
{
// avoid loading the errorneous resource over and over again
Modified: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilterProvider.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilterProvider.java?rev=671131&r1=671130&r2=671131&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilterProvider.java (original)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/stylesheet/TextResourceFilterProvider.java Tue Jun 24 04:19:43 2008
@@ -37,23 +37,31 @@
*/
public class TextResourceFilterProvider implements ResourceProvider
{
+ // Hack note: a slash has to be prefixed to the resource value here because
+ // we are abusing the AddResource API in StylesheetRenderer; see comments
+ // in StylesheetRenderer.encodeEnd for details.
+
public boolean exists(ServletContext context, String resource)
{
+ resource = "/" + resource; // hack
return TextResourceFilter.getInstance(context).getFilteredResource(resource) != null;
}
public int getContentLength(ServletContext context, String resource) throws IOException
{
+ resource = "/" + resource; // hack
return TextResourceFilter.getInstance(context).getFilteredResource(resource).getSize();
}
public long getLastModified(ServletContext context, String resource) throws IOException
{
+ resource = "/" + resource; // hack
return TextResourceFilter.getInstance(context).getFilteredResource(resource).getLastModified();
}
public InputStream getInputStream(ServletContext context, String resource) throws IOException
{
+ resource = "/" + resource; // hack
return new ByteArrayInputStream(
TextResourceFilter.getInstance(context).getFilteredResource(resource).getText().getBytes(
getEncoding(context, resource)