Ladies and Gentlemen,
Is there an elegant way to have ABCL load Lisp code from a JAR file in the Java CLASSPATH?
I'm helping build an application to run under ABCL and I'd like to take all the code and roll it up into a JAR file in the CLASSPATH when I start the interpreter. If possible I'd then like to have ABCL find the file as though it were in the current directory. I know that ABLC is finding its system files in abcl.jar and I can load Lisp code from a local JAR file, but I haven't figured out how to put the two together and load Lisp elegantly from a JAR file in the CLASSPATH. I can do it inelegantly by getting the CLASSPATH from the Java System class, inspecting all its JAR files, then loading the right ones manually, but that seems awkward for a customer application.
I'd appreciate any pointers.
Finally, please let me apologize in advance if there's some simple answer that I should have found but haven't.
Peter
On 1/12/10 5:07 AM, Olsen, Peter C. wrote:
Ladies and Gentlemen,
Is there an elegant way to have ABCL load Lisp code from a JAR file in the Java CLASSPATH?
Unfortunately, not yet.
As it stands, "naked" ABCL really doesn't interact with the Java CLASSPATH in any meaningful way for Lisp objects.
Once I get the the JAR file support working again, I could easily add the following meaning to
CL-USER> (load "jar:file:foo.jar!/a/b/bar.abcl")
1. Resolve "foo.jar" with respect to *DEFAULT-PATHNAME-DEFAULTS*, and if it exists, attempt to load "a/b/bar.abcl".
2. If resolution of "foo.jar" fails on the filesystem, iterate through the CLASSPATH to match the name.
Alan Ruttenberg's [JSS][1] has long had the ability to dynamically add JARs to the JVM CLASSPATH which would be nice to incorporate as well.
[1]: http://mumble.net:8080/svn/lsw/trunk/jss/
I'm helping build an application to run under ABCL and I'd like to take all the code and roll it up into a JAR file in the CLASSPATH when I start the interpreter. If possible I'd then like to have ABCL find the file as though it were in the current directory. I know that ABLC is finding its system files in abcl.jar and I can load Lisp code from a local JAR file, but I haven't figured out how to put the two together and load Lisp elegantly from a JAR file in the CLASSPATH. I can do it inelegantly by getting the CLASSPATH from the Java System class, inspecting all its JAR files, then loading the right ones manually, but that seems awkward for a customer application. […]
It certainly should be a lot smoother by default.
On Tue, Jan 12, 2010 at 12:56 PM, Mark Evenson evenson@panix.com wrote:
On 1/12/10 5:07 AM, Olsen, Peter C. wrote:
Ladies and Gentlemen,
Is there an elegant way to have ABCL load Lisp code from a JAR file in the Java CLASSPATH?
Unfortunately, not yet.
As it stands, "naked" ABCL really doesn't interact with the Java CLASSPATH in any meaningful way for Lisp objects.
Once I get the the JAR file support working again, I could easily add the following meaning to
CL-USER> (load "jar:file:foo.jar!/a/b/bar.abcl")
- Resolve "foo.jar" with respect to *DEFAULT-PATHNAME-DEFAULTS*, and
if it exists, attempt to load "a/b/bar.abcl".
- If resolution of "foo.jar" fails on the filesystem, iterate through
the CLASSPATH to match the name.
I don't agree on point 2. Ideally I would like to keep the two points distinct, i.e. cook up another pseudo-pathname - say, "classpath:/a/b/foo.abcl" - specifically for classpath resources. The reason is that I see two very distinct usages of this functionality:
2. (classpath) is what applications would normally use: just ensure that resources are in the classpath, ignore where they are physically located; 1. (explicit jar path) would normally be used by ABCL itself in order to correctly resolve relative paths, load internal stuff, and similar.
imho, of course.
Bye, Alessio
[…]
Is there an elegant way to have ABCL load Lisp code from a JAR file in the Java CLASSPATH?
[…]
- If resolution of "foo.jar" fails on the filesystem, iterate through
the CLASSPATH to match the name.
I don't agree on point 2. Ideally I would like to keep the two points distinct, i.e. cook up another pseudo-pathname - say, "classpath:/a/b/foo.abcl" - specifically for classpath resources. The reason is that I see two very distinct usages of this functionality:
- (classpath) is what applications would normally use: just ensure
that resources are in the classpath, ignore where they are physically located;
- (explicit jar path) would normally be used by ABCL itself in order
to correctly resolve relative paths, load internal stuff, and similar.
I accept that there is a conceptual difference between a java CLASSPATH and an explicit reference to a jar which.
Being more strict, I suppose we could say that translated into Lisp a Java CLASSPATH is a proper list of pathnames which may either be references to JAR files or directories.
Thus CLASSPATH="/a/b/foo.jar:bar.jar:baz"
would be translated into Lisp (using the "jar:" syntax as specified in java.net.JarUrlConnection): (#p"jar:file:/a/b/foo.jar!/" #p"jar:file:bar.jar!/" #p"baz/")
Since one can access arbitrary resources from the CLASSPATH, I would propose we declare that a PATHNAME NAMESTRING beginning with "classpath:" refers to an item that should be resolved via the CLASSPATH. I think I can include wildcards here in the implementation (but I have to think through more fully through this) so
(truename #p"classpath:jar:file:*/foo.jar!/") for the previous CLASSPATH would return #p"classpath:jar:file:/a/b/foo.jar!/"
And (truename #p"classpath:baz/foo.text") if there were a directory "baz/" on the local filesystem under "/a/b/c" would return #p"classpath:/a/b/c/baz/foo.text"
Another subtlety to consider later is that JAR manifests [can apparently modify the classpath for sources loaded from that JAR][1]. Not sure what this would mean at the moment.
[1]: http://en.wikipedia.org/wiki/Classpath_%28Java%29#Setting_the_path_in_a_Mani...
I'd also like to think through the ramifications of packaging Lisp applications via ASDF definitions in JAR files. It would be nice for one ASDF system needing another one could have some mechanism to specify this relationship without knowing the exact JAR that this dependency entails. But since such dependencies are currently specified by symbolic links in a directory which won't work with JARs, we probably need to extend ASDF in some manner. It would be nice to crib some Java implementation, but I don't know anything that is standardized. Managing CLASSPATH dependencies in Java is a generally considered weakness. Java 7 was supposed to help with this via superpackages and/or modules, but that is in an uncertain future.
On Wed, Jan 13, 2010 at 11:00 AM, Mark Evenson evenson@panix.com wrote:
[…] Another subtlety to consider later is that JAR manifests [can apparently modify the classpath for sources loaded from that JAR][1]. Not sure what this would mean at the moment.
Commenting just on this point for now: we don't need to worry about that as it is just a facility used by the JVM to make launching applications easier: when you do java -jar some.jar the manifest in some.jar (and only in some.jar) is consulted to determine the classpath, i.e. the command is equivalent to java -cp some.jar;...additional.jars... com.foo.whatever.Main
Bye, Ale
On Tue, Jan 12, 2010 at 5:07 AM, Olsen, Peter C. Peter.Olsen@jhuapl.edu wrote:
Ladies and Gentlemen,
Is there an elegant way to have ABCL load Lisp code from a JAR file in the Java CLASSPATH?
I believe these are two different issues coalesced into one:
1. load code from the classpath 2. load code from a Jar
At runtime, the classpath is a logical entity, and it is the combination of several resources, such as local and remote jars, local .class files, etc.
A jar is just a zip file with some extra metadata, and its contents may or may not be part of the classpath.
Also, you refer generically to Lisp code, but it may be Lisp source or a FASL (which in ABCL might be a compressed file itself).
So, it's not as simple as it seems. I believe that, internally, ABCL can load code from any stream, be it source code or compiled code. What it lacks, and there are ongoing efforts to address that (see Mark's mail), is a well-thought integration with CL:LOAD semantics, such as addressing resources inside the classpath and jars with Lisp pathnames, proper setting of *LOAD-TRUENAME*, etc.
hth, Alessio
armedbear-devel@common-lisp.net