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] &nbsp; <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;
+        }
+    }
+}