source: trunk/abcl/contrib/abcl-asdf/maven-embedder.lisp @ 13367

Last change on this file since 13367 was 13367, checked in by Mark Evenson, 10 years ago

RESOLVE-DEPENDENCIES now working for remote resolution.

Something like

CL-USER> (require :abcl-asdf)
CL-USER> (abcl-asdf:resolve-dependencies "org.slf4j" "slf4j-api" "1.6.1")

should download the required dependencies for the corresponding Maven
artifact, returning the result as a string suitable for inclusion in
the CLASSPATH.

Abandoned strategy of using Maven Ant tasks to directly maniuplating
the Aether API in contemporary version of Maven 3.

Remove MVN package, folding symbols into ABCL-ASDF until clearer API
vision is in place as there is no need to complicate things at this
point.

The ASDF links are not currently working, nor is the ability to find
the Maven location under WIN32 as the resolution mechanism currently
uses UNIX 'which'.

File size: 6.6 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  (jss: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 version)
136  (let* ((system 
137          (repository-system))
138         (session 
139          (new-session system))
140         (repository 
141          (jss:new "org.sonatype.aether.repository.RemoteRepository"
142                   "central" "default" "http://repo1.maven.org/maven2/"))
143         (artifact-string (format nil "~A:~A:~A"
144                                  group-id artifact-id version))
145         (artifact 
146          (jss:new "org.sonatype.aether.util.artifact.DefaultArtifact" artifact-string))
147         (artifact-request 
148          (java:jnew "org.sonatype.aether.resolution.ArtifactRequest")))
149    (#"setArtifact" artifact-request artifact)
150    (#"addRepository" artifact-request repository)
151    (#"resolveArtifact" system session artifact-request)))
152
153(defun resolve-dependencies (group-id artifact-id version)
154  (unless *init* (init))
155  (let* ((system 
156          (repository-system))
157         (session 
158          (new-session system))
159         (artifact
160          (java:jnew (jss:find-java-class "aether.util.artifact.DefaultArtifact")
161                     (format nil "~A:~A:~A"
162                             group-id artifact-id version)))
163         (dependency 
164          (java:jnew (jss:find-java-class "aether.graph.Dependency")
165                     artifact "compile"))
166         (central
167          (java:jnew (jss:find-java-class "RemoteRepository")
168                     "central" "default" "http://repo1.maven.org/maven2/"))
169         (collect-request (java:jnew (jss:find-java-class "CollectRequest"))))
170    (#"setRoot" collect-request dependency)
171    (#"addRepository" collect-request central)
172    (let* ((node 
173            (#"getRoot" (#"collectDependencies" system session collect-request)))
174           (dependency-request 
175            (java:jnew (jss:find-java-class "DependencyRequest")
176                       node java:+null+))
177           (nlg 
178            (java:jnew (jss:find-java-class "PreorderNodeListGenerator"))))
179      (#"resolveDependencies" system session dependency-request)
180      (#"accept" node nlg)
181      (#"getClassPath" nlg))))
182
183
184
185
186         
187
Note: See TracBrowser for help on using the repository browser.