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:[EMAIL PROTECTED]] > 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: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>