[ 
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]

Reply via email to