You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Carsten Ziegeler <cz...@apache.org> on 2009/03/23 15:47:42 UTC

[RT] Resource class loader

I'm thinking about improving our jsp (and other scripting) support. One
problem I see atm is our class loading for compiled scripts.

At the moment, we have the RepositoryClassLoaderProvider which allows to
get a class loader for a user which is able to load classes from
somewhere out of the repository. All the scripting support for writing
classes into the repository have to know where in the repository classes
are located. The scripting engines write the compiled script to this
configured locations and later on the class is loaded by the
RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
- The repository path where classes are located has to be configured
properly at several places
- The scripting support is tied to jcr which makes it unusable in non
JCR environments

I think we should come up with a solution for these problems by
introducing a ResourceClassLoaderProvider with a similar interface as
the RepositoryClassLoaderProvider. I'm not sure about the user argument
especially if we plan to use the OSGi User Admin stuff.

The provider could provide a ResourceClassLoader which extends
ClassLoader and has an additional method for writing class files and
maybe removing them (perhaps we need more functionality?)

WDYT?

Carsten
-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Resource class loader

Posted by Michael Dürig <mi...@day.com>.
>> might for example be the case for languages which have some built in
>> dependency injection support (i.e. find me all available implementations
>> of a given interface).
> 
> Hmm, this is probably more a problem of the Design of the respective
> scripting language, than one of the ClassLoader. The Java ClassLoader is
> not a generic resource accessor with API to walk some package tree. The
> ClassLoader allows direct access to classes (and resources).
> 
> And this is good and sufficient.

No I think it isn't. Class loaders were designed to load binary 
representations of classes into the JVM. Using them for scripting 
languages which need to resolve symbols at compile time is a hack. In 
fact all languages which I looked at and which do symbol resolution at 
compile time use the same 'classloader.getResource("foo.class")' hack to 
get access to a class file. Languages which require to browse the 
classes available to them at compile time need to resort to even more 
esoteric hacks.

Now this is certainly not a problem of Sling. Given however, that Sling 
has support for a great variety scripting languages and that each of 
those makes certain assumptions on the representation of the 
'classpath', there will be more or less of a hassle for each of it to 
get it working within Sling.

So the decision is whether we leave this to integrators of scripting 
languages and let each of those come up with its own - possible brittle 
solution - which in the worst case might depend on implementation 
details of actual class loaders. Or whether we provide some means to 
them which makes their lives easier and which factors out potential 
problematic/implementation dependent code. After all the latter 
'solution' will facilitate integration of new scripting languages and 
enhance stability and maintainability.

Michael


> 
> The problem with the Scripting Language you are talking about is, that
> it is not using the ClassLoader as the ClassLoader is intended to be
> used. It tries to enumerate classes and resources, which is only
> possible if you can access the resources upon which the class loader
> operates, but this functionality is outside of the general ClassLoader API.
> 
> In the case of the OSGi framework such functionality might in addition
> violate or break the separation of concerns mechanisms built using the
> Import/Export declarations.
> 
> BTW: Are there language with built-in functionality to find all
> implementations of a given interface ? This sounds more like an IDE
> feature which indexes the class space, than like a language feature....
> 
>> I faced this issue when I implemented support for Scala [1]. To work
>> around it I implemented a (Scala specific) file system abstraction on
>> top of Felix's bundles [2]. While this works atm, the approach might not
>> be too stable. Since others might face similar problems, we could maybe
>> provide a more standardized way to Scripts for accessing classes on the
>> 'classpath'.
> 
> The problem must really be solved in Scala, which IMHO has no reason to
> know the source of the class path entries as long as it can ask the
> ClassLoader for classes and resources.
> 
> Regards
> Felix
> 
>> Michael
>>
>> [1]
>> http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala
>>
>> [2]
>> http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/BundleFS.scala
>>
>>
>>
>> Carsten Ziegeler wrote:
>>> I'm thinking about improving our jsp (and other scripting) support. One
>>> problem I see atm is our class loading for compiled scripts.
>>>
>>> At the moment, we have the RepositoryClassLoaderProvider which allows to
>>> get a class loader for a user which is able to load classes from
>>> somewhere out of the repository. All the scripting support for writing
>>> classes into the repository have to know where in the repository classes
>>> are located. The scripting engines write the compiled script to this
>>> configured locations and later on the class is loaded by the
>>> RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
>>> - The repository path where classes are located has to be configured
>>> properly at several places
>>> - The scripting support is tied to jcr which makes it unusable in non
>>> JCR environments
>>>
>>> I think we should come up with a solution for these problems by
>>> introducing a ResourceClassLoaderProvider with a similar interface as
>>> the RepositoryClassLoaderProvider. I'm not sure about the user argument
>>> especially if we plan to use the OSGi User Admin stuff.
>>>
>>> The provider could provide a ResourceClassLoader which extends
>>> ClassLoader and has an additional method for writing class files and
>>> maybe removing them (perhaps we need more functionality?)
>>>
>>> WDYT?
>>>
>>> Carsten
>>
> 


Re: [RT] Resource class loader

Posted by Felix Meschberger <fm...@gmail.com>.
Hi Michael,

Michael Dürig schrieb:
> 
> There is another issue with the current design which might be worthwhile
> to tackle at the same time. While class loaders are fine for loading
> classes into the JVM they are in general the wrong abstraction when
> compiling scripts. Scripts need access to the class files itself and
> might even need to browse the available classes on the 'classpath'. This

This is not true in general. In fact I never encountered a scripting
language which would require this (provided the script language
implementation supports compilation into byte code).

> might for example be the case for languages which have some built in
> dependency injection support (i.e. find me all available implementations
> of a given interface).

Hmm, this is probably more a problem of the Design of the respective
scripting language, than one of the ClassLoader. The Java ClassLoader is
not a generic resource accessor with API to walk some package tree. The
ClassLoader allows direct access to classes (and resources).

And this is good and sufficient.

The problem with the Scripting Language you are talking about is, that
it is not using the ClassLoader as the ClassLoader is intended to be
used. It tries to enumerate classes and resources, which is only
possible if you can access the resources upon which the class loader
operates, but this functionality is outside of the general ClassLoader API.

In the case of the OSGi framework such functionality might in addition
violate or break the separation of concerns mechanisms built using the
Import/Export declarations.

BTW: Are there language with built-in functionality to find all
implementations of a given interface ? This sounds more like an IDE
feature which indexes the class space, than like a language feature....

> 
> I faced this issue when I implemented support for Scala [1]. To work
> around it I implemented a (Scala specific) file system abstraction on
> top of Felix's bundles [2]. While this works atm, the approach might not
> be too stable. Since others might face similar problems, we could maybe
> provide a more standardized way to Scripts for accessing classes on the
> 'classpath'.

The problem must really be solved in Scala, which IMHO has no reason to
know the source of the class path entries as long as it can ask the
ClassLoader for classes and resources.

Regards
Felix

> 
> Michael
> 
> [1]
> http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala
> 
> [2]
> http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/BundleFS.scala
> 
> 
> 
> Carsten Ziegeler wrote:
>> I'm thinking about improving our jsp (and other scripting) support. One
>> problem I see atm is our class loading for compiled scripts.
>>
>> At the moment, we have the RepositoryClassLoaderProvider which allows to
>> get a class loader for a user which is able to load classes from
>> somewhere out of the repository. All the scripting support for writing
>> classes into the repository have to know where in the repository classes
>> are located. The scripting engines write the compiled script to this
>> configured locations and later on the class is loaded by the
>> RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
>> - The repository path where classes are located has to be configured
>> properly at several places
>> - The scripting support is tied to jcr which makes it unusable in non
>> JCR environments
>>
>> I think we should come up with a solution for these problems by
>> introducing a ResourceClassLoaderProvider with a similar interface as
>> the RepositoryClassLoaderProvider. I'm not sure about the user argument
>> especially if we plan to use the OSGi User Admin stuff.
>>
>> The provider could provide a ResourceClassLoader which extends
>> ClassLoader and has an additional method for writing class files and
>> maybe removing them (perhaps we need more functionality?)
>>
>> WDYT?
>>
>> Carsten
> 
> 


Re: [RT] Resource class loader

Posted by Michael Dürig <mi...@day.com>.
There is another issue with the current design which might be worthwhile 
to tackle at the same time. While class loaders are fine for loading 
classes into the JVM they are in general the wrong abstraction when 
compiling scripts. Scripts need access to the class files itself and 
might even need to browse the available classes on the 'classpath'. This 
might for example be the case for languages which have some built in 
dependency injection support (i.e. find me all available implementations 
of a given interface).

I faced this issue when I implemented support for Scala [1]. To work 
around it I implemented a (Scala specific) file system abstraction on 
top of Felix's bundles [2]. While this works atm, the approach might not 
be too stable. Since others might face similar problems, we could maybe 
provide a more standardized way to Scripts for accessing classes on the 
'classpath'.

Michael

[1] 
http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala
[2] 
http://svn.apache.org/repos/asf/incubator/sling/trunk/contrib/scripting/scala/interpreter/src/main/scala/org/apache/sling/scripting/scala/interpreter/BundleFS.scala


Carsten Ziegeler wrote:
> I'm thinking about improving our jsp (and other scripting) support. One
> problem I see atm is our class loading for compiled scripts.
> 
> At the moment, we have the RepositoryClassLoaderProvider which allows to
> get a class loader for a user which is able to load classes from
> somewhere out of the repository. All the scripting support for writing
> classes into the repository have to know where in the repository classes
> are located. The scripting engines write the compiled script to this
> configured locations and later on the class is loaded by the
> RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
> - The repository path where classes are located has to be configured
> properly at several places
> - The scripting support is tied to jcr which makes it unusable in non
> JCR environments
> 
> I think we should come up with a solution for these problems by
> introducing a ResourceClassLoaderProvider with a similar interface as
> the RepositoryClassLoaderProvider. I'm not sure about the user argument
> especially if we plan to use the OSGi User Admin stuff.
> 
> The provider could provide a ResourceClassLoader which extends
> ClassLoader and has an additional method for writing class files and
> maybe removing them (perhaps we need more functionality?)
> 
> WDYT?
> 
> Carsten


OCM by jackrabbit annotations

Posted by Markus Pallo <pa...@dig.de>.
Hi,

we are using jcrom as object mapper for now and we are thinking to 
switch to use sling-ocm (jackrabbit).
As far as i have seen its not possible to use ocm with jackrabbit 
annotations instead of mappings file, or generated by maven-jcrocm, is 
that right ?

What about scanning bundles classloader for annotated classes if there 
is no mapping.xml file found for the bundle and forward the 
AnnotationDescriptorReader with the found classnames to the BundleMapper 
? (see ObjectContentManagerFactoryImpl.loadMappings() )

What do you think ?


Markus




Re: [RT] Resource class loader

Posted by Carsten Ziegeler <cz...@apache.org>.
I've committed a first version if the ClassLoaderWriter (commons
classloader) - not sure of the name :)

It is used by the jsp and java scripting bundles to write the classes
(generated java files) - the jcr classloader implements this and writes
the stuff into the repository.

The whole script reading, class loading and class writing is now
delegated and not done by the script engines itself anymore.

WDYT?

Carsten
-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Resource class loader

Posted by Michael Dürig <mi...@day.com>.
  > I think we should change this and leave the path handling to a service.
> For example a (don't quote me on the name)
> WriteableDynamicClassLoaderProvider could offer methods for getting the
> output stream to write a class file. The argument would only be the file
> name. 

This seems to get pretty close to
https://issues.apache.org/jira/browse/SLING-945

Since script engines might also need to read class files, I suggest to 
also add a method for getting a stream for reading from a class file.

Michael


Re: [RT] Resource class loader

Posted by Carsten Ziegeler <cz...@apache.org>.
Ok, I'm coming back to this discussion as I'm currently looking in how
to implement this.

We now have a dynamic class loader manager (commons/classloader bundle)
which returns a class loader (proxy) to dynamically load classes.
This class loader has two purposes
- remove the need for dynamic import package * in script handlers. The
new dynamic class loader uses the package admin to find classes.
- allow custom dynamic class loaders like a jcr class loader. Therefore
we have the new DynamicClassLoaderProvider interface which could be
implemented by the JCR class loader.

The second point would make the current RepositoryClassLoaderProvider
obsolete and should make class loading for compiled scripts working in
JCR and non-JCR environments (we could simply make a dynamic class
loader provider using a temporary directory).

So far this should work - but that's only one side of the coin - loading
classes. The more interesting point is how can the script handlers write
classes?

For this I looked how the JSP engine currently does it's work and it
seems to me that this is not that easily changeable.  There is the
IOProvider which is the interface for IO :) It reads java files, writes
class files (or other generated files) etc. Unfortunately all the path
handling is done somewhere inside the jsp engine. So instead of having a
getInputStream(String javaClassName) and getOutputStream(String
javaClassName) both methods use a fileName - so all the path handling
etc has already been done.

I think we should change this and leave the path handling to a service.
For example a (don't quote me on the name)
WriteableDynamicClassLoaderProvider could offer methods for getting the
output stream to write a class file. The argument would only be the file
name. Reading of sources should work through the resource resolver.

Just a rough idea, but WDYT?

Carsten

Felix Meschberger wrote:
> Hi Carsten,
> 
> Carsten Ziegeler schrieb:
>> I'm thinking about improving our jsp (and other scripting) support. One
>> problem I see atm is our class loading for compiled scripts.
>>
>> At the moment, we have the RepositoryClassLoaderProvider which allows to
>> get a class loader for a user which is able to load classes from
>> somewhere out of the repository. All the scripting support for writing
>> classes into the repository have to know where in the repository classes
>> are located. The scripting engines write the compiled script to this
>> configured locations and later on the class is loaded by the
>> RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
>> - The repository path where classes are located has to be configured
>> properly at several places
>> - The scripting support is tied to jcr which makes it unusable in non
>> JCR environments
>>
>> I think we should come up with a solution for these problems by
>> introducing a ResourceClassLoaderProvider with a similar interface as
>> the RepositoryClassLoaderProvider. I'm not sure about the user argument
>> especially if we plan to use the OSGi User Admin stuff.
>>
>> The provider could provide a ResourceClassLoader which extends
>> ClassLoader and has an additional method for writing class files and
>> maybe removing them (perhaps we need more functionality?)
>>
>> WDYT?
> 
> +1 for a ResourceClassLoader
> 
> Maybe we should even register the ResourceClassLoader as a globally
> available service with the following properties:
> 
>   * The service is really a proxy, since upon class changes, the
>      real class loader used is replaced.
>   * The class loader service is shared by all clients using classes
>      (or resources) from the ResourceClassLoader
>   * The locations from where the class loader is loading classes and
>      and resources is queryable, similar to URLClassLoader.getURLs()
>   * The ResourceClassLoader must only be used for short-lived use of
>      classes and resources.
> 
> The last point is important, since the actual class loader will be
> dropped upon changes in the class path. If we would be referring to
> classes over an extended period of time, we would run into memory issues
> (the classloader and all loaded classes cannot be collected) and class
> cast exceptions.
> 
> Regarding "user specific classloaders": I don't think, we really need
> this (any more). It has not been implemented in the current release (the
> class loader is always using the administrative session) and I don't see
> a use in it (right now).
> 
> Regards
> Felix
> 
>> Carsten
> 


-- 
Carsten Ziegeler
cziegeler@apache.org

Re: [RT] Resource class loader

Posted by Felix Meschberger <fm...@gmail.com>.
Hi Carsten,

Carsten Ziegeler schrieb:
> I'm thinking about improving our jsp (and other scripting) support. One
> problem I see atm is our class loading for compiled scripts.
> 
> At the moment, we have the RepositoryClassLoaderProvider which allows to
> get a class loader for a user which is able to load classes from
> somewhere out of the repository. All the scripting support for writing
> classes into the repository have to know where in the repository classes
> are located. The scripting engines write the compiled script to this
> configured locations and later on the class is loaded by the
> RepositoryClassLoader. Obvioulsly this has at least two drawbacks:
> - The repository path where classes are located has to be configured
> properly at several places
> - The scripting support is tied to jcr which makes it unusable in non
> JCR environments
> 
> I think we should come up with a solution for these problems by
> introducing a ResourceClassLoaderProvider with a similar interface as
> the RepositoryClassLoaderProvider. I'm not sure about the user argument
> especially if we plan to use the OSGi User Admin stuff.
> 
> The provider could provide a ResourceClassLoader which extends
> ClassLoader and has an additional method for writing class files and
> maybe removing them (perhaps we need more functionality?)
> 
> WDYT?

+1 for a ResourceClassLoader

Maybe we should even register the ResourceClassLoader as a globally
available service with the following properties:

  * The service is really a proxy, since upon class changes, the
     real class loader used is replaced.
  * The class loader service is shared by all clients using classes
     (or resources) from the ResourceClassLoader
  * The locations from where the class loader is loading classes and
     and resources is queryable, similar to URLClassLoader.getURLs()
  * The ResourceClassLoader must only be used for short-lived use of
     classes and resources.

The last point is important, since the actual class loader will be
dropped upon changes in the class path. If we would be referring to
classes over an extended period of time, we would run into memory issues
(the classloader and all loaded classes cannot be collected) and class
cast exceptions.

Regarding "user specific classloaders": I don't think, we really need
this (any more). It has not been implemented in the current release (the
class loader is always using the administrative session) and I don't see
a use in it (right now).

Regards
Felix

> 
> Carsten