comparison src/name/blackcap/exifwasher/exiv2/Initialize.kt @ 0:db63d01a23c6

JNI calls and test case (finally!) seem to work.
author David Barts <n5jrn@me.com>
date Tue, 31 Mar 2020 13:24:48 -0700
parents
children 42277ce58ace
comparison
equal deleted inserted replaced
-1:000000000000 0:db63d01a23c6
1 /*
2 * Logic common to initializing all external (JNI) classes goes here.
3 */
4 package name.blackcap.exifwasher.exiv2
5
6 import java.io.File
7 import java.io.FileOutputStream
8 import java.io.IOException
9 import java.util.jar.JarEntry
10 import java.util.jar.JarFile
11 import name.blackcap.exifwasher.LF_DIR
12 import name.blackcap.exifwasher.OS
13
14 object Initialize {
15 private var initialized = false
16
17 public fun libraries() {
18 /* no-op if already initialized */
19 if (initialized) {
20 return
21 }
22
23 /* use the appropriate binary for the system we're on */
24 val subdir = when(OS.type) {
25 OS.UNIX -> "linux"
26 OS.MAC -> "mac"
27 OS.WINDOWS -> "windows"
28 OS.OTHER -> throw RuntimeException("unsupported OS!")
29 }
30 val ext = when(OS.type) {
31 OS.UNIX -> "so"
32 OS.MAC -> "dylib"
33 OS.WINDOWS -> "dll"
34 OS.OTHER -> throw RuntimeException("unsupported OS!")
35 }
36
37 /* extract to scratch files, if needed, then load */
38 val klass = Initialize::class.java
39 var myJar = JarFile(File(klass.getProtectionDomain().getCodeSource().getLocation().toURI()))
40 for (base in arrayOf("libexiv2", "libjni")) {
41 val eBase = "${base}.${ext}"
42 val sPath = "name/blackcap/exifwasher/binaries/${subdir}/${eBase}"
43 val source = myJar.getJarEntry(sPath)
44 if (source == null) {
45 die("${sPath} not found in jar")
46 }
47 val target = File(LF_DIR, eBase)
48 val tPath = target.toString()
49 try {
50 if (!target.exists() || target.lastModified() < source.getTime()) {
51 myJar.getInputStream(source).use { sfp ->
52 FileOutputStream(target).use { tfp ->
53 sfp.copyTo(tfp)
54 }
55 }
56 target.setExecutable(true)
57 target.setLastModified(source.getTime())
58 }
59 } catch (e: IOException) {
60 val message = e.message ?: "I/O error"
61 die("unable to create ${tPath}: ${message}")
62 }
63 try {
64 println("loading: ${tPath}") /* debug */
65 System.load(tPath)
66 } catch (e: UnsatisfiedLinkError) {
67 val message = e.message ?: "unsatisfied link"
68 die("unable to link ${tPath}: ${message}")
69 }
70 }
71
72 initialized = true
73 System.err.println("libraries loaded") /* debug */
74 }
75
76 private fun die(message: String) {
77 /* should open a dialog */
78 System.err.println(message)
79 System.exit(1)
80 }
81 }