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
|
package cz.crcs.ectester.standalone.libs;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.Provider;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class NativeECLibrary extends ProviderECLibrary {
private String resource;
private String[] requriements;
public static String LIB_RESOURCE_DIR = "/cz/crcs/ectester/standalone/libs/jni/";
public NativeECLibrary(String resource, String... requirements) {
this.resource = resource;
this.requriements = requirements;
}
@Override
public boolean initialize() {
try {
/* Determine what OS are we running on and use appropriate suffix and path. */
String suffix;
Path appData;
if (System.getProperty("os.name").startsWith("Windows")) {
suffix = "dll";
appData = Paths.get(System.getenv("AppData"));
} else {
suffix = "so";
if (System.getProperty("os.name").startsWith("Linux")) {
String dataHome = System.getenv("XDG_DATA_HOME");
if (dataHome != null) {
appData = Paths.get(dataHome);
} else {
appData = Paths.get(System.getProperty("user.home"), ".local", "share");
}
} else {
appData = Paths.get(System.getProperty("user.home"), ".local", "share");
}
}
/* Resolve and create the ECTester directories in appData. */
Path libDir = appData.resolve("ECTesterStandalone");
File libDirFile = libDir.toFile();
Path libReqDir = libDir.resolve("lib");
File libReqDirFile = libReqDir.toFile();
Path libPath = libDir.resolve(resource + "." + suffix);
/* Create directory for shims and for requirements. */
libDirFile.mkdirs();
libReqDirFile.mkdirs();
/* Write the shim. */
writeNewer(resource + "." + suffix, libPath);
/*
* Need to hack in /usr/local/lib to path.
* See: https://stackoverflow.com/questions/5419039/is-djava-library-path-equivalent-to-system-setpropertyjava-library-path/24988095#24988095
*/
String path = System.getProperty("java.library.path");
if (suffix.equals("so")) {
String newPath = path + ":/usr/local/lib";
System.setProperty("java.library.path", newPath);
Field fieldSysPath;
try {
fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
/* Load the requirements, if they are bundled, write them in and load them. */
try {
for (String requirement : requriements) {
if (requirement.endsWith(suffix)) {
/* The requirement is bundled, write it */
Path reqPath = libReqDir.resolve(requirement);
writeNewer(requirement, reqPath);
System.load(reqPath.toString());
} else {
System.loadLibrary(requirement);
}
}
} catch (UnsatisfiedLinkError ule) {
return false;
} finally {
if (suffix.equals("so")) {
System.setProperty("java.library.path", path);
}
}
System.load(libPath.toString());
provider = createProvider();
return super.initialize();
} catch (IOException | UnsatisfiedLinkError ex) {
System.err.println(ex.getMessage());
}
return false;
}
private boolean isNewer(URLConnection jarConn, Path realPath) throws IOException {
if (realPath.toFile().isFile()) {
long jarModified = jarConn.getLastModified();
long realModified = Files.getLastModifiedTime(realPath).toMillis();
return jarModified > realModified;
}
return true;
}
private boolean writeNewer(String resource, Path outPath) throws IOException {
URL reqURL = NativeECLibrary.class.getResource(LIB_RESOURCE_DIR + resource);
if (reqURL == null) {
return false;
}
URLConnection reqConn = reqURL.openConnection();
if (isNewer(reqConn, outPath)) {
Files.copy(reqConn.getInputStream(), outPath, StandardCopyOption.REPLACE_EXISTING);
}
reqConn.getInputStream().close();
return true;
}
abstract Provider createProvider();
}
|