Many changes to provide site-specific resource loading (we're almost

there) and to bring things up to date with some Velocity changes Geir made
at my prompting.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@428 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2001-11-06 04:49:32 +00:00
parent 4d10799b9e
commit 3be945b22a
7 changed files with 786 additions and 55 deletions
@@ -1,5 +1,5 @@
//
// $Id: Application.java,v 1.4 2001/11/02 00:58:22 mdb Exp $
// $Id: Application.java,v 1.5 2001/11/06 04:49:32 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
@@ -38,10 +38,63 @@ import com.samskivert.util.StringUtil;
public class Application
{
/**
* This should be overridden by the application implementation to
* perform any necessary initialization.
* Performs initializations common to all applications. Applications
* should override {@link #willInit} to perform initializations that
* need to take place before the common initialization (which includes
* the creation of the site identifier and message manager) and should
* override {@link #didInit} to perform initializations that need to
* take place after the common initialization (like passing the
* application to entities that might turn around and request a
* reference to our site identifier).
*
* @param context the servlet context in which this application is
* operating.
* @param logicPkg the base package for all of the logic
* implementations for this application.
*/
public void init (ServletContext context)
public void init (ServletContext context, String logicPkg)
{
// keep this around for later
_context = context;
// let the derived application do pre-init stuff
willInit();
// remove any trailing dot
if (logicPkg.endsWith(".")) {
_logicPkg = logicPkg.substring(0, logicPkg.length()-1);
} else {
_logicPkg = logicPkg;
}
// instantiate our message manager if the application wants one
String bpath = getMessageBundlePath();
if (bpath != null) {
_msgmgr = new MessageManager(bpath);
}
// create our site identifier
_siteIdent = createSiteIdentifier(_context);
// let the derived application do post-init stuff
didInit();
}
/**
* This should be overridden by the application implementation to
* invoke any necessary pre-initialization code. They should be sure
* to call <code>super.willInit()</code>.
*/
protected void willInit ()
{
}
/**
* This should be overridden by the application implementation to
* invoke any necessary post-initialization code. They should be sure
* to call <code>super.didInit()</code>.
*/
protected void didInit ()
{
}
@@ -53,6 +106,15 @@ public class Application
{
}
/**
* Returns a reference to the servlet context in which this
* application is operating.
*/
public ServletContext getServletContext ()
{
return _context;
}
/**
* Returns the message manager in effect for this application, if one
* is in effect.
@@ -144,34 +206,6 @@ public class Application
return _msgmgr.getMessage(ctx.getRequest(), msg, args);
}
/**
* Performs initializations common to all applications. We could put
* this in {@link #init} and require application derived classes to
* call <code>super.init()</code> but we want it to happen after the
* application initializes itself.
*
* @param logicPkg the base package for all of the logic
* implementations for this application.
*/
protected void postInit (ServletContext ctx, String logicPkg)
{
// remove any trailing dot
if (logicPkg.endsWith(".")) {
_logicPkg = logicPkg.substring(0, logicPkg.length()-1);
} else {
_logicPkg = logicPkg;
}
// instantiate our message manager if the application wants one
String bpath = getMessageBundlePath();
if (bpath != null) {
_msgmgr = new MessageManager(bpath);
}
// create our site identifier
_siteIdent = createSiteIdentifier(ctx);
}
/**
* Given the servlet path (the part of the URI after the context path)
* this generates the classname of the logic class that should handle
@@ -190,6 +224,10 @@ public class Application
return _logicPkg + path;
}
/** A reference to the servlet context in which this application is
* operating. */
protected ServletContext _context;
/** The prefix that we use to generate fully qualified logic class
* names. */
protected String _logicPkg;
@@ -1,5 +1,5 @@
//
// $Id: DispatcherServlet.java,v 1.8 2001/11/02 18:46:48 mdb Exp $
// $Id: DispatcherServlet.java,v 1.9 2001/11/06 04:49:32 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
@@ -35,12 +35,14 @@ import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeSingleton;
import org.apache.velocity.servlet.VelocityServlet;
import com.samskivert.Log;
import com.samskivert.servlet.MessageManager;
import com.samskivert.servlet.RedirectException;
import com.samskivert.servlet.SiteIdentifier;
import com.samskivert.servlet.util.ExceptionMap;
import com.samskivert.servlet.util.FriendlyException;
@@ -162,16 +164,13 @@ public class DispatcherServlet extends VelocityServlet
/**
* Initialize ourselves and our application.
*/
public void init (ServletConfig config)
throws ServletException
protected void initVelocity (ServletConfig config)
throws ServletException
{
super.init(config);
// Log.info("Initializing dispatcher servlet.");
// load up our application configuration
try {
String appcl = config.getInitParameter(APP_CLASS_PROPS_KEY);
Log.info("Creating application [class=" + appcl + "].");
if (appcl == null) {
_app = new Application();
} else {
@@ -184,21 +183,17 @@ public class DispatcherServlet extends VelocityServlet
if (StringUtil.blank(logicPkg)) {
logicPkg = "";
}
_app.init(getServletContext());
_app.postInit(getServletContext(), logicPkg);
_app.init(getServletContext(), logicPkg);
} catch (Throwable t) {
Log.warning("Error instantiating application.");
Log.logStackTrace(t);
}
}
// documentation inherited
protected void initVelocity (ServletConfig config)
throws ServletException
{
// stick the servlet context into the Velocity application context
Velocity.setApplicationContext(getServletContext());
// stick the application into the Velocity application context
Velocity.setApplicationContext(_app);
// now let velocity initialize itself
super.initVelocity(config);
}
@@ -219,13 +214,20 @@ public class DispatcherServlet extends VelocityServlet
*/
public Template handleRequest (HttpServletRequest req,
HttpServletResponse rsp,
Context ctx) throws Exception
Context ctx)
throws Exception
{
InvocationContext ictx = (InvocationContext)ctx;
String errmsg = null;
// first we select the template
Template tmpl = selectTemplate(ictx);
// obtain the siteid for this request and stuff that into the
// context
SiteIdentifier ident = _app.getSiteIdentifier();
int siteId = ident.identifySite(req);
ctx.put("__siteid__", new Integer(siteId));
// then select the template
Template tmpl = selectTemplate(siteId, ictx);
// assume an HTML response unless otherwise massaged by the logic
rsp.setContentType("text/html");
@@ -313,12 +315,16 @@ public class DispatcherServlet extends VelocityServlet
*
* @return The template to be used in generating the response.
*/
protected Template selectTemplate (InvocationContext ctx)
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();
// Log.info("Loading template [path=" + path + "].");
return getTemplate(path);
SiteResourceKey key = new SiteResourceKey(siteId, path);
// Log.info("Loading template [key=" + key + "].");
return RuntimeSingleton.getRuntimeServices().getTemplate(key);
}
/**
@@ -0,0 +1,170 @@
//
// $Id: ImportDirective.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 java.io.IOException;
import java.io.Writer;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.Template;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import com.samskivert.servlet.SiteIdentifier;
import com.samskivert.util.StringUtil;
/**
* Pluggable directive that handles the #import() statement in VTL. Import
* is like #parse() except that it creates a {@link SiteResourceKey} based
* on information from the current request when fetching the imported
* template.
*/
public class ImportDirective extends Directive
{
/**
* Returns name of this directive.
*/
public String getName ()
{
return "import";
}
/**
* Return type of this directive.
*/
public int getType ()
{
return LINE;
}
/**
* Loads and renders the imported template.
*/
public boolean render (
InternalContextAdapter context, Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException,
MethodInvocationException
{
// make sure an argument was supplied to the directive
if (node.jjtGetChild(0) == null) {
rsvc.error("#import() error : null argument");
return false;
}
// make sure that argument has a value
Object value = node.jjtGetChild(0).value(context);
if (value == null) {
rsvc.error("#import() error : null argument");
return false;
}
// obtain the path to the desired template
String path = value.toString();
// make sure we haven't exceeded the configured parse depth
Object[] templateStack = context.getTemplateNameStack();
int maxlen = rsvc.getInt(
RuntimeConstants.PARSE_DIRECTIVE_MAXDEPTH, 20);
if (templateStack.length >= maxlen) {
rsvc.error("Max recursion depth reached (" + maxlen + "). " +
"File stack: " +
StringUtil.toString(templateStack) + ".");
return false;
}
// inherit the current encoding if there is a current template,
// otherwise use the configured encoding
String encoding = null;
Resource current = context.getCurrentResource();
if (current != null) {
encoding = current.getEncoding();
} else {
encoding = (String)
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
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.");
}
Object tkey = new SiteResourceKey(siteId, path);
// locate the requested template
Template t = null;
try {
t = rsvc.getTemplate(tkey, encoding);
} catch (ResourceNotFoundException rnfe) {
rsvc.error("#import(): cannot find template '" + tkey +
"', called from template " +
context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
throw rnfe;
} catch (ParseErrorException pee) {
rsvc.error("#import(): syntax error in #import()-ed template '" +
tkey + "', called from template " +
context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
throw pee;
} catch (Exception e) {
rsvc.error("#import(): Error [path=" + tkey +
", error=" + e + "].");
return false;
}
// finally render the template
try {
context.pushCurrentTemplateName(path);
((SimpleNode)t.getData()).render(context, writer);
} catch (Exception e) {
// we want to pass method invocation exceptions through
if (e instanceof MethodInvocationException) {
throw (MethodInvocationException)e;
}
rsvc.error("Exception rendering #import(" + path + "): " + e);
return false;
} finally {
context.popCurrentTemplateName();
}
return true;
}
}
@@ -1,5 +1,5 @@
//
// $Id: ServletContextResourceLoader.java,v 1.2 2001/11/02 02:30:24 mdb Exp $
// $Id: ServletContextResourceLoader.java,v 1.3 2001/11/06 04:49:32 mdb Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne
@@ -38,6 +38,24 @@ import org.apache.velocity.runtime.resource.loader.ResourceLoader;
*/
public class ServletContextResourceLoader extends ResourceLoader
{
/**
* When used with the default Velocity resource manager, we are
* constructed with our zero-argument constructor and later
* initialized via {@link #init}.
*/
public ServletContextResourceLoader ()
{
}
/**
* When used with the {@link SiteResourceManager} we are constructed
* with our servlet context reference and not later initialized.
*/
public ServletContextResourceLoader (ServletContext sctx)
{
_sctx = sctx;
}
/**
* Called by Velocity to initialize this resource loader.
*/
@@ -0,0 +1,182 @@
//
// $Id: SiteJarResourceLoader.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 java.io.InputStream;
import java.io.IOException;
import javax.servlet.ServletContext;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import com.samskivert.Log;
import com.samskivert.servlet.SiteIdentifier;
/**
* A Velocity resource loader that loads resources from site-specific jar
* files. This cannot be used with the default Velocity resource manager,
* but is used by the {@link SiteResourceManager} which automatically
* handles the creation and use of this resource loader.
*
* @see com.samskivert.servlet.SiteResourceLoader
*/
public class SiteResourceLoader extends ResourceLoader
{
/**
* Constructs a site resource loader that will use the specified site
* identifier to map site ids to site strings.
*/
public SiteResourceLoader (SiteIdentifier ident, ServletContext context)
{
// naming conflict... alas.
_loader = new com.samskivert.servlet.SiteResourceLoader(
ident, context);
}
/**
* This is not called.
*/
public void init (ExtendedProperties config)
{
}
/**
* Returns the input stream that can be used to load the named
* resource.
*
* @param resourceKey the locator key 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)
throws ResourceNotFoundException
{
SiteResourceKey skey = castKey(resourceKey);
if (skey == null) {
String errmsg = "Cannot use SiteResourceLoader without " +
"loading resources with SiteResourceKey instances.";
throw new ResourceNotFoundException(errmsg);
}
// load it on up
try {
InputStream stream = _loader.getResourceAsStream(
skey.getSiteId(), skey.getPath(), false);
if (stream == null) {
String errmsg = "Unable to load resource via " +
"site-specific jar file [key=" + skey + "].";
throw new ResourceNotFoundException(errmsg);
}
return stream;
} catch (IOException ioe) {
throw new ResourceNotFoundException(ioe.getMessage());
}
}
/**
* 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.
*/
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;
}
// 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) {
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
try {
return (resource.getLastModified() <
_loader.getLastModified(siteId));
} catch (IOException ioe) {
Log.warning("Failure obtaining last modified time of " +
"site-specific jar file [siteId=" + siteId +
", error=" + ioe + "].");
return false;
}
}
}
/**
* 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.
*/
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;
}
// 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) {
return 0;
} else {
// otherwise return the last modified time of the associated
// site-specific jar file
try {
return _loader.getLastModified(siteId);
} catch (IOException ioe) {
Log.warning("Failure obtaining last modified time of " +
"site-specific jar file [siteId=" + 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. */
protected com.samskivert.servlet.SiteResourceLoader _loader;
}
@@ -0,0 +1,180 @@
//
// $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;
}
@@ -0,0 +1,137 @@
//
// $Id: SiteResourceManager.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 javax.servlet.ServletContext;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.ResourceFactory;
import org.apache.velocity.runtime.resource.ResourceManagerImpl;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import com.samskivert.Log;
import com.samskivert.servlet.SiteIdentifier;
/**
* A resource manager implementation for Velocity that first loads site
* specific resources (via the {@link SiteResourceLoader}), but falls back
* to default resources if no site-specific resource loader is available.
*
* <p> If this resource manager is to be used, resources must be fetched
* using {@likn SiteResourceKey} objects as keys rather than simple
* strings.
*/
public class SiteResourceManager extends ResourceManagerImpl
{
public void initialize (RuntimeServices rsvc)
throws Exception
{
super.initialize(rsvc);
// the web framework was kind enough to slip this into the runtime
// instance when it started up
Application app = (Application)rsvc.getApplicationContext();
if (app == null) {
rsvc.warn("SiteResourceManager: Application reference " +
"was not supplied as application context. A " +
"user of the site resource manager must supply " +
"a reference to the Application instance via " +
"Velocity.setApplicationContext().");
}
// get handles on the good stuff
_sctx = app.getServletContext();
_ident = app.getSiteIdentifier();
// create our resource loaders
_siteLoader = new SiteResourceLoader(_ident, _sctx);
_contextLoader = new ServletContextResourceLoader(_sctx);
}
protected Resource loadResource(
Object resourceKey, int resourceType, String encoding)
throws ResourceNotFoundException, ParseErrorException, Exception
{
// create a blank new resource
Resource resource =
ResourceFactory.getResource(resourceKey, 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;
Log.info("Looking for site-specific version of " +
rkey.description() + ".");
// 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);
Log.info("Loaded site-specific [key=" + resourceKey + "].");
} catch (ResourceNotFoundException rnfe) {
// nothing to worry about here
}
}
}
// try the servlet context loader if we didn't find a
// site-specific resource
if (resource.getData() == null) {
resolveResource(resource, _contextLoader);
Log.info("Loaded default [key=" + resourceKey + "].");
}
return resource;
}
protected void resolveResource (Resource resource, ResourceLoader loader)
throws ResourceNotFoundException, ParseErrorException, Exception
{
resource.setResourceLoader(loader);
resource.process();
resource.setLastModified(loader.getLastModified(resource));
resource.setModificationCheckInterval(
loader.getModificationCheckInterval());
resource.touch();
}
/** 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. */
protected SiteIdentifier _ident;
/** We use this to load site-specific resources. */
protected SiteResourceLoader _siteLoader;
/** We use this to load default resources. */
protected ServletContextResourceLoader _contextLoader;
}