aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/tool/compiler/meta/packager/jvm.lux
blob: 15552a65668ad689bd5101a9b4026f535e1eebcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
(.module:
  [lux (#- Module Definition)
   [type (#+ :share)]
   ["." ffi (#+ import: do_to)]
   [abstract
    ["." monad (#+ Monad do)]]
   [control
    ["." try (#+ Try)]
    [concurrency
     ["." promise (#+ Promise)]]
    [security
     ["!" capability]]]
   [data
    ["." binary (#+ Binary)]
    ["." text
     ["%" format (#+ format)]]
    [collection
     ["." row (#+ Row)]
     ["." list ("#\." functor)]]]
   [math
    [number
     ["n" nat]]]
   [target
    [jvm
     [encoding
      ["." name]]]]
   [world
    ["." file (#+ File Directory)]]]
  [program
   [compositor
    ["." static (#+ Static)]]]
  ["." // (#+ Packager)
   [//
    ["." archive
     ["." descriptor (#+ Module)]
     ["." artifact]]
    ["." io #_
     ["#" archive]]
    [//
     [language
      ["$" lux
       [generation (#+ Context)]
       [phase
        [generation
         [jvm
          ["." runtime (#+ Definition)]]]]]]]]])

(import: java/lang/Object)

(import: java/lang/String)

(import: java/util/jar/Attributes
  ["#::."
   (put [java/lang/Object java/lang/Object] #? java/lang/Object)])

(import: java/util/jar/Attributes$Name
  ["#::."
   (#static MAIN_CLASS java/util/jar/Attributes$Name)
   (#static MANIFEST_VERSION java/util/jar/Attributes$Name)])

(import: java/util/jar/Manifest
  ["#::."
   (new [])
   (getMainAttributes [] java/util/jar/Attributes)])

(import: java/io/Flushable
  ["#::."
   (flush [] void)])

(import: java/io/Closeable
  ["#::."
   (close [] void)])

(import: java/io/OutputStream)

(import: java/io/ByteArrayOutputStream
  ["#::."
   (new [int])
   (toByteArray [] [byte])])

(import: java/util/zip/ZipEntry)

(import: java/util/zip/ZipOutputStream
  ["#::."
   (write [[byte] int int] void)
   (closeEntry [] void)])

(import: java/util/jar/JarEntry
  ["#::."
   (new [java/lang/String])])

(import: java/util/jar/JarOutputStream
  ["#::."
   (new [java/io/OutputStream java/util/jar/Manifest])
   (putNextEntry [java/util/zip/ZipEntry] void)])

(def: byte 1)
## https://en.wikipedia.org/wiki/Kibibyte
(def: kibi_byte (n.* 1,024 byte))
## https://en.wikipedia.org/wiki/Mebibyte
(def: mebi_byte (n.* 1,024 kibi_byte))

(def: manifest_version "1.0")

(def: (manifest program)
  (-> Context java/util/jar/Manifest)
  (let [manifest (java/util/jar/Manifest::new)]
    (exec (do_to (java/util/jar/Manifest::getMainAttributes manifest)
                 (java/util/jar/Attributes::put (java/util/jar/Attributes$Name::MAIN_CLASS) (|> program runtime.class_name name.internal name.external))
                 (java/util/jar/Attributes::put (java/util/jar/Attributes$Name::MANIFEST_VERSION) ..manifest_version))
      manifest)))

## TODO: Delete ASAP
(type: (Action ! a)
  (! (Try a)))

(def: (write_class monad file_system static context sink)
  (All [!]
    (-> (Monad !) (file.System !) Static Context java/util/jar/JarOutputStream
        (Action ! java/util/jar/JarOutputStream)))
  (do (try.with monad)
    [artifact (let [[module artifact] context]
                (!.use (\ file_system file) [(io.artifact file_system static module (%.nat artifact))]))
     content (!.use (\ artifact content) [])
     #let [class_path (format (runtime.class_name context) (get@ #static.artifact_extension static))]]
    (wrap (do_to sink
                 (java/util/jar/JarOutputStream::putNextEntry (java/util/jar/JarEntry::new class_path))
                 (java/util/zip/ZipOutputStream::write content +0 (.int (binary.size content)))
                 (java/io/Flushable::flush)
                 (java/util/zip/ZipOutputStream::closeEntry)))))

(def: (write_module monad file_system static [module artifacts] sink)
  (All [!]
    (-> (Monad !) (file.System !) Static [archive.ID (List artifact.ID)] java/util/jar/JarOutputStream
        (Action ! java/util/jar/JarOutputStream)))
  (monad.fold (:assume (try.with monad))
              (function (_ artifact sink)
                (..write_class monad file_system static [module artifact] sink))
              sink
              artifacts))

(def: #export (package monad file_system static archive program)
  (All [!] (Packager !))
  (do {! (try.with monad)}
    [cache (:share [!]
                   {(Monad !)
                    monad}
                   {(! (Try (Directory !)))
                    (:assume (!.use (\ file_system directory) [(get@ #static.target static)]))})
     order (|> archive
               archive.archived
               (monad.map try.monad (function (_ module)
                                      (do try.monad
                                        [[descriptor document] (archive.find module archive)
                                         module_id (archive.id module archive)]
                                        (wrap (|> descriptor
                                                  (get@ #descriptor.registry)
                                                  artifact.artifacts
                                                  row.to_list
                                                  (list\map (|>> (get@ #artifact.id)))
                                                  [module_id])))))
               (\ monad wrap))
     #let [buffer (java/io/ByteArrayOutputStream::new (.int ..mebi_byte))
           sink (java/util/jar/JarOutputStream::new buffer (..manifest program))]
     sink (monad.fold ! (..write_module monad file_system static) sink order)
     #let [_ (do_to sink
                    (java/io/Flushable::flush)
                    (java/io/Closeable::close))]]
    (wrap (java/io/ByteArrayOutputStream::toByteArray buffer))))