abcl-asdf.lisp 5.03 KB
Newer Older
1 2 3
;;;; The ABCL specific overrides in ASDF.  
;;;;
;;;; Done separate from asdf.lisp for stability.
4
(require :asdf)
5
(in-package :asdf)
6

7 8 9 10 11 12
(defclass iri (component) 
  ((schema :initform nil)
   (authority :initform nil)
   (path :initform nil)
   (query :initform nil)
   (fragment :initform nil)))
13

14
(defclass mvn (iri) 
15 16
  ((group-id :initarg :group-id :initform nil)
   (artifact-id :initarg :artifact-id :initform nil)
17 18
   (repository :initform "http://repo1.maven.org/maven2/") ;;; XXX unimplmented
;; inherited from ASDF:COMPONENT ??? what are the CL semantics on overriding -- ME 2012-04-01
19
#+nil   (version :initform nil)))
20 21 22 23

#+nil
(defmethod find-component ((component iri) path)
  component)
24

25

26
;;; We intercept compilation to ensure that load-op will succeed
27
(defmethod perform ((op compile-op) (c mvn))
28 29
  (abcl-asdf:resolve   
   (ensure-parsed-mvn c)))
30
     
31
(defmethod perform ((operation load-op) (c mvn))
32 33
  (java:add-to-classpath 
   (abcl-asdf:as-classpath 
34 35
    (abcl-asdf:resolve 
     (ensure-parsed-mvn c)))))
36 37 38

;;; A Maven URI has the form "mvn:group-id/artifact-id/version"
;;;
39 40 41 42
;;; Sometimes people write "group-id:artifact-id:version" to refer to
;;; Maven artifacts.  One can use ABCL-ASDF:RESOLVE directly for
;;; serialized references to artifacts of this form.
;;;
43
;;; Currently we "stuff" the group-id/artifact-id into the 'name' and
44 45 46
;;; use the component 'version' for the version.  Parts of ASDF 
;;; *reallY* want ASDF:VERSION to be a triple of intergers, and never
;;; anything more, so that is part of the motivation behind this effort.
47 48 49
(defparameter *mvn-repositories* nil
  "A list of all Maven repositories encountered in the lifetime of this instance of the implementation.")

50 51 52 53 54 55 56
#+nil
(defmethod slot-missing ((class mvn) object slot-name operation &optional new-value)
  (setf (slot-value object slot-name) 
        (if new-value
            new-value
            nil)))

57
(defun ensure-parsed-mvn (component)
58
  (with-slots (name group-id artifact-id
59
               version schema path repository) 
60
      component
61
    (when (null asdf::artifact-id) 
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
      (let ((parsed (abcl-asdf::split-string name "/"))
            (asdf-version-p (slot-boundp component 'version))
            (default-version "LATEST"))
        (cond ((= (length parsed) 3)
               (setf 
                group-id (first parsed)
                artifact-id (second parsed)
                version (third parsed)))
              ((= (length parsed) 2)
               (setf 
                group-id (first parsed)
                artifact-id (second parsed)
                version (if asdf-version-p
                            version
                            default-version)))
              (t
               (error "Failed to construct a mvn reference from name '~A' and version '~A'"
                      name version)))
        (setf schema "mvn")
81
        (pushnew repository *mvn-repositories*)
82
        ;;; Always normalized path "on the way out" to contain group-id/artifact-id/version
83 84 85 86 87
        (setf path (format nil "~A/~A/~A" group-id artifact-id version))))
    component))

(export `(mvn iri ensure-parsed-mvn
              group-id artifact-id version) 'asdf)
88 89 90 91 92 93

(defmethod source-file-type ((component iri) (system system))
  nil)

(defmethod component-relative-pathname ((component iri))
  nil)
94

95
(in-package #:abcl-asdf)
96

97
(defgeneric resolve (something)
98
 (:documentation "Returns a string in JVM CLASSPATH format as entries delimited by classpath separator string."))
99

100
(defmethod resolve ((mvn-component asdf::mvn))
101 102
  "Resolve all runtime dependencies of MVN-COMPONENT.

103 104 105
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."
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
  (macrolet ((aif (something consequence alternative))
             `(let ((it ,(something)))
                (if it
                    consequence
                    alternative)))
    (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))
          (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 
123 124 125
            ((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))
126 127 128
            (t 
             (error "Failed to resolve MVN component name ~A." name)))))))
  
129
(defun as-classpath (classpath)
130
  "Break apart the JVM CLASSPATH string into a list of its consituents."
131 132
  (split-string classpath 
                (java:jfield "java.io.File" "pathSeparator")))
133

134 135 136 137
(defun split-string (string split-char)
  (loop :for i = 0 :then (1+ j)
     :as j = (position split-char string :test #'string-equal :start i)
     :collect (subseq string i j)
138
     :while j))