>Velocity version?
The latest version ie 2.0.
>When you say you "shut down the container (tomcat)", >can you be more
specific? Do you bounce the >application, or do you >terminate Tomcat and
the JVM, >etc.?
Terminate tomcat shutdown.sh and then restart it.
>Did you write your own WebappResourceLoader (and if >so, why)?
Its a bit application so I do have my own version.
I did read on a list that it was an issue. Think Nathan
answered the post???
Maybe I have missed something in the code?
public class WebappResourceLoader extends ResourceLoader {
private static Log log = LogFactory.getLog(WebappResourceLoader.class);
// The root paths for templates (relative to webapp's root).
protected String[] paths = null;
protected HashMap<String, String> templatePaths = null;
protected ServletContext servletContext = null;
/**
* This is abstract in the base class, so we need it. 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 configuration
*/
@Override
public void init(ExtProperties configuration) {
if (log.isDebugEnabled())
log.debug("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] += "/";
}
if (log.isDebugEnabled())
log.debug("WebappResourceLoader: added template path -
'"
+ paths[i] + "'");
}
}
// Try out default
servletContext = EventsContext.getServletContext();
// get the ServletContext
if (servletContext == null) {
Object obj = rsvc
.getApplicationAttribute(ServletContext.class.getName()
);
if (obj instanceof ServletContext) {
servletContext = (ServletContext) obj;
} else {
log.error(
"WebappResourceLoader: unable to retrieve
ServletContext");
}
}
if (log.isDebugEnabled()) {
for (int i = 0; i < paths.length; i++) {
log.debug("Servlet Context = "
+ servletContext.getRealPath(paths[i]));
}
}
// init the template paths map
templatePaths = new HashMap<String, String>();
if (log.isDebugEnabled())
log.debug("WebappResourceLoader: initialization complete.");
}
/**
* Get an InputStream so that the Runtime can build a template with it.
*
* @param name
* name of template to get
* @param encoding
* the encoding
*
* @return InputStream containing the template
*
* @throws ResourceNotFoundException
* if template not found in classpath.
*/
@Override
public Reader getResourceReader(String name, String encoding)
throws ResourceNotFoundException {
// public synchronized InputStream getResourceStream(String name)
// throws ResourceNotFoundException {
InputStream result = null;
Exception exception = null;
if (name == null || name.length() == 0) {
throw new ResourceNotFoundException(
"WebappResourceLoader: No template name provided");
}
// names are <template>:<deviceType>
// loading events_macros.vm etc will not have the type so only
check for
// one.
String[] split = name.split(":", 2);
if (split.length < 1) {
throw new ResourceNotFoundException("Invalid ThemeRL key " +
name);
}
String savedPath = (String) templatePaths.get(name);
if (savedPath != null) {
result = servletContext.getResourceAsStream(savedPath +
split[0]);
}
if (result == null) {
for (int i = 0; i < paths.length; i++) {
String path = paths[i] + split[0];
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 on class path.";
// convert to a general Velocity ResourceNotFoundException
if (exception == null) {
throw new ResourceNotFoundException(msg);
} else {
msg += " Due to: " + exception;
throw new ResourceNotFoundException(msg, exception);
}
}
return new BufferedReader(new InputStreamReader(result));
}
/**
* Gets the cached file.
*
* @param rootPath
* the root path
* @param fileName
* the file name
*
* @return the cached file
*/
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);
// names are <template>:<deviceType>
// loading events_macros.vm etc will not have the type so only
check for
// one.
String[] split = fileName.split(":", 2);
return new File(rootPath + savedPath, split[0]);
}
/**
* Checks to see if a resource has been deleted, moved or modified. When
* using the resource.loader.cache=true option
*
* @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;
}
}
}
On 4 January 2017 at 16:04, Christopher Schultz <
[email protected]> wrote:
> Greg,
>
> On 1/4/17 8:43 AM, Greg Huber wrote:
> > The was one issue that has been around for ages, and I am not sure if it
> is
> > possible to fix it.
> >
> > If I have added a new macro into a velocity template file loaded via a
> > resource loader, I have to shut down the container (tomcat) and restart
> for
> > it to be picked up. I will allow the contents of the macro to be changed
> > but not a new macro. I did try to see if I could fix it but without much
> > success.
> >
> > my velocity.properties :
> > ..
> > webapp.resource.loader.description=Webapp Resource Loader
> > webapp.resource.loader.class=rendering.velocity.WebappResourceLoader
> > webapp.resource.loader.cache=true
> > webapp.resource.loader.path=/WEB-INF/velocity,/WEB-INF/
> velocity/templates,/WEB-INF/velocity/templates/feeds,/WEB-
> INF/velocity/templates/emails
> > ...
> >
> > If you are now familiar with the code you might be in a better position
> to
> > see why I have to shut down for it to be picked up.
>
> Velocity version?
>
> When you say you "shut down the container (tomcat)", can you be more
> specific? Do you bounce the application, or do you terminate Tomcat and
> the JVM, etc.?
>
> Did you write your own WebappResourceLoader (and if so, why)?
>
> -chris
>
>