(in-package :system) (require :asdf) (defconstant +get-classloader+ (java:jmethod "java.lang.Class" "getClassLoader")) (defun boot-classloader () (let ((boot-class (java:jclass "org.armedbear.lisp.Main"))) (java:jcall +get-classloader+ boot-class))) (defun system-jar-p (p) (named-jar-p "abcl" p)) (defun contrib-jar-p (p) (named-jar-p "abcl-contrib" p)) (defun named-jar-p (name p) (and (pathnamep p) (equal (pathname-type p) "jar") (or (java:jstatic "matches" "java.util.regex.Pattern" (concatenate 'string name "(-[0-9]\\.[0-9]\\.[0-9]([+~-].+)?)?") (pathname-name p)) (java:jstatic "matches" "java.util.regex.Pattern" (concatenate 'string name "(-[0-9]\\.[0-9]\\.[0-9]\\.[0-9]([+~-]+)?)?") (pathname-name p))) p)) (defun find-system () "Find the location of the system. Used to determine relative pathname to find 'abcl-contrib.jar'." (or (ignore-errors (find-system-jar)) (ignore-errors (some (lambda (u) (probe-file (make-pathname :defaults (java:jcall "toString" u) :name "abcl"))) (java:jcall "getURLs" (boot-classloader)))) (ignore-errors #p"http://abcl.org/releases/current/abcl.jar"))) (defun find-jar (predicate) (dolist (loader (java:dump-classpath)) (let ((jar (some predicate loader))) (when jar (return jar))))) (defun find-system-jar () "Return the pathname of the system jar, one of `abcl.jar` or `abcl-m.n.p.jar` or `abcl-m.n.p[.~-]something.jar`." (find-jar #'system-jar-p)) (defun find-contrib-jar () "Return the pathname of the contrib jar, one of `abcl-contrib.jar` or `abcl-contrib-m.n.p.jar` or `abcl-contrib-m.n.p[.~-]something.jar`." (find-jar #'contrib-jar-p)) (defvar *abcl-contrib* nil "Pathname of the ABCL contrib. Initialized via SYSTEM:FIND-CONTRIB.") (defparameter *verbose* t) (defun add-contrib (abcl-contrib-jar) "Introspects ABCL-CONTRIB-JAR for asdf systems to add to ASDF:*CENTRAL-REGISTRY*" (when abcl-contrib-jar (dolist (asdf-file (directory (make-pathname :device (list abcl-contrib-jar) :directory '(:absolute :wild) :name :wild :type "asd"))) (let ((asdf-directory (make-pathname :defaults asdf-file :name nil :type nil))) (unless (find asdf-directory asdf:*central-registry* :test #'equal) (push asdf-directory asdf:*central-registry*) (format *verbose* "~&Added ~A to ASDF.~&" asdf-directory)))))) (defun find-and-add-contrib (&key (verbose nil)) "Attempt to find the ABCL contrib jar and add its contents to ASDF. Returns the pathname of the contrib if it can be found." (if *abcl-contrib* (format verbose "~&Using already initialized value of abcl-contrib:~&'~A'.~%" *abcl-contrib*) (progn (setf *abcl-contrib* (find-contrib)) (format verbose "~&Using probed value of abcl-contrib:~&'~A'.~%" *abcl-contrib*))) (add-contrib *abcl-contrib*)) (defun find-contrib () "Introspect runtime classpaths to find a loadable ABCL-CONTRIB." (or (ignore-errors (find-contrib-jar)) (ignore-errors (let ((system-jar (find-system-jar))) (when system-jar (probe-file (make-pathname :defaults system-jar :name (concatenate 'string "abcl-contrib" (subseq (pathname-name system-jar) 4))))))) (some (lambda (u) (probe-file (make-pathname :defaults (java:jcall "toString" u) :name "abcl-contrib"))) (java:jcall "getURLs" (boot-classloader))))) (export `(find-system find-contrib *abcl-contrib*)) (when (find-and-add-contrib :verbose t) (provide :abcl-contrib))