source: trunk/abcl/contrib/abcl-asdf/asdf-jar.lisp @ 14967

Last change on this file since 14967 was 14967, checked in by mevenson, 9 months ago

abcl-asdf: introduce JDK-JAR object to describe JDK tags (Alan Ruttenberg)

We introduce an ASDF component JDK-JAR, a jar file where the pathname
and name are relative to the 'java.home' property of the executing
JVM.

Note that the use of JDK-JAR consistutes an experimental interface
with a lot of potential problems going forward. We note some of those
issues for further consideration:

1) Java9 does away with the packaging of system tools in jar files,
using the Java module system to provide "optimized" access to system
resources. Therefore, a better abstraction would be to somehow
describe the artifacts that need to be loaded to satisfy the
dependencies, and then provide mappings to strategies that locate and
load them within the JDK filesystem. c.f. <http://abcl.org/trac/ticket/423>.

2) The structure of the 'java.home' directory varies in unknown ways
between JDK versions and across platforms, making the use of JDK-JAR
relative pathnames need special casing for various situations.

3) ABCL may be run on a JRE runtimes which have a different directory
structure than a JDK, most notably missing the 'tools.jar' artifact.

4) Given the problems arising from points 3 and 4, meaningful
conditions and appropiate restarts should be emitted by ABCL-ASDF when
it cannot satisfy JDK-JAR dependencies. This machinery should also be
extended to the other major current deficiency in ABCL-ASDF lack of
intellible errors/meaningful restarts when Maven cannot be located.

Despite these problems, it is more useful to experiment with being
able to reference JDK artifacts in ABCL-ASDF definitions than not, so
we include JDK-JAR as an experimental feature.

We need some way to mark the JDK-JAR feature as experimental. The
easiest way forward would be to split it off into a separate file
compilation unit with appropiate comments.

Merges <https://github.com/armedbear/abcl/pull/35/files>.

File size: 4.2 KB
Line 
1(in-package :abcl-asdf)
2
3(defvar *added-to-classpath* nil)
4
5(defvar *inhibit-add-to-classpath* nil)
6
7(defun add-directory-jars-to-class-path (directory recursive-p)
8  (loop :for jar :in (if recursive-p 
9                         (all-jars-below directory) 
10                         (directory (merge-pathnames "*.jar" directory)))
11     :do (java:add-to-classpath jar)))
12
13(defun all-jars-below (directory) 
14  (loop :with q = (system:list-directory directory) 
15     :while q :for top = (pop q)
16     :if (null (pathname-name top)) 
17     :do (setq q (append q (all-jars-below top))) 
18     :if (equal (pathname-type top) "jar") 
19     :collect top))
20
21(defun need-to-add-directory-jar? (directory recursive-p)
22  (loop :for jar :in (if recursive-p 
23                         (all-jars-below directory)
24                         (directory (merge-pathnames "*.jar" directory)))
25     :doing (if (not (member (namestring (truename jar)) 
26                             *added-to-classpath* :test 'equal))
27                (return-from need-to-add-directory-jar? t)))
28  nil)
29
30(defmethod java:add-to-classpath :around ((uri-or-uris t) &optional classloader)
31  (declare (ignore classloader))
32  (call-next-method)
33  (if (listp uri-or-uris)
34      (dolist (uri uri-or-uris)
35        (pushnew uri *added-to-classpath*))
36      (pushnew uri-or-uris *added-to-classpath*)))
37
38(in-package :asdf)
39
40(defclass jar-directory (static-file) ())
41
42(defmethod perform ((operation compile-op) (c jar-directory))
43  (unless abcl-asdf:*inhibit-add-to-classpath*
44    (abcl-asdf:add-directory-jars-to-class-path (truename (component-pathname c)) t)))
45
46(defmethod perform ((operation load-op) (c jar-directory))
47  (unless abcl-asdf:*inhibit-add-to-classpath*
48    (abcl-asdf:add-directory-jars-to-class-path (truename (component-pathname c)) t)))
49
50(defmethod operation-done-p ((operation load-op) (c jar-directory))
51  (or abcl-asdf:*inhibit-add-to-classpath*
52      (not (abcl-asdf:need-to-add-directory-jar? (component-pathname c) t))))
53
54(defmethod operation-done-p ((operation compile-op) (c jar-directory))
55  t)
56
57(defclass jar-file (static-file) ())
58
59(defmethod source-file-type ((c jar-file) (s module)) "jar")
60
61(defmethod perform ((operation compile-op) (c jar-file))
62  (java:add-to-classpath (component-pathname c)))
63
64(defmethod perform ((operation load-op) (c jar-file))
65  (or abcl-asdf:*inhibit-add-to-classpath*
66      (java:add-to-classpath (component-pathname c))))
67
68;;; The original JSS specified jar pathnames as having a NAME ending
69;;; in ".jar" without a TYPE.  If we encounter such a definition, we
70;;; clean it up.
71(defmethod normalize-jar-name ((component jar-file))
72  (when (#"endsWith" (slot-value component 'name) ".jar")
73    (with-slots (name absolute-pathname) component
74      (let* ((new-name 
75              (subseq name 0 (- (length name) 4)))
76             (new-absolute-pathname 
77              (make-pathname :defaults absolute-pathname :name new-name)))
78        (setf name new-name
79              absolute-pathname new-absolute-pathname)))))
80
81(defmethod perform :before ((operation compile-op) (c jar-file))
82  (normalize-jar-name c))
83
84(defmethod perform :before ((operation load-op) (c jar-file))
85  (normalize-jar-name c))
86
87(defmethod operation-done-p :before ((operation load-op) (c jar-file))
88  (normalize-jar-name c))
89
90(defmethod operation-done-p ((operation load-op) (c jar-file))
91  (or abcl-asdf:*inhibit-add-to-classpath*
92      (member (namestring (truename (component-pathname c)))
93              abcl-asdf:*added-to-classpath* :test 'equal)))
94
95(defmethod operation-done-p ((operation compile-op) (c jar-file))
96  t)
97
98(defclass class-file-directory (static-file) ())
99
100(defmethod perform ((operation compile-op) (c class-file-directory))
101  (java:add-to-classpath (component-pathname c)))
102
103(defmethod perform ((operation load-op) (c class-file-directory))
104  (java:add-to-classpath (component-pathname c)))
105
106;; a jar file where the pathname and name are relative to JAVA_HOME
107(defclass jdk-jar (jar-file) ())
108
109(defmethod normalize-jar-name :after ((c jdk-jar))
110  (setf (slot-value c 'absolute-pathname)
111  (merge-pathnames
112   (merge-pathnames 
113    (slot-value c 'name)
114    (make-pathname :directory `(:relative ,(slot-value (component-parent c) 'relative-pathname))))
115   (java::jstatic "getProperty" "java.lang.System" "java.home"))))
116
117
118       
Note: See TracBrowser for help on using the repository browser.