| 1 | ;;;; The ABCL specific overrides in ASDF. |
|---|
| 2 | ;;;; |
|---|
| 3 | ;;;; Extensions to ASDF for use by ABCL |
|---|
| 4 | (require :asdf) |
|---|
| 5 | (in-package :asdf) |
|---|
| 6 | |
|---|
| 7 | (defclass iri (component) |
|---|
| 8 | ((schema :initform nil) |
|---|
| 9 | (authority :initform nil) |
|---|
| 10 | (path :initform nil) |
|---|
| 11 | (query :initform nil) |
|---|
| 12 | (fragment :initform nil))) |
|---|
| 13 | |
|---|
| 14 | (defclass mvn (iri) |
|---|
| 15 | ((group-id :initarg :group-id :initform nil) |
|---|
| 16 | (artifact-id :initarg :artifact-id :initform nil) |
|---|
| 17 | (repositories :initarg :repositories :initform (list abcl-asdf::*default-repository*)) |
|---|
| 18 | (resolved-classpath :initform nil :accessor resolved-classpath) |
|---|
| 19 | (classname :initarg :classname :initform nil) |
|---|
| 20 | (alternate-uri :initarg :alternate-uri :initform nil) |
|---|
| 21 | ;; inherited from ASDF:COMPONENT ??? what are the CL semantics on overriding -- ME 2012-04-01 |
|---|
| 22 | #+nil (version :initform nil))) |
|---|
| 23 | |
|---|
| 24 | (defmethod shared-initialize ((mvn mvn) slot-names &rest initargs &key (repository NIL repository-p) repositories &allow-other-keys) |
|---|
| 25 | (if repository-p |
|---|
| 26 | (let ((initargs (list* :repositories (cons repository repositories) |
|---|
| 27 | (remove-plist-keys '(:repository :repositories) initargs)))) |
|---|
| 28 | (apply #'call-next-method mvn slot-names initargs)) |
|---|
| 29 | (call-next-method))) |
|---|
| 30 | |
|---|
| 31 | ;;; We intercept compilation to ensure that load-op will succeed |
|---|
| 32 | (defmethod perform ((op compile-op) (c mvn)) |
|---|
| 33 | (unless (resolved-classpath c) |
|---|
| 34 | (setf (resolved-classpath c) |
|---|
| 35 | (abcl-asdf:resolve |
|---|
| 36 | (ensure-parsed-mvn c))))) |
|---|
| 37 | |
|---|
| 38 | (defmethod perform ((operation load-op) (c mvn)) |
|---|
| 39 | (let ((resolved-classpath (resolved-classpath c))) |
|---|
| 40 | (when (stringp resolved-classpath) |
|---|
| 41 | (java:add-to-classpath (abcl-asdf:as-classpath resolved-classpath))))) |
|---|
| 42 | |
|---|
| 43 | ;;; A Maven URI has the form "mvn:group-id/artifact-id/version" |
|---|
| 44 | ;;; |
|---|
| 45 | ;;; Sometimes people write "group-id:artifact-id:version" to refer to |
|---|
| 46 | ;;; Maven artifacts. One can use ABCL-ASDF:RESOLVE directly for |
|---|
| 47 | ;;; serialized references to artifacts of this form. |
|---|
| 48 | ;;; |
|---|
| 49 | ;;; Currently we "stuff" the group-id/artifact-id into the 'name' and |
|---|
| 50 | ;;; use the component 'version' for the version. Parts of ASDF |
|---|
| 51 | ;;; *reallY* want ASDF:VERSION to be a triple of intergers, and never |
|---|
| 52 | ;;; anything more, so that is part of the motivation behind this effort. |
|---|
| 53 | (defparameter *mvn-repositories* nil |
|---|
| 54 | "A list of all Maven repositories encountered in the lifetime of this instance of the implementation.") |
|---|
| 55 | |
|---|
| 56 | #+nil |
|---|
| 57 | (defmethod slot-missing ((class mvn) object slot-name operation &optional new-value) |
|---|
| 58 | (setf (slot-value object slot-name) |
|---|
| 59 | (if new-value |
|---|
| 60 | new-value |
|---|
| 61 | nil))) |
|---|
| 62 | |
|---|
| 63 | (defun ensure-parsed-mvn (component) |
|---|
| 64 | (with-slots (name group-id artifact-id |
|---|
| 65 | version schema path repositories) |
|---|
| 66 | component |
|---|
| 67 | (when (null asdf::artifact-id) |
|---|
| 68 | (let ((parsed (abcl-asdf::split-string name "/")) |
|---|
| 69 | (asdf-version-p (slot-boundp component 'version)) |
|---|
| 70 | (default-version "LATEST")) |
|---|
| 71 | (cond ((= (length parsed) 3) |
|---|
| 72 | (setf |
|---|
| 73 | group-id (first parsed) |
|---|
| 74 | artifact-id (second parsed) |
|---|
| 75 | version (third parsed))) |
|---|
| 76 | ((= (length parsed) 2) |
|---|
| 77 | (setf |
|---|
| 78 | group-id (first parsed) |
|---|
| 79 | artifact-id (second parsed) |
|---|
| 80 | version (if asdf-version-p |
|---|
| 81 | version |
|---|
| 82 | default-version))) |
|---|
| 83 | (t |
|---|
| 84 | (error "Failed to construct a mvn reference from name '~A' and version '~A'" |
|---|
| 85 | name version))) |
|---|
| 86 | (setf schema "mvn") |
|---|
| 87 | (when repositories |
|---|
| 88 | (setf *mvn-repositories* (union repositories *mvn-repositories* :test #'string=))) |
|---|
| 89 | ;;; Always set path to normalized path "on the way out" to |
|---|
| 90 | ;;; contain group-id/artifact-id/version |
|---|
| 91 | ;;; TODO? record repository as well in path of component |
|---|
| 92 | (setf path (format nil "~A/~A/~A" group-id artifact-id version)))) |
|---|
| 93 | component)) |
|---|
| 94 | |
|---|
| 95 | (eval-when (:compile-toplevel :load-toplevel :execute) |
|---|
| 96 | (export `(mvn iri ensure-parsed-mvn group-id artifact-id version) |
|---|
| 97 | 'asdf)) |
|---|
| 98 | |
|---|
| 99 | (defmethod source-file-type ((component iri) (system system)) |
|---|
| 100 | nil) |
|---|
| 101 | |
|---|
| 102 | (defmethod component-relative-pathname ((component iri)) |
|---|
| 103 | nil) |
|---|
| 104 | |
|---|
| 105 | (in-package #:abcl-asdf) |
|---|
| 106 | |
|---|
| 107 | (defgeneric resolve (something) |
|---|
| 108 | (:documentation "Returns a string in JVM CLASSPATH format as entries delimited by classpath separator string.")) |
|---|
| 109 | |
|---|
| 110 | (defmethod resolve ((mvn-component asdf::mvn)) |
|---|
| 111 | "Resolve all runtime dependencies of MVN-COMPONENT. |
|---|
| 112 | |
|---|
| 113 | Returns either a string in jvm classpath format as entries delimited |
|---|
| 114 | by classpath separator string or T. If the value T is returned, it |
|---|
| 115 | denotes that current JVM already has already loaded a given class. Can possibly be a |
|---|
| 116 | single entry denoting a remote binary artifact." |
|---|
| 117 | (asdf::ensure-parsed-mvn mvn-component) |
|---|
| 118 | (let ((name (slot-value mvn-component 'asdf::name)) |
|---|
| 119 | (group-id (slot-value mvn-component 'asdf::group-id)) |
|---|
| 120 | (artifact-id (slot-value mvn-component 'asdf::artifact-id)) |
|---|
| 121 | (classname (slot-value mvn-component 'asdf::classname)) |
|---|
| 122 | (alternate-uri (slot-value mvn-component 'asdf::alternate-uri)) |
|---|
| 123 | (repositories (slot-value mvn-component 'asdf::repositories)) |
|---|
| 124 | (version (if (slot-value mvn-component 'asdf::version) |
|---|
| 125 | (slot-value mvn-component 'asdf::version) |
|---|
| 126 | "LATEST"))) |
|---|
| 127 | (handler-case |
|---|
| 128 | (when (and classname |
|---|
| 129 | (let ((jss:*muffle-warnings* T)) |
|---|
| 130 | (jss:find-java-class classname))) |
|---|
| 131 | (warn "Not loading ~A from the network because ~A is present in classpath." |
|---|
| 132 | name classname) |
|---|
| 133 | (return-from resolve t)) |
|---|
| 134 | (java:java-exception (e) |
|---|
| 135 | (unless (java:jinstance-of-p (java:java-exception-cause e) |
|---|
| 136 | "java.lang.ClassNotFoundException") |
|---|
| 137 | (error "Unexpected Java exception~&~A.~&" e)))) |
|---|
| 138 | (let ((result (ignore-errors |
|---|
| 139 | (with-aether () |
|---|
| 140 | (resolve-dependencies group-id artifact-id |
|---|
| 141 | :version version |
|---|
| 142 | :repository NIL |
|---|
| 143 | :repositories repositories))))) |
|---|
| 144 | (if result |
|---|
| 145 | result |
|---|
| 146 | ;; The alternate-uri facility doesn't currently work. |
|---|
| 147 | ;; It would only work if there is a single jar that |
|---|
| 148 | ;; corresponds to a dependency, which is often not the case. |
|---|
| 149 | ;; probably should just remove⊠|
|---|
| 150 | (if alternate-uri |
|---|
| 151 | (values (pathname alternate-uri) alternate-uri) |
|---|
| 152 | (error "Failed to resolve MVN component name ~A." name)))))) |
|---|
| 153 | |
|---|
| 154 | (defmethod resolve ((uri pathname)) |
|---|
| 155 | (warn "Unimplemented.")) |
|---|
| 156 | |
|---|
| 157 | (defun as-classpath (classpath) |
|---|
| 158 | "Break apart the JVM CLASSPATH string into a list of its consituents." |
|---|
| 159 | (split-string classpath |
|---|
| 160 | (java:jfield "java.io.File" "pathSeparator"))) |
|---|
| 161 | |
|---|