You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Alan Newberger <al...@plumbdesign.com> on 2002/01/22 20:04:55 UTC

StandardWrapper patch (was RE: shell connector)

Finally got around to packages my changes as a patch to the HEAD. As previously discussed, it should be sufficient for a servlet to implement ContainerServlet and for the class to be placed in the server/lib directory for it to load and initialize correctly (in a Context where privileged is true).  This is currently not the case, because in the current implementation being placed in the server/lib directory is not sufficient for the servlet to be loaded by the catalina class loader.  The attached StandardWrapper patch resolves this issue by attempting to load the servlet class in the catalina class loader if the context is privileged.

________________________________________________________________________
 
p l u m b d e s i g n
 
alan newberger 
chief architect
157 chambers st ny ny 10007
p.212.381.0541 | f.212.285.8999


> -----Original Message-----
> From: Alan Newberger 
> Sent: Friday, January 11, 2002 1:52 PM
> To: Tomcat Developers List
> Subject: RE: shell connector
> 
> 
> thanks for your reply, I still feel there is a problem with 
> ContainerServlets from arbitrary packages even when placed in 
> $CATALINA_HOME/server/lib, see below...
> 
> > From: Craig R. McClanahan [mailto:craigmcc@apache.org]
> > I committed some Ant custom tasks yesterday that talk to 
> > Manager ... they
> > might be useful to you.
> 
> I'll check them out, thanks.
> 
> 
> > So that one can write servlet-based services that need access 
> > to Catalina
> > internals.  Existing examples include:
> > * Manager servlet (needs to install, remove, and reload webapps)
> > * Invoker servlet (needs to create new Wrapper instances on the fly)
> > * Administration servlet (will provide web-based user interface for
> >   updating pretty much all of the things in server.xml).
> > 
> > The third thing is in the "admin" webapp in the HEAD branch.
> > 
> 
> That also sounds really useful, I'm going to have to take a 
> close look at the HEAD branch :) Hopefully it's capable of 
> persisting changes back into server.xml...
> 
> > In order to execute a ContainerServlet that has access to the 
> > internals of
> > Tomcat 4, the following rules must all be followed:
> > 
> > * Your servlet must implement the 
> org.apache.catalina.ContainerServlet
> >   interface.
> > 
> > * Your servlet, and all the code it depends on, must be 
> > loaded from the
> >   "server" classloader.  That means it needs to be installed 
> > as unpacked
> >   classes under $CATALINA_HOME/server/classes or in JAR files in
> >   $CATALINA_HOME/server/lib.  (Classes in common/classes and 
> > common/lib
> >   are also visible to these components.)
> > 
> > No changes to Tomcat code, or to standard server.xml settings, are
> > required.
> > 
> 
> IF a servlet which implements ContainerServlet is loaded by 
> the Catalina class loader, everything will work fine, i.e. it 
> will have its 'setWrapper()' command called by 
> StandardWrapper.load().  The problem is in the way 
> StandardWrapper decides which classloader to use to load the 
> servlet.  It uses its private 'isContainerServlet(string)' 
> method, which only looks at the String representation of the 
> className and checks if it starts with 'org.apache.catalina'. 
>  So, if I have a servlet implementing ContainerServlet in 
> some package, say 'com.foo.servlets', and put it in a jar 
> $CATALINA_HOME/server/lib, and create some webapp with a 
> web.xml with com.foo.servlets.SomeContainerServlet as a 
> 'server-class' for a servlet, things will still fail.  The 
> StandardWrapper.isContainerServlet(string classname) method 
> will return false, so the StandardWrapper.load() method will 
> try to load the class from the webapp classloader, which of 
> course will not find the class since it is not in the webapp 
> classpath.  You can put the 
> com.foo.servlets.SomeContainerServlet in the common/lib 
> folder and it will load correctly, but things will break 
> because no catalina classes will be visible to it (an object 
> instance cannot see other objects loaded in _child_ 
> classloaders, only _parent_ classloaders).
> 
> The solution to this isn't trivial -- you want all 
> ContainerServlets to be loaded in the catalina classloader, 
> but how do you know whether a servlet is a ContainerServlet 
> by its classname alone, before actually loading it and doing 
> something like 'instanceof' or 'isAssignableFrom()'?  I'm 
> sure this was why the StandardWrapper.isContainerServlet() 
> method was written but it just doesn't do the right thing.  I 
> think the way to a nicer solution is through the 'privileged' 
> attribute for a Context in servlet.xml (evaluated in 
> ServletWrapper via the isServletAllowed() function).  I 
> suggest that if a Context is designated as privileged, the 
> context's wrapper should attempt to load servlets via the 
> catalina classloader.  If the class isn't found, catch the 
> exception and attempt to load it via the webapp classloader.  
> If the class is loaded, check if it implements 
> ContainerServlet; if so, call setWrapper() on it and 
> continue, if not destroy the class object and attempt to load 
> it in the webapp classloader.  This is a bit more expensive 
> way of loading classes than what is done now, but if only 
> performed in Contexts marked 'privileged', most Context will 
> be unaffected and privileged Contexts would actually work :)  
> I'm fairly sure I'm right about this, I've read the code 
> pretty carefully and tested out the above behavior (i.e. I've 
> previously tried doing the two things you outline as 
> necessary above and things failed, it was a mystery until I 
> delved into StandardWrapper source). I'd be happy to code up 
> these proposed changes into StandardWrapper if you're interested.
> 
> -alan
> 
> --
> To unsubscribe, e-mail:   
> <ma...@jakarta.apache.org>
> For additional commands, e-mail: 
> <ma...@jakarta.apache.org>
> 
>