[
https://issues.apache.org/jira/browse/VELOCITY-263?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Henning Schmiedehausen closed VELOCITY-263.
-------------------------------------------
> LogManager.createLogSystem does not use contextClassLoader
> ----------------------------------------------------------
>
> Key: VELOCITY-263
> URL: https://issues.apache.org/jira/browse/VELOCITY-263
> Project: Velocity
> Issue Type: Bug
> Components: Engine
> Affects Versions: 1.4
> Environment: Operating System: Linux
> Platform: All
> Reporter: Steve Revilak
> Assigned To: Velocity-Dev List
>
> We use velocity-1.4 as part of a web application; it processes
> templates that are served to clients as html files. The servlet
> container used is tomcat 5.0.18. Things are laid out like this:
> * CATALINA_HOME/shared/lib/velocity.jar
> (along with other third-party libraries)
> Our class files:
> * CATALINA_HOME/webapps/<context>/WEB-INF/classes
> * CATALINA_HOME/webapps/<context>/WEB-INF/lib
> Recently, we attempted to add our own logging class
> (implements org.apache.velocity.runtime.log.LogSystem). In doing so,
> I believe I have discovered a bug in velocity's LogManager class.
> Our logger is com.r9.nucleus.velocity.Logger
> runtime.log.logsystem.class=com.r9.nucleus.velocity.Logger
> com.r9.nucleus.velocity.Logger lives in a jar in WEB-INF/lib.
> A servlet (in the same jar file) can locate, instantiate, and use this
> class directly. However, when velocity attempts to use it, we get
> this:
> java.lang.ClassNotFoundException: com.r9.nucleus.velocity.Logger
> at
> org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClassLoader.java:891)
> at
> org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClassLoader.java:756)
> at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
> at java.lang.Class.forName0(Native Method)
> at java.lang.Class.forName(Class.java:141)
> at
> org.apache.velocity.runtime.log.LogManager.createLogSystem(LogManager.java:123)
> at
> org.apache.velocity.runtime.RuntimeInstance.initializeLogger(RuntimeInstance.java:553)
> at
> org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:226)
> at
> org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:461)
> at
> org.apache.velocity.app.VelocityEngine.init(VelocityEngine.java:106)
> at
> com.r9.nucleus.velocity.VelocityUtils.createVelocityEngine(VelocityUtils.java:83)
> at
> com.r9.seeker.template.FormTemplate.getEngine(FormTemplate.java:519)
> at com.r9.seeker.template.FormTemplate.parse(FormTemplate.java:99)
> at
> com.r9.seeker.scrape.AirScraper.populateAndParseTemplate(AirScraper.java:200)
> at
> com.r9.seeker.scrape.AirScraper.retrieveResultsPage(AirScraper.java:174)
> at com.r9.seeker.scrape.AirScraper.specificSearch(AirScraper.java:104)
> at com.r9.seeker.core.MultiSearcher.search(MultiSearcher.java:167)
> at
> com.r9.seeker.core.SearchThreadPool$RunnableSearch.run(SearchThreadPool.java:82)
> at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(Unknown
> Source)
> at java.lang.Thread.run(Thread.java:534)
> Here is the relevant section of LogManager.createLogSystem (w/line
> numbers).
> 107 /*
> 108 * now run through the list, trying each. It's ok to
> 109 * fail with a class not found, as we do this to also
> 110 * search out a default simple file logger
> 111 */
> 112
> 113 for( Iterator ii = classes.iterator(); ii.hasNext(); )
> 114 {
> 115 String claz = (String) ii.next();
> 116
> 117 if (claz != null && claz.length() > 0 )
> 118 {
> 119 rsvc.info("Trying to use logger class " + claz
> );
> 120
> 121 try
> 122 {
> 123 >>> HERE >>> o = Class.forName( claz ).newInstance();
> 124
> 125 if ( o instanceof LogSystem )
> 126 {
> 127 ((LogSystem) o).init( rsvc );
> 128
> 129 rsvc.info("Using logger class " + claz
> );
> 130
> 131 return (LogSystem) o;
> 132 }
> 133 else
> 134 {
> 135 rsvc.error("The specifid logger class "
> + claz +
> 136 " isn't a valid LogSystem");
> 137 }
> 138 }
> 139 catch( NoClassDefFoundError ncdfe )
> 140 {
> 141 rsvc.debug("Couldn't find class " + claz
> 142 + " or necessary supporting
> classes in "
> 143 + "classpath. Exception : " +
> ncdfe);
> 144 }
> 145 }
> 146 }
> This is what appears to be happening:
> - velocity.jar is loaded by tomcat's shared loader.
> - a servlet can instantiate and use our Logger class directly; they
> both fall under the same tomcat WebAppClassLoader.
> - LogManager fails because it's using Class.forName() - attempting to
> use the Shared classloader that loaded velocity.jar. This
> classloader cannot has no visibility into the webapp classloader
> repository.
> Would it be possible to consider changing this:
> 123 >>> HERE >>> o = Class.forName( claz ).newInstance();
> to something like:
> ClassLoader loader = Thread.currentThread().getContextClassLoader();
> if (loader == null) {
> loader = getClass().getClassLoader();
> }
> o = Class.forName(claz, true, loader).newInstance();
> This should allow LogManager to have the same class visibility as the
> executing servlet thread.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]