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:
@@ -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;
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user