source: tags/1.0.0/abcl/contrib/abcl-asdf/maven-embedder.lisp

Last change on this file was 13575, checked in by Mark Evenson, 13 years ago

Update ABCL-ASDF contrib to 0.4.1.

Document functions a bit better. Include an example that can be used
without reference to ASDF.

File size: 7.4 KB
Line 
1;;; Use the Aether system in a default maven distribution to download
2;;; and install dependencies.
3;;;
4;;; https://docs.sonatype.org/display/AETHER/Home
5;;;
6
7(in-package :abcl-asdf)
8
9(require :abcl-contrib)
10(require :jss)
11
12#|
13Test:
14(resolve-dependencies "org.slf4j" "slf4j-api" "1.6.1")
15
16(resolve-dependencies "org.apache.maven" "maven-aether-provider" "3.0.3")
17|#
18
19(defvar *mavens* '("/opt/local/bin/mvn3" "mvn3" "mvn" "mvn.bat")
20  "Locations to search for the Maven executable.")
21
22(defun find-mvn () 
23  (dolist (mvn-path *mavens*)
24    (let ((mvn 
25           (handler-case 
26               (truename (read-line (sys::process-output 
27                                     (sys::run-program "which" `(,mvn-path)))))
28             (end-of-file () nil))))
29      (when mvn
30        (return-from find-mvn mvn)))))
31
32(defun find-mvn-libs ()
33  (let ((mvn (find-mvn)))
34    (unless mvn
35      (warn "Failed to find Maven3 libraries.")
36      (return-from find-mvn-libs))
37    (truename (make-pathname 
38               :defaults (merge-pathnames "../lib/" mvn)
39               :name nil :type nil))))
40
41(defparameter *mvn-libs-directory*
42  nil
43  "Location of 'maven-core-3.<m>.<p>.jar', 'maven-embedder-3.<m>.<p>.jar' etc.")
44
45(defun mvn-version ()
46  (let* ((line
47         (read-line (sys::process-output 
48                     (sys::run-program 
49                      (namestring (find-mvn)) '("-version")))))
50         (pattern (#"compile" 
51                   'regex.Pattern
52                   "Apache Maven ([0-9]+)\\.([0-9]+)\\.([0-9]+)"))
53         (matcher (#"matcher" pattern line))
54         (found (#"find" matcher)))
55    (unless found 
56      (return-from mvn-version nil))
57    (mapcar #'parse-integer
58            `(,(#"group" matcher 1)
59              ,(#"group" matcher 2)
60              ,(#"group" matcher 3)))))
61
62(defun ensure-mvn-version ()
63  "Return t if Maven version is 3.0.3 or greater."
64  (let* ((version (mvn-version))
65         (major (first version))
66         (minor (second version))
67         (patch (third version)))
68    (or 
69     (and (>= major 3)
70          (>= minor 1))
71     (and (>= major 3)
72          (>= major 0)
73          (>= patch 3)))))
74
75(defparameter *init* nil)
76
77(defun init ()
78  (unless *mvn-libs-directory*
79    (setf *mvn-libs-directory* (find-mvn-libs)))
80  (unless (probe-file *mvn-libs-directory*)
81    (error "You must download maven-3.0.3 from http://maven.apache.org/download.html, then set ABCL-ASDF:*MVN-DIRECTORY* appropiately."))
82  (unless (ensure-mvn-version)
83    (error "We need maven-3.0.3 or later."))
84  (add-directory-jars-to-class-path *mvn-libs-directory* nil)
85  (setf *init* t))
86
87(defun make-wagon-provider ()
88  (unless *init* (init))
89  (java:jinterface-implementation 
90   "org.sonatype.aether.connector.wagon.WagonProvider"
91   "lookup"
92   (lambda (role-hint)
93     (if (string-equal "http" role-hint)
94       (java:jnew "org.apache.maven.wagon.providers.http.LightweightHttpWagon")
95       java:+null+))
96   "release"
97   (lambda (wagon)
98     (declare (ignore wagon)))))
99
100(defun repository-system ()
101  (unless *init* (init))
102  (let ((locator 
103         (java:jnew "org.apache.maven.repository.internal.DefaultServiceLocator"))
104        (repository-connector-factory-class 
105         (java:jclass "org.sonatype.aether.spi.connector.RepositoryConnectorFactory"))
106        (wagon-repository-connector-factory-class
107         (java:jclass "org.sonatype.aether.connector.wagon.WagonRepositoryConnectorFactory"))
108        (wagon-provider-class 
109         (java:jclass "org.sonatype.aether.connector.wagon.WagonProvider"))
110        (repository-system-class
111         (java:jclass "org.sonatype.aether.RepositorySystem")))
112    (#"addService" locator
113                   repository-connector-factory-class 
114                   wagon-repository-connector-factory-class)
115    (#"setServices" locator
116                    wagon-provider-class
117                    (java:jnew-array-from-list 
118                     "org.sonatype.aether.connector.wagon.WagonProvider"
119                     (list 
120                      (make-wagon-provider))))
121    (#"getService" locator
122                   repository-system-class)))
123       
124(defun new-session (repository-system)
125  (let ((session 
126         (java:jnew (jss:find-java-class "MavenRepositorySystemSession")))
127        (local-repository 
128         (java:jnew (jss:find-java-class "LocalRepository")
129                  (namestring (merge-pathnames ".m2/repository/"
130                                               (user-homedir-pathname))))))
131    (#"setLocalRepositoryManager" 
132     session
133     (#"newLocalRepositoryManager" repository-system local-repository))))
134
135(defun resolve-artifact (group-id artifact-id &optional (version "LATEST" versionp))
136  "Dynamically resolve Maven dependencies for item with GROUP-ID and ARTIFACT-ID at VERSION.
137
138Declared dependencies are not attempted to be located.
139
140If unspecified, the string \"LATEST\" will be used for the VERSION.
141
142Returns a string containing the necessary jvm classpath entries packed
143in Java CLASSPATH representation."
144
145  (unless versionp
146    (warn "Using LATEST for unspecified version."))
147  (let* ((system 
148          (repository-system))
149         (session 
150          (new-session system))
151         (repository 
152          (jss:new "org.sonatype.aether.repository.RemoteRepository"
153                   "central" "default" "http://repo1.maven.org/maven2/"))
154         (artifact-string (format nil "~A:~A:~A"
155                                  group-id artifact-id version))
156         (artifact 
157          (jss:new "org.sonatype.aether.util.artifact.DefaultArtifact" artifact-string))
158         (artifact-request 
159          (java:jnew "org.sonatype.aether.resolution.ArtifactRequest")))
160    (#"setArtifact" artifact-request artifact)
161    (#"addRepository" artifact-request repository)
162    (#"resolveArtifact" system session artifact-request)))
163
164(defun resolve-dependencies (group-id artifact-id &optional (version "LATEST" versionp))
165  "Dynamically resolve Maven dependencies for item with GROUP-ID and ARTIFACT-ID at VERSION.
166
167All recursive dependencies will be visited before resolution is successful.
168
169If unspecified, the string \"LATEST\" will be used for the VERSION.
170
171Returns a string containing the necessary jvm classpath entries packed
172in Java CLASSPATH representation."
173  (unless *init* (init))
174  (unless versionp
175    (warn "Using LATEST for unspecified version."))
176  (let* ((system 
177          (repository-system))
178         (session 
179          (new-session system))
180         (artifact
181          (java:jnew (jss:find-java-class "aether.util.artifact.DefaultArtifact")
182                     (format nil "~A:~A:~A"
183                             group-id artifact-id version)))
184         (dependency 
185          (java:jnew (jss:find-java-class "aether.graph.Dependency")
186                     artifact "compile"))
187         (central
188          (java:jnew (jss:find-java-class "RemoteRepository")
189                     "central" "default" "http://repo1.maven.org/maven2/"))
190         (collect-request (java:jnew (jss:find-java-class "CollectRequest"))))
191    (#"setRoot" collect-request dependency)
192    (#"addRepository" collect-request central)
193    (let* ((node 
194            (#"getRoot" (#"collectDependencies" system session collect-request)))
195           (dependency-request 
196            (java:jnew (jss:find-java-class "DependencyRequest")
197                       node java:+null+))
198           (nlg 
199            (java:jnew (jss:find-java-class "PreorderNodeListGenerator"))))
200      (#"resolveDependencies" system session dependency-request)
201      (#"accept" node nlg)
202      (#"getClassPath" nlg))))
203
204
205
206
207         
208
Note: See TracBrowser for help on using the repository browser.