abcl-asdf: Enable bypassing of loading from network if a given class already exists.

An ASDF:MVN component can now optionally specify a CLASSNAME that if
able to be found in the current jvm process, inhbits further loading
from the network.

An ASDF:MVN component may also optionally specify an ALTERNATE-URI
that will be added to the current jvm classpath if Maven cannot be
invoked.  Most jvm implementations won't access such jar archives from
the network by default, so this is an intermediate step before
actually writing the code to download the jar to the local filesystem
to then be added.

Refresh documentation in README.markdown.
parent 8c4a5eab
......@@ -46,9 +46,35 @@ JAR-DIRECTORY, JAR-FILE, and CLASS-FILE-DIRECTORY for JVM artifacts
that have a currently valid pathname representation (i.e. they exist
on the local filesystem).
And we define MVN and IRI classes descend from ASDF-COMPONENT, but do not
The MVN and IRI classes descend from ASDF-COMPONENT, but do not
directly have a filesystem location.
The IRI component is currently unused, but serves as a point to base
the inheritance of the MVN component while allowing other forms of
uri-like resources to be encapsulated in the future.
The MVN component should specifiy a [Maven URI][1] as its PATH. A
Maven URI has the form "GROUP-ID/ARTIFACT-ID/VERSION" which specifies
the dependency to be satisfied for this component by resolution
through the Maven distributed dependency graph. The scheme (the
initial "mvn://") is implied, usually omitted for brevity. If a
VERSION is not specified (i.e. by a form like "GROUP-ID/ARTIFACT-ID"),
then the latest available version of the artifact will be retrieved
from the network.
[1]: http://team.ops4j.org/wiki/display/paxurl/Mvn+Protocol
The MVN component may specify a CLASSNAME which if present in the
current jvm, inhibits further loading from the network. This may be
used to bypass the invocation of Maven. Since classnames are not
unique to jar archives, this mechanism may not have the desired result
in all cases, but it is surpisingly, like the rest of Java, "good
enough" for everyday use.
The MVN component may specify an ALTERNATE-URI which will be added to
the jvm classpath if Maven cannot be located. Since a Maven URI may
refer to more than one binary artifact, this may not work in all cases.
For use outside of ASDF, we currently define the generic function
ABCL-ASDF:RESOLVE which locates, downloads, caches, and then loads
into the currently executing JVM process all recursive dependencies
......@@ -136,6 +162,11 @@ The following ASDF defintion loads enough JVM artifacts to use the
Releases
--------
### 9.9.2 2012-11-09
### 0.7.0 2012-02-05
Plausibly work under MSFT operating systems.
......@@ -168,5 +199,5 @@ Working with maven-3.0.4.
Mark <evenson.not.org@gmail.com>
Created: 2011-01-01
Revised: 2012-02-06
Revised: 2012-11-09
......@@ -2,7 +2,7 @@
(asdf:defsystem :abcl-asdf
:author "Mark Evenson"
:version "0.9.1"
:version "0.9.2"
:depends-on (jss)
:components
((:module packages :pathname ""
......
;;;; The ABCL specific overrides in ASDF.
s;;;; The ABCL specific overrides in ASDF.
;;;;
;;;; Done separate from asdf.lisp for stability.
(require :asdf)
......@@ -15,6 +15,8 @@
((group-id :initarg :group-id :initform nil)
(artifact-id :initarg :artifact-id :initform nil)
(repository :initform "http://repo1.maven.org/maven2/") ;;; XXX unimplmented
(classname :initarg :classname :initform nil)
(alternate-uri :initarg :alternate-uri :initform nil)
;; inherited from ASDF:COMPONENT ??? what are the CL semantics on overriding -- ME 2012-04-01
#+nil (version :initform nil)))
......@@ -29,10 +31,10 @@
(ensure-parsed-mvn c)))
(defmethod perform ((operation load-op) (c mvn))
(java:add-to-classpath
(abcl-asdf:as-classpath
(abcl-asdf:resolve
(ensure-parsed-mvn c)))))
(let ((resolved-path
(abcl-asdf:resolve (ensure-parsed-mvn c))))
(when (stringp resolved-path)
(java:add-to-classpath (abcl-asdf:as-classpath resolved-path)))))
;;; A Maven URI has the form "mvn:group-id/artifact-id/version"
;;;
......@@ -100,9 +102,10 @@
(defmethod resolve ((mvn-component asdf::mvn))
"Resolve all runtime dependencies of MVN-COMPONENT.
Returns a string in JVM CLASSPATH format as entries delimited by
classpath separator string. Can possibly be a single entry denoting a
remote binary artifact."
Returns either a string in jvm classpath format as entries delimited
by classpath separator string or T. If the value T is returned, it
denotes that current JVM already has already loaded a given class. Can possibly be a
single entry denoting a remote binary artifact."
(macrolet ((aif (something consequence alternative))
`(let ((it ,(something)))
(if it
......@@ -111,20 +114,30 @@ remote binary artifact."
(let ((name (slot-value mvn-component 'asdf::name))
(group-id (slot-value mvn-component 'asdf::group-id))
(artifact-id (slot-value mvn-component 'asdf::artifact-id))
(classname (slot-value mvn-component 'asdf::classname))
(alternate-uri (slot-value mvn-component 'asdf::alternate-uri))
(version (let ((it (slot-value mvn-component 'asdf::version)))
(cond
((not it)
it)
(t
"LATEST")))))
(if (find-mvn)
(resolve-dependencies group-id artifact-id version)
(cond
((string= name "net.java.dev.jna/jna/3.4.0")
(let ((uri #p"http://repo1.maven.org/maven2/net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar")))
(values (namestring uri) uri))
(t
(error "Failed to resolve MVN component name ~A." name)))))))
(handler-case
(when (and classname
(jss:find-java-class classname))
(warn "Not loading ~A from the network because ~A is present in classpath."
name classname)
(return-from resolve t))
(java:java-exception (e)
(unless (java:jinstance-of-p (java:java-exception-cause e)
"java.lang.ClassNotFoundException")
(error "Unexpected Java exception~&~A.~&" e))
(if (find-mvn)
(resolve-dependencies group-id artifact-id version)
(if alternate-uri
(values (namestring alternate-uri) alternate-uri)
(t
(error "Failed to resolve MVN component name ~A." name)))))))))
(defun as-classpath (classpath)
"Break apart the JVM CLASSPATH string into a list of its consituents."
......
;;;; -*- Mode: LISP -*-
;;;; Need to have jna.jar present for CFFI to have a chance of working.
;;;; Need to have jna.jar present for CFFI to work.
(asdf:defsystem :jna
:version "3.5.1"
:defsystem-depends-on (jss abcl-asdf)
;; FIXME: always seems to be resolving the LATEST maven artifact.
:components ((:mvn "net.java.dev.jna/jna/3.5.1")))
:components ((:mvn "net.java.dev.jna/jna/3.5.1"
:alternate-uri "http://repo1.maven.org/maven2/net/java/dev/jna/jna/3.5.1/jna-3.5.1.jar"
:classname "com.sun.jna.Native")))
(in-package :asdf)
(defmethod perform :after ((o load-op) (c (eql (find-system :jna))))
(when (jss:find-java-class "com.sun.jna.Native")
(provide :jna)))
;;; After ASDF performs COMPILE-OP, one expects that the JNA Java
;;; classes can be instantiated. If not, execute various loading strategies.
(defmethod perform ((o compile-op) (c (eql (find-system :jna))))
;; Theoretically this should be the same thing as the MVN component.
(format *debug-io* "~&Attemping to locate jvm binary artifacts for JNA...~&")
(handler-case
(jss:find-java-class "com.sun.jna.Native")
(java:java-exception (e)
(unless
(java:add-to-classpath (abcl-asdf:resolve "net.java.dev.jna:jna:3.5.1"))
(unless
;; Might want to download to local filesystem, then place in classpath
(java:add-to-classpath #p"http://repo1.maven.org/maven2/net/java/dev/jna/jna/3.5.1/jna-3.5.1.jar")
(error "Failed to load jna-3.5.0.jar from the network via URI."))
(error "Failed to load jna.jar via ABCL-ASDF.")))
(t (e)
(error "Failed to resolve 'jna.jar' because~&~A.~&" e))))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment