You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Chefo <ch...@gmail.com> on 2010/08/26 15:38:17 UTC

Access StandardContext in WebappClassLoader

Hi guys,

I'm using tomcat 6.0.18 adapted to osgi environment and I would like to make
the WebappClassLoader configurable so that it does not load certain packages
directly through the system class loader but use the class loader hierarchy
instead. In order to do that I have extended the standard webapp class
loader and configured the container to use the new one in the base
context.xml. I want to configure the packages through a context parameter
(separately for each webapp) or eventually through an env-entry. However I
cannot find a way to access the StandardContext instance in my
WebappClassLoader. This is probably a very simple thing to do but I'm not
really well familiar with catalina API and this is kinda driving me crazy.
Any help/suggestion is more than welcome.

Thanks in advance
Stefan

Re: Access StandardContext in WebappClassLoader

Posted by Pid <pi...@pidster.com>.
On 30/08/2010 10:13, Chefo wrote:
> Hi Chris,
> 
> On Sat, Aug 28, 2010 at 1:12 AM, Christopher Schultz <
> chris@christopherschultz.net> wrote:
> 
> Stefan,
> 
> On 8/27/2010 7:34 AM, Chefo wrote:
>>>> thanks for the interest - of course I'll give you an example.
> Surprisingly
>>>> it is not java.lang.Object that I'm trying to hide but the stax api in
> java
>>>> 6. I need to do so because of the notorious fault in the
>>>> XMLOutputFactory#newInstance(String, ClassLoader).
> 
> Interesting.
> 
> Why not simply put your replacement STAX into the system's endorsed
> libraries? Wouldn't that fix pretty much everything, and require much
> less work?
> 
> 
>> Anathema!
>> Messing with the endorsed libs is strongly discouraged (and considered
>> heresy) around here. Otherwise yeah - that was my first thought also.

So you're inventing a new way of doing things instead?


p

>>>> The thing is that osgi runtime in which the catalina lives complicates
> the
>>>> class loading a bit.
>>>> Note that this black voodoo magic for configuring restricted system
> packages
>>>> is not something I've invented - I just saw there is such thing in jetty
> and
>>>> was extremely happy to see it could be implemented with little effort in
>>>> tomcat as well.
> 
> Jetty is OSS... can you steal their ClassLoader implementation?
> 
> 
>> Hey I sense some negative connotation here - I got the idea from there. I'm
>> extending the catalina webapp class loader (basically adding 5-6 lines of
>> code) and it has nothing in common with jetty src.
> 
> 
> I highly recommend Rainer's suggestion of writing a loader to configure
> your ClassLoader, rather than trying to get the ClassLoader to configure
> itself (always tricky).
> 
> Good luck, and let us know how it goes.
> 
> 
>> Sure already followed Rainer's advice - worked perfectly fine.
>> Thanks again for all the help guys.
> 
> 
> 
> -chris
>>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
> Best regards,
> chefo


Re: Access StandardContext in WebappClassLoader

Posted by Chefo <ch...@gmail.com>.
Hi Chris,

On Sat, Aug 28, 2010 at 1:12 AM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Stefan,
>
> On 8/27/2010 7:34 AM, Chefo wrote:
> > thanks for the interest - of course I'll give you an example.
> Surprisingly
> > it is not java.lang.Object that I'm trying to hide but the stax api in
> java
> > 6. I need to do so because of the notorious fault in the
> > XMLOutputFactory#newInstance(String, ClassLoader).
>
> Interesting.
>
> Why not simply put your replacement STAX into the system's endorsed
> libraries? Wouldn't that fix pretty much everything, and require much
> less work?
>

Anathema!
Messing with the endorsed libs is strongly discouraged (and considered
heresy) around here. Otherwise yeah - that was my first thought also.


>
> > The thing is that osgi runtime in which the catalina lives complicates
> the
> > class loading a bit.
> > Note that this black voodoo magic for configuring restricted system
> packages
> > is not something I've invented - I just saw there is such thing in jetty
> and
> > was extremely happy to see it could be implemented with little effort in
> > tomcat as well.
>
> Jetty is OSS... can you steal their ClassLoader implementation?
>

Hey I sense some negative connotation here - I got the idea from there. I'm
extending the catalina webapp class loader (basically adding 5-6 lines of
code) and it has nothing in common with jetty src.

>
> I highly recommend Rainer's suggestion of writing a loader to configure
> your ClassLoader, rather than trying to get the ClassLoader to configure
> itself (always tricky).
>
> Good luck, and let us know how it goes.
>

Sure already followed Rainer's advice - worked perfectly fine.
Thanks again for all the help guys.


>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAkx4OGAACgkQ9CaO5/Lv0PD+TACeOVU9e2L41rqdmZ8pRx/DIktv
> Rh0An1OC5U/ZXarXx7e2xEAwt7DPyB5+
> =BvEJ
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>
Best regards,
chefo

Re: Access StandardContext in WebappClassLoader

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stefan,

On 8/27/2010 7:34 AM, Chefo wrote:
> thanks for the interest - of course I'll give you an example. Surprisingly
> it is not java.lang.Object that I'm trying to hide but the stax api in java
> 6. I need to do so because of the notorious fault in the
> XMLOutputFactory#newInstance(String, ClassLoader).

Interesting.

Why not simply put your replacement STAX into the system's endorsed
libraries? Wouldn't that fix pretty much everything, and require much
less work?

> The thing is that osgi runtime in which the catalina lives complicates the
> class loading a bit.
> Note that this black voodoo magic for configuring restricted system packages
> is not something I've invented - I just saw there is such thing in jetty and
> was extremely happy to see it could be implemented with little effort in
> tomcat as well.

Jetty is OSS... can you steal their ClassLoader implementation?

I highly recommend Rainer's suggestion of writing a loader to configure
your ClassLoader, rather than trying to get the ClassLoader to configure
itself (always tricky).

Good luck, and let us know how it goes.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkx4OGAACgkQ9CaO5/Lv0PD+TACeOVU9e2L41rqdmZ8pRx/DIktv
Rh0An1OC5U/ZXarXx7e2xEAwt7DPyB5+
=BvEJ
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Access StandardContext in WebappClassLoader

Posted by Chefo <ch...@gmail.com>.
Hi Chris,

thanks for the interest - of course I'll give you an example. Surprisingly
it is not java.lang.Object that I'm trying to hide but the stax api in java
6. I need to do so because of the notorious fault in the
XMLOutputFactory#newInstance(String, ClassLoader). Therefore I'm using using
stax-api 1.0.1 that is available through the equinox my catalina lives in
(mentioned in my first post). I also have a woodstox implementation as a
bundle. The situation is the following - a web application tries to obtain a
factory instance through the api. The XMLOutputFactory class is loaded
through the webapp class loader from the system class loader. The woodstox
implementation is found (as osgi bundle) and it is instantiated. When
the com.ctc.wstx.stax.WstxInputFactory / WstxOutputFactory class is loaded
from the osgi bundle class loader it has been identified correctly as
implementing the XMLInput/OutputFactory loaded from the stax-api bundle
again in the osgi. Thus I end up with the following exception in my web
application:

"java.lang.ClassCastException: com.ctc.wstx.stax.WstxInputFactory cannot be
cast to javax.xml.stream.XMLInputFactory"

The thing is that osgi runtime in which the catalina lives complicates the
class loading a bit.
Note that this black voodoo magic for configuring restricted system packages
is not something I've invented - I just saw there is such thing in jetty and
was extremely happy to see it could be implemented with little effort in
tomcat as well.

Best regards,
Stefan



On Thu, Aug 26, 2010 at 8:28 PM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Chefo,
>
> On 8/26/2010 11:24 AM, Chefo wrote:
> > What bothers me in the WebappClassLoader is the fact that before it
> checks
> > its repositories (lib folder and classes) and asks its parent class
> loader,
> > it will first attempt to load a class from the system class loader - from
> > the jvm.
>
> That's supposed to be how it's done: webapps aren't supposed to be able
> to subvert the JVM by loading their own definitions for, say,
> java.lang.Object.
>
> > I want to prevent that for certain packages and I
> > want it to be configurable for each web application.
>
> Can you give me an example of when this would be a good idea?
>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAkx2pEMACgkQ9CaO5/Lv0PCQiQCgrrlP1MmzO7zfg+db81i+h82D
> 4eAAn3I5g/Vb1JPpaC24jzfGLNhqMwT7
> =uIHX
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: Access StandardContext in WebappClassLoader

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chefo,

On 8/26/2010 11:24 AM, Chefo wrote:
> What bothers me in the WebappClassLoader is the fact that before it checks
> its repositories (lib folder and classes) and asks its parent class loader,
> it will first attempt to load a class from the system class loader - from
> the jvm.

That's supposed to be how it's done: webapps aren't supposed to be able
to subvert the JVM by loading their own definitions for, say,
java.lang.Object.

> I want to prevent that for certain packages and I
> want it to be configurable for each web application.

Can you give me an example of when this would be a good idea?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkx2pEMACgkQ9CaO5/Lv0PCQiQCgrrlP1MmzO7zfg+db81i+h82D
4eAAn3I5g/Vb1JPpaC24jzfGLNhqMwT7
=uIHX
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Access StandardContext in WebappClassLoader

Posted by Chefo <ch...@gmail.com>.
Great idea. I'll give it a try immediately!

Thanks a lot,
Chefo

On Thu, Aug 26, 2010 at 6:43 PM, Rainer Jung <ra...@kippdata.de>wrote:

> On 26.08.2010 17:24, Chefo wrote:
>
>> Hi again
>>
>> and thanks for the quick responses.
>>
>> What bothers me in the WebappClassLoader is the fact that before it checks
>> its repositories (lib folder and classes) and asks its parent class
>> loader,
>> it will first attempt to load a class from the system class loader - from
>> the jvm. This is not standard classloader logic but sth done on purpose in
>> the webapp class loader. I want to prevent that for certain packages and I
>> want it to be configurable for each web application. That's why I wrote my
>> WebappClassLoader and configured its usage in the default context.xml
>> (<Loader loaderClass="org.chefo.OSGiWebappClassLoader"/>  in<catalina
>> home>/conf/context/xml). I figured the easiest way to configure a list of
>> packages that should not be loaded through the system class loader is with
>> a
>> parameter in the context of the web application, thus I need to access a
>> context parameter in my webapp class loader. I thought it would be normal
>> for the webapp class loader to be able to access the context that is
>> associated with it...
>>
>> Hope that makes it a bit clearer...
>>
>
> You can configure your loader by extending WebappLoader (not only
> WebappClassLoader) and then using attributes in the loader element you added
> to context.xml (and corresponding setters in the loader implementation).
>
> For an example see
>
>
> http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/loader/VirtualWebappLoader.html
>
> Regards,
>
> Rainer
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: Access StandardContext in WebappClassLoader

Posted by Rainer Jung <ra...@kippdata.de>.
On 26.08.2010 17:24, Chefo wrote:
> Hi again
>
> and thanks for the quick responses.
>
> What bothers me in the WebappClassLoader is the fact that before it checks
> its repositories (lib folder and classes) and asks its parent class loader,
> it will first attempt to load a class from the system class loader - from
> the jvm. This is not standard classloader logic but sth done on purpose in
> the webapp class loader. I want to prevent that for certain packages and I
> want it to be configurable for each web application. That's why I wrote my
> WebappClassLoader and configured its usage in the default context.xml
> (<Loader loaderClass="org.chefo.OSGiWebappClassLoader"/>  in<catalina
> home>/conf/context/xml). I figured the easiest way to configure a list of
> packages that should not be loaded through the system class loader is with a
> parameter in the context of the web application, thus I need to access a
> context parameter in my webapp class loader. I thought it would be normal
> for the webapp class loader to be able to access the context that is
> associated with it...
>
> Hope that makes it a bit clearer...

You can configure your loader by extending WebappLoader (not only 
WebappClassLoader) and then using attributes in the loader element you 
added to context.xml (and corresponding setters in the loader 
implementation).

For an example see

http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/loader/VirtualWebappLoader.html

Regards,

Rainer

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Access StandardContext in WebappClassLoader

Posted by Chefo <ch...@gmail.com>.
Hi again

and thanks for the quick responses.

What bothers me in the WebappClassLoader is the fact that before it checks
its repositories (lib folder and classes) and asks its parent class loader,
it will first attempt to load a class from the system class loader - from
the jvm. This is not standard classloader logic but sth done on purpose in
the webapp class loader. I want to prevent that for certain packages and I
want it to be configurable for each web application. That's why I wrote my
WebappClassLoader and configured its usage in the default context.xml
(<Loader loaderClass="org.chefo.OSGiWebappClassLoader"/> in <catalina
home>/conf/context/xml). I figured the easiest way to configure a list of
packages that should not be loaded through the system class loader is with a
parameter in the context of the web application, thus I need to access a
context parameter in my webapp class loader. I thought it would be normal
for the webapp class loader to be able to access the context that is
associated with it...

Hope that makes it a bit clearer...

Thanks,
Chefo


On Thu, Aug 26, 2010 at 5:43 PM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Chefo,
>
> On 8/26/2010 9:38 AM, Chefo wrote:
> > I'm using tomcat 6.0.18 adapted to osgi environment and I would like to
> make
> > the WebappClassLoader configurable so that it does not load certain
> packages
> > directly through the system class loader but use the class loader
> hierarchy
> > instead.
>
> What ClassLoader hierarchy?
>
> > In order to do that I have extended the standard webapp class
> > loader and configured the container to use the new one in the base
> > context.xml.
>
> Ok.
>
> > I want to configure the packages through a context parameter
> > (separately for each webapp) or eventually through an env-entry. However
> I
> > cannot find a way to access the StandardContext instance in my
> > WebappClassLoader.
>
> That's because these two classes have no relationship to one another.
>
> > This is probably a very simple thing to do but I'm not
> > really well familiar with catalina API and this is kinda driving me
> crazy.
> > Any help/suggestion is more than welcome.
>
> The WebappClassLoader is just a ClassLoader that loads "down" instead of
> "up" like traditional ClassLoaders. It's not really webapp or
> context-specific in it's code... it's just that the servlet spec says
> that webapps need to load classes locally before looking up the
> ClassLoader tree, so this class was written to do just that.
>
> The WebappClassLoader isn't tied to the webapp/context other than it's
> the one that's been assigned to the context as it's ClassLoader.
>
> Instead of trying to reach-down from the ClassLoader to the
> StandardContext, why not do the reverse: register a
> ServletContextListener that configures the (already-created)
> ClassLoader. Something like this:
>
> public class CrazyClassLoaderConfigrationListener
>  implements ServletContextListener
> {
>  public void contextInitialized(ServletContextEvent e)
>  {
>    ClassLoader cl = this.getClass().getClassLoader();
>
>    if(!(cl instanceof CrazyClassLoader))
>      cl = Thread.currentThread().getContextClassLoader();
>
>    if(cl instanceof CrazyClassLoader)
>    {
>      ((CrazyClassLoader)cl)
>           .configure(e.getServletContext()
>                       .getInitParameter("packages"));
>    }
>    else
>    {
>      e.getServletContext().log("Could not configure CrazyClassLoader");
>    }
>  }
> }
>
> That's a little late to be setting the ClassLoader configuration, but it
> will happen before your servlets are loaded.
>
> Of course, you could also just use a .properties file to configure your
> ClassLoader.
>
> The real question is: what is it that you're really trying to do?
>
> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAkx2fYgACgkQ9CaO5/Lv0PAs0ACgtV8J5d+y8n+CbxlNZpYJZndA
> qckAn2P0c45ioh8O7SyUsKfiYQfK3TPU
> =4TUr
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: Access StandardContext in WebappClassLoader

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chefo,

On 8/26/2010 9:38 AM, Chefo wrote:
> I'm using tomcat 6.0.18 adapted to osgi environment and I would like to make
> the WebappClassLoader configurable so that it does not load certain packages
> directly through the system class loader but use the class loader hierarchy
> instead.

What ClassLoader hierarchy?

> In order to do that I have extended the standard webapp class
> loader and configured the container to use the new one in the base
> context.xml.

Ok.

> I want to configure the packages through a context parameter
> (separately for each webapp) or eventually through an env-entry. However I
> cannot find a way to access the StandardContext instance in my
> WebappClassLoader.

That's because these two classes have no relationship to one another.

> This is probably a very simple thing to do but I'm not
> really well familiar with catalina API and this is kinda driving me crazy.
> Any help/suggestion is more than welcome.

The WebappClassLoader is just a ClassLoader that loads "down" instead of
"up" like traditional ClassLoaders. It's not really webapp or
context-specific in it's code... it's just that the servlet spec says
that webapps need to load classes locally before looking up the
ClassLoader tree, so this class was written to do just that.

The WebappClassLoader isn't tied to the webapp/context other than it's
the one that's been assigned to the context as it's ClassLoader.

Instead of trying to reach-down from the ClassLoader to the
StandardContext, why not do the reverse: register a
ServletContextListener that configures the (already-created)
ClassLoader. Something like this:

public class CrazyClassLoaderConfigrationListener
  implements ServletContextListener
{
  public void contextInitialized(ServletContextEvent e)
  {
    ClassLoader cl = this.getClass().getClassLoader();

    if(!(cl instanceof CrazyClassLoader))
      cl = Thread.currentThread().getContextClassLoader();

    if(cl instanceof CrazyClassLoader)
    {
      ((CrazyClassLoader)cl)
           .configure(e.getServletContext()
                       .getInitParameter("packages"));
    }
    else
    {
      e.getServletContext().log("Could not configure CrazyClassLoader");
    }
  }
}

That's a little late to be setting the ClassLoader configuration, but it
will happen before your servlets are loaded.

Of course, you could also just use a .properties file to configure your
ClassLoader.

The real question is: what is it that you're really trying to do?

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkx2fYgACgkQ9CaO5/Lv0PAs0ACgtV8J5d+y8n+CbxlNZpYJZndA
qckAn2P0c45ioh8O7SyUsKfiYQfK3TPU
=4TUr
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Access StandardContext in WebappClassLoader

Posted by Pid <pi...@pidster.com>.
On 26/08/2010 14:38, Chefo wrote:
> Hi guys,
> 
> I'm using tomcat 6.0.18 adapted to osgi environment and I would like to make
> the WebappClassLoader configurable so that it does not load certain packages
> directly through the system class loader but use the class loader hierarchy
> instead. In order to do that I have extended the standard webapp class
>
> loader and configured the container to use the new one in the base
> context.xml. I want to configure the packages through a context parameter
> (separately for each webapp) or eventually through an env-entry. However I
> cannot find a way to access the StandardContext instance in my
> WebappClassLoader. This is probably a very simple thing to do but I'm not
> really well familiar with catalina API and this is kinda driving me crazy.
> Any help/suggestion is more than welcome.

The public parts, (and arguably some other bits), of WebappClassLoader
are accessible to any code calling Thread.getContextClassLoader() with a
simple cast.

Simple access to the underlying StandardContext which circumvented the
ServletContext interface would be a bit pointless & somewhat dangerous.

Why do you need the StandardContext?


p