You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/06/17 11:48:24 UTC
svn commit: r955528 - in /click/trunk/click:
documentation/docs/developer-guide/ framework/src/org/apache/click/
framework/src/org/apache/click/service/
framework/src/org/apache/velocity/tools/view/
framework/src/org/apache/velocity/tools/view/servlet/
Author: sabob
Date: Thu Jun 17 09:48:24 2010
New Revision: 955528
URL: http://svn.apache.org/viewvc?rev=955528&view=rev
Log:
Switched to Velocity Tools 2.0 WebappResourceLoader. CLK-693
Added:
click/trunk/click/framework/src/org/apache/velocity/tools/view/WebappResourceLoader.java
Removed:
click/trunk/click/framework/src/org/apache/velocity/tools/view/servlet/
Modified:
click/trunk/click/documentation/docs/developer-guide/building.html
click/trunk/click/framework/src/org/apache/click/Control.java
click/trunk/click/framework/src/org/apache/click/service/VelocityTemplateService.java
Modified: click/trunk/click/documentation/docs/developer-guide/building.html
URL: http://svn.apache.org/viewvc/click/trunk/click/documentation/docs/developer-guide/building.html?rev=955528&r1=955527&r2=955528&view=diff
==============================================================================
--- click/trunk/click/documentation/docs/developer-guide/building.html (original)
+++ click/trunk/click/documentation/docs/developer-guide/building.html Thu Jun 17 09:48:24 2010
@@ -232,9 +232,9 @@ The Click framework has the following ru
</tr>
<tr>
<td>Velocity Tools</td>
- <td>1.1</td>
- <td>WebappLoader source<span class="red">**</span></td>
- <td><a target="_blank" href="http://jakarta.apache.org/velocity/tools/">Jakarta Velocity Tools</a></td>
+ <td>2.0</td>
+ <td>WebappResourceLoader source<span class="red">**</span></td>
+ <td><a target="_blank" href="http://velocity.apache.org/tools/releases/2.0/">Jakarta Velocity Tools</a></td>
<td>Velocity Tools Utility Library</td>
</tr>
<tr>
Modified: click/trunk/click/framework/src/org/apache/click/Control.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Control.java?rev=955528&r1=955527&r2=955528&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Control.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Control.java Thu Jun 17 09:48:24 2010
@@ -67,7 +67,7 @@ import org.apache.click.util.HtmlStringB
* <a name="on-deploy"></a>
* <h4>Deploying Resources</h4>
*
- * The Click framework uses the Velocity Tools <tt>WebappLoader</tt> for loading templates.
+ * The Click framework uses the Velocity Tools <tt>WebappResourceLoader</tt> for loading templates.
* This avoids issues associate with using the Velocity <tt>ClasspathResourceLoader</tt> and
* <tt>FileResourceLoader</tt> on J2EE application servers.
* To make preconfigured resources (templates, JavaScript, stylesheets, etc.)
Modified: click/trunk/click/framework/src/org/apache/click/service/VelocityTemplateService.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/service/VelocityTemplateService.java?rev=955528&r1=955527&r2=955528&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/service/VelocityTemplateService.java (original)
+++ click/trunk/click/framework/src/org/apache/click/service/VelocityTemplateService.java Thu Jun 17 09:48:24 2010
@@ -48,7 +48,7 @@ import org.apache.velocity.runtime.Runti
import org.apache.velocity.runtime.log.LogChute;
import org.apache.velocity.runtime.parser.TemplateParseException;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
-import org.apache.velocity.tools.view.servlet.WebappLoader;
+import org.apache.velocity.tools.view.WebappResourceLoader;
import org.apache.velocity.util.SimplePool;
/**
@@ -83,7 +83,7 @@ import org.apache.velocity.util.SimplePo
* <pre class="codeConfig">
* resource.loader=<span class="blue">webapp</span>, <span class="red">class</span>
*
- * <span class="blue">webapp</span>.resource.loader.class=org.apache.velocity.tools.view.servlet.WebappLoader
+ * <span class="blue">webapp</span>.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
* <span class="blue">webapp</span>.resource.loader.cache=[true|false] <span class="green">#depending on application mode</span>
* <span class="blue">webapp</span>.resource.loader.modificationCheckInterval=0 <span class="green">#depending on application mode</span>
*
@@ -95,7 +95,7 @@ import org.apache.velocity.util.SimplePo
* velocimacro.library=click/VM_global_library.vm
* </pre>
*
- * This service uses the Velocity Tools WebappLoader for loading templates.
+ * This service uses the Velocity Tools WebappResourceLoader for loading templates.
* This avoids issues associate with using the Velocity FileResourceLoader on JEE
* application servers.
* <p/>
@@ -263,7 +263,7 @@ public class VelocityTemplateService imp
velocityEngine.setApplicationAttribute(ConfigService.class.getName(),
configService);
- // Set ServletContext instance for WebappLoader
+ // Set ServletContext instance for WebappResourceLoader
velocityEngine.setApplicationAttribute(ServletContext.class.getName(),
configService.getServletContext());
@@ -387,7 +387,7 @@ public class VelocityTemplateService imp
velProps.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp, class");
velProps.setProperty("webapp.resource.loader.class",
- WebappLoader.class.getName());
+ WebappResourceLoader.class.getName());
velProps.setProperty("class.resource.loader.class",
ClasspathResourceLoader.class.getName());
Added: click/trunk/click/framework/src/org/apache/velocity/tools/view/WebappResourceLoader.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/velocity/tools/view/WebappResourceLoader.java?rev=955528&view=auto
==============================================================================
--- click/trunk/click/framework/src/org/apache/velocity/tools/view/WebappResourceLoader.java (added)
+++ click/trunk/click/framework/src/org/apache/velocity/tools/view/WebappResourceLoader.java Thu Jun 17 09:48:24 2010
@@ -0,0 +1,285 @@
+package org.apache.velocity.tools.view;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
+import javax.servlet.ServletContext;
+import org.apache.commons.collections.ExtendedProperties;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.runtime.resource.Resource;
+import org.apache.velocity.runtime.resource.loader.ResourceLoader;
+
+/**
+ * Resource loader that uses the ServletContext of a webapp to
+ * load Velocity templates. (it's much easier to use with servlets than
+ * the standard FileResourceLoader, in particular the use of war files
+ * is transparent).
+ *
+ * The default search path is '/' (relative to the webapp root), but
+ * you can change this behaviour by specifying one or more paths
+ * by mean of as many webapp.resource.loader.path properties as needed
+ * in the velocity.properties file.
+ *
+ * All paths must be relative to the root of the webapp.
+ *
+ * To enable caching and cache refreshing the webapp.resource.loader.cache and
+ * webapp.resource.loader.modificationCheckInterval properties need to be
+ * set in the velocity.properties file ... auto-reloading of global macros
+ * requires the webapp.resource.loader.cache property to be set to 'false'.
+ *
+ * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
+ * @author Nathan Bubna
+ * @author <a href="mailto:claude@savoirweb.com">Claude Brisson</a>
+ * @version $Id$ */
+
+public class WebappResourceLoader extends ResourceLoader
+{
+ /** The root paths for templates (relative to webapp's root). */
+ protected String[] paths = null;
+ protected HashMap templatePaths = null;
+ protected ServletContext servletContext = null;
+
+
+ /**
+ * This is abstract in the base class, so we need it.
+ * <br>
+ * NOTE: this expects that the ServletContext has already
+ * been placed in the runtime's application attributes
+ * under its full class name (i.e. "javax.servlet.ServletContext").
+ *
+ * @param configuration the {@link ExtendedProperties} associated with
+ * this resource loader.
+ */
+ public void init(ExtendedProperties configuration)
+ {
+ log.trace("WebappResourceLoader: initialization starting.");
+
+ /* get configured paths */
+ paths = configuration.getStringArray("path");
+ if (paths == null || paths.length == 0)
+ {
+ paths = new String[1];
+ paths[0] = "/";
+ }
+ else
+ {
+ /* make sure the paths end with a '/' */
+ for (int i=0; i < paths.length; i++)
+ {
+ if (!paths[i].endsWith("/"))
+ {
+ paths[i] += '/';
+ }
+ log.info("WebappResourceLoader: added template path - '" + paths[i] + "'");
+ }
+ }
+
+ /* get the ServletContext */
+ Object obj = rsvc.getApplicationAttribute(ServletContext.class.getName());
+ if (obj instanceof ServletContext)
+ {
+ servletContext = (ServletContext)obj;
+ }
+ else
+ {
+ log.error("WebappResourceLoader: unable to retrieve ServletContext");
+ }
+
+ /* init the template paths map */
+ templatePaths = new HashMap();
+
+ log.trace("WebappResourceLoader: initialization complete.");
+ }
+
+ /**
+ * Get an InputStream so that the Runtime can build a
+ * template with it.
+ *
+ * @param name name of template to get
+ * @return InputStream containing the template
+ * @throws ResourceNotFoundException if template not found
+ * in classpath.
+ */
+ public synchronized InputStream getResourceStream(String name)
+ throws ResourceNotFoundException
+ {
+ InputStream result = null;
+
+ if (name == null || name.length() == 0)
+ {
+ throw new ResourceNotFoundException("WebappResourceLoader: No template name provided");
+ }
+
+ /* since the paths always ends in '/',
+ * make sure the name never starts with one */
+ while (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ Exception exception = null;
+ for (int i = 0; i < paths.length; i++)
+ {
+ String path = paths[i] + name;
+ try
+ {
+ result = servletContext.getResourceAsStream(path);
+
+ /* save the path and exit the loop if we found the template */
+ if (result != null)
+ {
+ templatePaths.put(name, paths[i]);
+ break;
+ }
+ }
+ catch (NullPointerException npe)
+ {
+ /* no servletContext was set, whine about it! */
+ throw npe;
+ }
+ catch (Exception e)
+ {
+ /* only save the first one for later throwing */
+ if (exception == null)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("WebappResourceLoader: Could not load "+path, e);
+ }
+ exception = e;
+ }
+ }
+ }
+
+ /* if we never found the template */
+ if (result == null)
+ {
+ String msg = "WebappResourceLoader: Resource '" + name + "' not found.";
+
+ /* convert to a general Velocity ResourceNotFoundException */
+ if (exception == null)
+ {
+ throw new ResourceNotFoundException(msg);
+ }
+ else
+ {
+ msg += " Due to: " + exception;
+ throw new ResourceNotFoundException(msg, exception);
+ }
+ }
+ return result;
+ }
+
+ private File getCachedFile(String rootPath, String fileName)
+ {
+ // we do this when we cache a resource,
+ // so do it again to ensure a match
+ while (fileName.startsWith("/"))
+ {
+ fileName = fileName.substring(1);
+ }
+
+ String savedPath = (String)templatePaths.get(fileName);
+ return new File(rootPath + savedPath, fileName);
+ }
+
+
+ /**
+ * Checks to see if a resource has been deleted, moved or modified.
+ *
+ * @param resource Resource The resource to check for modification
+ * @return boolean True if the resource has been modified
+ */
+ public boolean isSourceModified(Resource resource)
+ {
+ String rootPath = servletContext.getRealPath("/");
+ if (rootPath == null) {
+ // rootPath is null if the servlet container cannot translate the
+ // virtual path to a real path for any reason (such as when the
+ // content is being made available from a .war archive)
+ return false;
+ }
+
+ // first, try getting the previously found file
+ String fileName = resource.getName();
+ File cachedFile = getCachedFile(rootPath, fileName);
+ if (!cachedFile.exists())
+ {
+ /* then the source has been moved and/or deleted */
+ return true;
+ }
+
+ /* check to see if the file can now be found elsewhere
+ * before it is found in the previously saved path */
+ File currentFile = null;
+ for (int i = 0; i < paths.length; i++)
+ {
+ currentFile = new File(rootPath + paths[i], fileName);
+ if (currentFile.canRead())
+ {
+ /* stop at the first resource found
+ * (just like in getResourceStream()) */
+ break;
+ }
+ }
+
+ /* if the current is the cached and it is readable */
+ if (cachedFile.equals(currentFile) && cachedFile.canRead())
+ {
+ /* then (and only then) do we compare the last modified values */
+ return (cachedFile.lastModified() != resource.getLastModified());
+ }
+ else
+ {
+ /* we found a new file for the resource
+ * or the resource is no longer readable. */
+ return true;
+ }
+ }
+
+ /**
+ * Checks to see when a resource was last modified
+ *
+ * @param resource Resource the resource to check
+ * @return long The time when the resource was last modified or 0 if the file can't be read
+ */
+ public long getLastModified(Resource resource)
+ {
+ String rootPath = servletContext.getRealPath("/");
+ if (rootPath == null) {
+ // rootPath is null if the servlet container cannot translate the
+ // virtual path to a real path for any reason (such as when the
+ // content is being made available from a .war archive)
+ return 0;
+ }
+
+ File cachedFile = getCachedFile(rootPath, resource.getName());
+ if (cachedFile.canRead())
+ {
+ return cachedFile.lastModified();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}