diff --git a/projects/samskivert/lib/velocity-1.5-dev.jar b/projects/samskivert/lib/velocity-1.5-dev.jar deleted file mode 100644 index d0404754..00000000 Binary files a/projects/samskivert/lib/velocity-1.5-dev.jar and /dev/null differ diff --git a/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java b/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java index 08d77d57..bf86a63f 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java @@ -241,6 +241,7 @@ public class DispatcherServlet extends VelocityServlet Log.info("Velocity loading templates from site loader."); props.setProperty(RuntimeSingleton.RESOURCE_MANAGER_CLASS, SiteResourceManager.class.getName()); + _usingSiteLoading = true; } else { // otherwise use a servlet context resource loader Log.info("Velocity loading templates from servlet context."); @@ -287,7 +288,9 @@ public class DispatcherServlet extends VelocityServlet // context SiteIdentifier ident = _app.getSiteIdentifier(); int siteId = ident.identifySite(req); - ctx.put("__siteid__", new Integer(siteId)); + if (_usingSiteLoading) { + ctx.put("__siteid__", new Integer(siteId)); + } // put the context path in the context as well to make it easier // to construct full paths @@ -434,13 +437,14 @@ public class DispatcherServlet extends VelocityServlet protected Template selectTemplate (int siteId, InvocationContext ctx) throws ResourceNotFoundException, ParseErrorException, Exception { - // create a site resource key based on the template path and the - // id of the site through which this request was made String path = ctx.getRequest().getServletPath(); - SiteResourceKey key = new SiteResourceKey(siteId, path); - - // Log.info("Loading template [key=" + key + "]."); - return RuntimeSingleton.getRuntimeServices().getTemplate(key); + if (_usingSiteLoading) { + // if we're using site resource loading, we need to prefix the path + // with the site identifier + path = siteId + ":" + path; + } + // Log.info("Loading template [path=" + path + "]."); + return RuntimeSingleton.getRuntimeServices().getTemplate(path); } /** @@ -493,6 +497,9 @@ public class DispatcherServlet extends VelocityServlet /** The character set in which serve our responses. */ protected String _charset; + /** Set to true if we're using the {@link SiteResourceLoader}. */ + protected boolean _usingSiteLoading; + /** This is the key used in the context for error messages. */ protected static final String ERROR_KEY = "error"; diff --git a/projects/samskivert/src/java/com/samskivert/velocity/ImportDirective.java b/projects/samskivert/src/java/com/samskivert/velocity/ImportDirective.java index 3dc3ee34..e7b1b507 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/ImportDirective.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/ImportDirective.java @@ -72,13 +72,13 @@ public class ImportDirective extends Directive MethodInvocationException { // make sure an argument was supplied to the directive - if (node.jjtGetChild(0) == null) { + if (node.getChild(0) == null) { rsvc.error("#import() error : null argument"); return false; } // make sure that argument has a value - Object value = node.jjtGetChild(0).value(context); + Object value = node.getChild(0).value(context); if (value == null) { rsvc.error("#import() error : null argument"); return false; @@ -109,27 +109,29 @@ public class ImportDirective extends Directive rsvc.getProperty(RuntimeConstants.INPUT_ENCODING); } - // construct the template key based on the desired path and the - // site information in the current context. the siteid was shoved - // into the context by the dispatcher servlet. this is a hack, i - // know, but i couldn't convince the velocity peeps that we should - // have access to a request context in places like this + // adjust the template path with the site information in the current + // context if available. the siteid is shoved into the context by the + // dispatcher servlet when we're using the site resource loader. this + // is a hack, i know, but i couldn't convince the velocity peeps that + // we should have access to a request context in places like this Object siteIdVal = context.get("__siteid__"); - int siteId = SiteIdentifier.DEFAULT_SITE_ID; - try { - siteId = ((Integer)siteIdVal).intValue(); - } catch (Exception e) { - rsvc.error("#import() error: No siteId information in context."); + if (siteIdVal != null) { + int siteId = SiteIdentifier.DEFAULT_SITE_ID; + try { + siteId = ((Integer)siteIdVal).intValue(); + } catch (Exception e) { + rsvc.error("#import() error: No siteId information in context."); + } + path = siteId + ":" + path; } - Object tkey = new SiteResourceKey(siteId, path); // locate the requested template Template t = null; try { - t = rsvc.getTemplate(tkey, encoding); + t = rsvc.getTemplate(path, encoding); } catch (ResourceNotFoundException rnfe) { - rsvc.error("#import(): cannot find template '" + tkey + + rsvc.error("#import(): cannot find template '" + path + "', called from template " + context.getCurrentTemplateName() + " at (" + getLine() + ", " + getColumn() + ")"); @@ -137,13 +139,13 @@ public class ImportDirective extends Directive } catch (ParseErrorException pee) { rsvc.error("#import(): syntax error in #import()-ed template '" + - tkey + "', called from template " + + path + "', called from template " + context.getCurrentTemplateName() + " at (" + getLine() + ", " + getColumn() + ")"); throw pee; } catch (Exception e) { - rsvc.error("#import(): Error [path=" + tkey + + rsvc.error("#import(): Error [path=" + path + ", error=" + e + "]."); return false; } diff --git a/projects/samskivert/src/java/com/samskivert/velocity/ServletContextResourceManager.java b/projects/samskivert/src/java/com/samskivert/velocity/ServletContextResourceManager.java index 0db5565b..ba3734c0 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/ServletContextResourceManager.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/ServletContextResourceManager.java @@ -65,14 +65,14 @@ public class ServletContextResourceManager extends ResourceManagerImpl } protected Resource loadResource( - Object resourceKey, int resourceType, String encoding) + String resourceName, int resourceType, String encoding) throws ResourceNotFoundException, ParseErrorException, Exception { // create a blank new resource Resource resource = - ResourceFactory.getResource(resourceKey, resourceType); + ResourceFactory.getResource(resourceName, resourceType); resource.setRuntimeServices(rsvc); - resource.setKey(resourceKey); + resource.setName(resourceName); resource.setEncoding(encoding); resource.setResourceLoader(_contextLoader); diff --git a/projects/samskivert/src/java/com/samskivert/velocity/SiteJarResourceLoader.java b/projects/samskivert/src/java/com/samskivert/velocity/SiteJarResourceLoader.java index 171ee24a..fae65a25 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/SiteJarResourceLoader.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/SiteJarResourceLoader.java @@ -63,29 +63,24 @@ public class SiteJarResourceLoader extends ResourceLoader * Returns the input stream that can be used to load the named * resource. * - * @param resourceKey the locator key for the resource to be loaded. + * @param path the path for the resource to be loaded. * * @return an input stream that can be used to read the resource. * * @exception ResourceNotFoundException if the resource was not found. */ - public InputStream getResourceStream (Object resourceKey) + public InputStream getResourceStream (String path) throws ResourceNotFoundException { - SiteResourceKey skey = castKey(resourceKey); - if (skey == null) { - String errmsg = "Cannot use SiteResourceLoader without " + - "loading resources with SiteResourceKey instances."; - throw new ResourceNotFoundException(errmsg); - } + SiteKey skey = new SiteKey(path); // load it on up try { InputStream stream = _loader.getResourceAsStream( - skey.getSiteId(), skey.getPath()); + skey.siteId, skey.path); if (stream == null) { String errmsg = "Unable to load resource via " + - "site-specific jar file [key=" + skey + "]."; + "site-specific jar file [path=" + path + "]."; throw new ResourceNotFoundException(errmsg); } return stream; @@ -97,33 +92,27 @@ public class SiteJarResourceLoader extends ResourceLoader /** * Things won't ever be modified when loaded from the servlet context - * because they came from the webapp .war file and if that is - * reloaded, everything will be thrown away and started afresh. + * because they came from the webapp .war file and if that is reloaded, + * everything will be thrown away and started afresh. */ public boolean isSourceModified (Resource resource) { - SiteResourceKey skey = castKey(resource.getKey()); - if (skey == null) { - // return false if we were supplied with a bogus key - return false; - } + SiteKey skey = new SiteKey(resource.getName()); - // if the resource is for the default site, it is never considered - // to be modified - int siteId = skey.getSiteId(); - if (siteId == SiteIdentifier.DEFAULT_SITE_ID) { + // if the resource is for the default site, it is never considered to + // be modified + if (skey.siteId == SiteIdentifier.DEFAULT_SITE_ID) { return false; } else { - // otherwise compare the last modified time of the loaded - // resource with the last modified time of the associated - // site-specific jar file + // otherwise compare the last modified time of the loaded resource + // with that of the associated site-specific jar file try { return (resource.getLastModified() < - _loader.getLastModified(siteId)); + _loader.getLastModified(skey.siteId)); } catch (IOException ioe) { Log.warning("Failure obtaining last modified time of " + - "site-specific jar file [siteId=" + siteId + + "site-specific jar file [siteId=" + skey.siteId + ", error=" + ioe + "]."); return false; } @@ -132,49 +121,33 @@ public class SiteJarResourceLoader extends ResourceLoader /** * Things won't ever be modified when loaded from the servlet context - * because they came from the webapp .war file and if that is - * reloaded, everything will be thrown away and started afresh. So we - * can punt here and return zero. + * because they came from the webapp .war file and if that is reloaded, + * everything will be thrown away and started afresh. So we can punt here + * and return zero. */ public long getLastModified (Resource resource) { - SiteResourceKey skey = castKey(resource.getKey()); - if (skey == null) { - // return 0 if we were supplied with a bogus key - return 0; - } + SiteKey skey = new SiteKey(resource.getName()); - // if the resource is for the default site, it is never considered - // to be modified - int siteId = skey.getSiteId(); - if (siteId == SiteIdentifier.DEFAULT_SITE_ID) { + // if the resource is for the default site, it is never considered to + // be modified + if (skey.siteId == SiteIdentifier.DEFAULT_SITE_ID) { return 0; } else { // otherwise return the last modified time of the associated // site-specific jar file try { - return _loader.getLastModified(siteId); + return _loader.getLastModified(skey.siteId); } catch (IOException ioe) { Log.warning("Failure obtaining last modified time of " + - "site-specific jar file [siteId=" + siteId + + "site-specific jar file [siteId=" + skey.siteId + ", error=" + ioe + "]."); return 0; } } } - /** - * Casts the supplied resource key to a {@link SiteResourceKey} and - * returns it iff it is an instance of such. Returns null otherwise. - */ - protected SiteResourceKey castKey (Object resourceKey) - { - return (resourceKey instanceof SiteResourceKey) ? - (SiteResourceKey)resourceKey : null; - } - - /** A reference to the site resource loader through which we'll load - * things. */ + /** The site resource loader through which we'll load things. */ protected SiteResourceLoader _loader; } diff --git a/projects/samskivert/src/java/com/samskivert/velocity/SiteKey.java b/projects/samskivert/src/java/com/samskivert/velocity/SiteKey.java new file mode 100644 index 00000000..66ef567b --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/velocity/SiteKey.java @@ -0,0 +1,49 @@ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2004 Michael Bayne +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.velocity; + +import com.samskivert.Log; + +/** + * Decodes a compound Velocity resource name plus site identifier. + */ +public class SiteKey +{ + /** The site identifier associated with this path or -1 if no site + * identifier was specified in the path. */ + public int siteId = -1; + + /** The resource path. */ + public String path; + + public SiteKey (String path) + { + int cidx = path.indexOf(":"); + if (cidx == -1) { + this.path = path; + } else { + try { + siteId = Integer.parseInt(path.substring(0, cidx)); + } catch (Exception e) { + Log.warning("Invalid site path [path=" + path + "]."); + } + this.path = path.substring(cidx+1); + } + } +} diff --git a/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceKey.java b/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceKey.java deleted file mode 100644 index 5d4d85a2..00000000 --- a/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceKey.java +++ /dev/null @@ -1,180 +0,0 @@ -// -// $Id: SiteResourceKey.java,v 1.1 2001/11/06 04:49:32 mdb Exp $ -// -// samskivert library - useful routines for java programs -// Copyright (C) 2001 Michael Bayne -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -package com.samskivert.velocity; - -import com.samskivert.servlet.SiteIdentifier; -import com.samskivert.util.IntListUtil; -import com.samskivert.util.StringUtil; - -/** - * The site resource key is used as a key for resources that can be used - * for one or more sites. A resource always has the same path, but can be - * valid for a single site, or multiple sites and the set of sites for - * which a resource is valid can change without impacting the key's hash - * value. - */ -public class SiteResourceKey -{ - /** - * Constructs a new site resource key for the specified resource, - * loaded via the specified site. - */ - public SiteResourceKey (int siteId, String path) - { - _path = path; - _sites = new int[] { siteId }; - } - - /** - * Resource keys that contain only a single site id will return that - * site id as their primary. Those that contain multiple sites are - * assumed to reference default resources (which may be applicable to - * multiple sites) in which case the default site id is returned. - */ - public int getSiteId () - { - return (_sites.length == 1 ? _sites[0] : - SiteIdentifier.DEFAULT_SITE_ID); - } - - /** - * Returns the path to the resource referenced by this site resource - * key. - */ - public String getPath () - { - return _path; - } - - /** - * Returns true if this resource key contains the specified site in - * its site set. - */ - public boolean containsSite (int siteId) - { - return IntListUtil.contains(_sites, siteId); - } - - /** - * Adds a site to this site resource key. The resource to which this - * key maps is assumed to be valid for the added site. - */ - public void addSite (int siteId) - { - // sanity check - if (siteId == 0) { - throw new IllegalArgumentException( - "Site IDs cannot have the value 0."); - } - - // add the site to the list only if it's not already there - int[] sites = IntListUtil.testAndAdd(_sites, siteId); - if (sites != null) { - _sites = sites; - } - } - - /** - * Removes a site from this site resource key. The resource to which - * this key maps is no longer assumed to be valid for the removed - * site. - */ - public boolean removeSite (int siteId) - { - // sanity check - if (siteId == 0) { - throw new IllegalArgumentException( - "Site IDs cannot have the value 0."); - } - - // remove the site from the list - return (IntListUtil.remove(_sites, siteId) != 0); - } - - /** - * We hash to the hash value of our path. - */ - public int hashCode () - { - return _path.hashCode(); - } - - /** - * Two site resource keys are equal if the paths are the same and at - * least one site id overlaps between the two keys. Most equality - * comparisons will involve one multi-site key and one key that - * contains only a single site. - */ - public boolean equals (Object other) - { - if (other instanceof SiteResourceKey) { - SiteResourceKey okey = (SiteResourceKey)other; - - // make sure the paths match - if (!_path.equals(okey._path)) { - return false; - } - - // select the key with fewer sites in its sites array to be in - // the outer loop - int[] s1 = _sites; - int[] s2 = okey._sites; - if (s2.length < s1.length) { - s1 = s2; - s2 = _sites; - } - - for (int i1 = 0; i1 < s1.length; i1++) { - for (int i2 = 0; i2 < s2.length; i2++) { - if (s1[i1] == s2[i2]) { - return true; - } - } - } - } - - return false; - } - - /** - * The string representation of a resource key is just the path so - * that it is backwards compatible with older resource loaders. - */ - public String toString () - { - return _path; - } - - /** - * Returns a string description of this object. - */ - public String description () - { - return ("[path=" + _path + - ", sites=" + StringUtil.toString(_sites) + "]"); - } - - /** The path to the resource. */ - protected String _path; - - /** The sites for which this resource is valid. */ - protected int[] _sites; -} diff --git a/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceManager.java b/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceManager.java index fb53d5bc..2c22f898 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceManager.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/SiteResourceManager.java @@ -35,13 +35,8 @@ import com.samskivert.servlet.SiteResourceLoader; /** * A resource manager implementation for Velocity that first loads site - * specific resources (via the {@link SiteJarResourceLoader}), but falls - * back to default resources if no site-specific resource loader is - * available. - * - *
If this resource manager is to be used, resources must be fetched - * using {@link SiteResourceKey} objects as keys rather than simple - * strings. + * specific resources (via the {@link SiteJarResourceLoader}), but falls back + * to default resources if no site-specific resource loader is available. */ public class SiteResourceManager extends ResourceManagerImpl { @@ -87,37 +82,35 @@ public class SiteResourceManager extends ResourceManagerImpl } protected Resource loadResource( - Object resourceKey, int resourceType, String encoding) + String resourceName, int resourceType, String encoding) throws ResourceNotFoundException, ParseErrorException, Exception { + SiteKey skey = new SiteKey(resourceName); + // create a blank new resource Resource resource = - ResourceFactory.getResource(resourceKey, resourceType); + ResourceFactory.getResource(skey.path, resourceType); resource.setRuntimeServices(rsvc); - resource.setKey(resourceKey); resource.setEncoding(encoding); // if the resource was requested using a site resource key, we can - // attempt to load a site-specific version - if (resourceKey instanceof SiteResourceKey) { - SiteResourceKey rkey = (SiteResourceKey)resourceKey; - - // make sure the site we're loading for is not the default - // site, in which case we want to skip to the second resource - // loader directly - if (rkey.getSiteId() != SiteIdentifier.DEFAULT_SITE_ID) { - // try loading it via the site-specific resource loader - try { - resolveResource(resource, _siteLoader); - } catch (ResourceNotFoundException rnfe) { - // nothing to worry about here - } + // attempt to load a site-specific version; also make sure the site + // we're loading for is not the default site, in which case we want to + // skip to the second resource loader directly + if (skey.siteId != -1 && skey.siteId != SiteIdentifier.DEFAULT_SITE_ID) { + // try loading it via the site-specific resource loader + try { + resource.setName(resourceName); + resolveResource(resource, _siteLoader); + } catch (ResourceNotFoundException rnfe) { + // nothing to worry about here } } - // try the servlet context loader if we didn't find a - // site-specific resource + // try the servlet context loader if we didn't find a site-specific + // resource if (resource.getData() == null) { + resource.setName(skey.path); resolveResource(resource, _contextLoader); } @@ -135,8 +128,8 @@ public class SiteResourceManager extends ResourceManagerImpl resource.touch(); } - /** A reference to the servlet context through which we'll load - * default resources. */ + /** A reference to the servlet context through which we'll load default + * resources. */ protected ServletContext _sctx; /** A reference to the site identifier in use by the application. */