Hello!

I am developing a Java application where Clojure is used as a library. The 
application is required to load sources (including Clojure sources) from 
arbitrary locations in filesystem, internet and maybe a dozen other places. 
Hence I have developed corresponding classloaders for that, which properly 
implement the required ClassLoader methods.

Loading Clojure sources is realized via this approach:

Compiler.LOADER.alterRoot(getMyClassLoader(), ...);          // changing 
the LOADER to my chain of classloaders
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("example.namespace"));

where the contents of the "example.namespace" are:

(ns example.namespace
  (:require [other.example.namespace :as other])))

I have figured that the loading happens with RT.load() 
<https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L415>
 
which delegates to RT.loadResourceScript() 
<https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L365>,
 so 
I just alter the Compiler.LOADER so that RT.baseLoader() returns my 
classloaders. And in my classloaders I simply have to override the 
getResourceAsStream 
and all works!
  
The namespace example.namespace starts loading ok. It successfully loads 
the whole clojure.core and then begins to process the first require - the 
other.example.namespace. And this is where something *bad *happens.

It appears to be that the (require) inside the ns form in the 
example.namespace uses not the RT.load() method, but Compiler.load() 
<https://github.com/clojure-android/clojure/blob/android/src/jvm/clojure/lang/Compiler.java#L7202>where
 
on line 7210 
<https://github.com/clojure-android/clojure/blob/android/src/jvm/clojure/lang/Compiler.java#L7210>the
 
Compiler.LOADER, which by that moment points to the correct classloader 
created by me, gets replaced by RT.makeClassLoader() 
<https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L2106>where
 
the current RT.baseLoader() which is effectively Compiler.LOADER gets 
passed as the parent to the newly created DynamicClassLoader.

So I get Compiler.LOADER which I have set to the correct classloader, 
replaced by the DynamicClassLoader whose parent is my classloader. The 
problem is that DynamicClassLoader inherits from URLClassLoader that 
inherits from ClassLoader which, although accepts a parent classloader on 
its creation, does not delegate getResourceAsStream() in case of its 
personal failure to its parent 
<http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/ClassLoader.java#1175>!
 That 
results in that my classloader, although still present in the chain, never 
gets called and the (require) in the ns form of example.namespace fails to 
locate the required namespaces that **are** available at that data source.

The problem is that this behavior is hard-coded in Clojure and it looks 
like it is impossible to change that. Clojure forces us to use a 
classloader that inherits the getResourceAsStream() method from 
java.lang.ClassLoader which does not allow delegation of this request to 
parent classloader. This effectively prevents using Clojure as a library 
together with a plugin system because it renders Clojure incapable of 
working with sources that are fetched from elsewhere than the Java's 
URLClassLoader is capable of retrieving data from. It is impossible to load 
sources from a database, or some internet data source or an encrypted data 
source, or even another location in the filesystem. Wow!

We've went with Clojure and now are in the desperate need to resolve this 
peculiar phenomenon.. What could be a proposed solution for this situation?

Thank you.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to