Skip to content

Commit b82c9e3

Browse files
committed
Merge pull request peter-lawrey#24 from isopov/master
Fix for Issue peter-lawrey#11 - Eliminate the need to manually deal with LD_library path
2 parents 62ee4a9 + 85cc0e0 commit b82c9e3

File tree

4 files changed

+217
-16
lines changed

4 files changed

+217
-16
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
libaffinity.so
2-
31
affinity.iml
42

53
affinity.ipr

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
<groupId>vanilla.java</groupId>
2424
<artifactId>affinity</artifactId>
25-
<version>1.5.3</version>
25+
<version>1.5.4-SNAPSHOT</version>
2626
<packaging>jar</packaging>
2727

2828
<licenses>

src/main/java/vanilla/java/affinity/impl/NativeAffinity.java

Lines changed: 216 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,34 @@
1616

1717
package vanilla.java.affinity.impl;
1818

19-
import vanilla.java.affinity.IAffinity;
20-
19+
import java.io.BufferedInputStream;
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.File;
22+
import java.io.FileInputStream;
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.security.DigestInputStream;
27+
import java.security.MessageDigest;
28+
import java.security.NoSuchAlgorithmException;
29+
import java.util.Properties;
2130
import java.util.logging.Level;
2231
import java.util.logging.Logger;
2332

33+
import vanilla.java.affinity.IAffinity;
34+
2435
/**
2536
* @author peter.lawrey
2637
*/
2738
public enum NativeAffinity implements IAffinity {
2839
INSTANCE;
2940

3041
public static final boolean LOADED;
31-
private static final Logger LOGGER = Logger.getLogger(NativeAffinity.class.getName());
42+
private static final Logger LOGGER = Logger.getLogger(NativeAffinity.class
43+
.getName());
3244

3345
static {
34-
boolean loaded;
35-
try {
36-
System.loadLibrary("affinity");
37-
loaded = true;
38-
} catch (UnsatisfiedLinkError ule) {
39-
if (LOGGER.isLoggable(Level.INFO))
40-
LOGGER.info("Unable to find libaffinity in " + System.getProperty("java.library.path") + " " + ule);
41-
loaded = false;
42-
}
43-
LOADED = loaded;
46+
LOADED = loadAffinityNativeLibrary();
4447
}
4548

4649
private native static long getAffinity0();
@@ -56,4 +59,204 @@ public long getAffinity() {
5659
public void setAffinity(long affinity) {
5760
setAffinity0(affinity);
5861
}
62+
63+
private static boolean initialize() {
64+
return loadAffinityNativeLibrary();
65+
}
66+
67+
/**
68+
* Computes the MD5 value of the input stream
69+
*
70+
* @param input
71+
* @return
72+
* @throws IOException
73+
* @throws NoSuchAlgorithmException
74+
*/
75+
private static String md5sum(InputStream input) throws IOException {
76+
BufferedInputStream in = new BufferedInputStream(input);
77+
78+
try {
79+
MessageDigest digest = java.security.MessageDigest
80+
.getInstance("MD5");
81+
DigestInputStream digestInputStream = new DigestInputStream(in,
82+
digest);
83+
for (; digestInputStream.read() >= 0;) {
84+
85+
}
86+
ByteArrayOutputStream md5out = new ByteArrayOutputStream();
87+
md5out.write(digest.digest());
88+
return md5out.toString();
89+
} catch (NoSuchAlgorithmException e) {
90+
throw new IllegalStateException("MD5 algorithm is not available: "
91+
+ e);
92+
} finally {
93+
in.close();
94+
}
95+
}
96+
97+
/**
98+
* Extract the specified library file to the target folder
99+
*
100+
* @param libFolderForCurrentOS
101+
* @param libraryFileName
102+
* @param targetFolder
103+
* @return
104+
*/
105+
private static boolean extractAndLoadLibraryFile(
106+
String libFolderForCurrentOS, String libraryFileName,
107+
String targetFolder) {
108+
String nativeLibraryFilePath = libFolderForCurrentOS + "/"
109+
+ libraryFileName;
110+
final String prefix = "javaaffinity-" + getVersion() + "-";
111+
112+
String extractedLibFileName = prefix + libraryFileName;
113+
File extractedLibFile = new File(targetFolder, extractedLibFileName);
114+
115+
try {
116+
if (extractedLibFile.exists()) {
117+
// test md5sum value
118+
String md5sum1 = md5sum(NativeAffinity.class
119+
.getResourceAsStream(nativeLibraryFilePath));
120+
String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
121+
122+
if (md5sum1.equals(md5sum2)) {
123+
return loadNativeLibrary(targetFolder, extractedLibFileName);
124+
} else {
125+
// remove old native library file
126+
boolean deletionSucceeded = extractedLibFile.delete();
127+
if (!deletionSucceeded) {
128+
throw new IOException(
129+
"failed to remove existing native library file: "
130+
+ extractedLibFile.getAbsolutePath());
131+
}
132+
}
133+
}
134+
135+
// extract file into the current directory
136+
InputStream reader = NativeAffinity.class
137+
.getResourceAsStream(nativeLibraryFilePath);
138+
FileOutputStream writer = new FileOutputStream(extractedLibFile);
139+
byte[] buffer = new byte[1024];
140+
int bytesRead = 0;
141+
while ((bytesRead = reader.read(buffer)) != -1) {
142+
writer.write(buffer, 0, bytesRead);
143+
}
144+
145+
writer.close();
146+
reader.close();
147+
148+
if (!System.getProperty("os.name").contains("Windows")) {
149+
try {
150+
Runtime.getRuntime()
151+
.exec(new String[] { "chmod", "755",
152+
extractedLibFile.getAbsolutePath() })
153+
.waitFor();
154+
} catch (Throwable e) {
155+
}
156+
}
157+
158+
} catch (IOException e) {
159+
// TODO something with exception - don't know what to do with it
160+
// using JUL
161+
if (LOGGER.isLoggable(Level.INFO)) {
162+
LOGGER.info("Unable to extract libaffinity in " + targetFolder);
163+
}
164+
return false;
165+
}
166+
return loadNativeLibrary(targetFolder, extractedLibFileName);
167+
168+
}
169+
170+
private static synchronized boolean loadNativeLibrary(String path,
171+
String name) {
172+
File libPath = new File(path, name);
173+
if (libPath.exists()) {
174+
175+
try {
176+
System.load(libPath.getAbsolutePath());
177+
return true;
178+
} catch (UnsatisfiedLinkError e) {
179+
// TODO something with e
180+
if (LOGGER.isLoggable(Level.INFO)) {
181+
LOGGER.info("Unable to find libaffinity in " + path);
182+
}
183+
return false;
184+
}
185+
} else {
186+
return false;
187+
}
188+
}
189+
190+
private static boolean loadAffinityNativeLibrary() {
191+
if (LOADED) {
192+
return LOADED;
193+
}
194+
String affinityNativeLibraryName = System.mapLibraryName("affinity");
195+
196+
// Load the os-dependent library from a jar file
197+
String affinityNativeLibraryPath = "/vanilla/java/affinity/native/"
198+
+ getNativeLibFolderPathForCurrentOS();
199+
200+
if (NativeAffinity.class.getResource(affinityNativeLibraryPath
201+
+ File.separator + affinityNativeLibraryName) == null) {
202+
return false;
203+
}
204+
205+
// temporary library folder
206+
String tempFolder = new File(System.getProperty("java.io.tmpdir"))
207+
.getAbsolutePath();
208+
// Try extracting the library from jar
209+
return extractAndLoadLibraryFile(affinityNativeLibraryPath,
210+
affinityNativeLibraryName, tempFolder);
211+
}
212+
213+
private static String getVersion() {
214+
215+
InputStream versionFile = NativeAffinity.class
216+
.getResourceAsStream("/META-INF/maven/vanilla.java/affinity/pom.properties");
217+
218+
String version = "unknown";
219+
try {
220+
if (versionFile != null) {
221+
Properties versionData = new Properties();
222+
versionData.load(versionFile);
223+
version = versionData.getProperty("version", version);
224+
version = version.trim().replaceAll("[^0-9\\.]", "");
225+
}
226+
} catch (IOException e) {
227+
if (LOGGER.isLoggable(Level.INFO)) {
228+
LOGGER.info("Unable to find libaffinity version from maven metadata");
229+
}
230+
}
231+
return version;
232+
}
233+
234+
private static String getNativeLibFolderPathForCurrentOS() {
235+
return getOSName() + "/" + getArchName();
236+
}
237+
238+
private static String getOSName() {
239+
return translateOSNameToFolderName(System.getProperty("os.name"));
240+
}
241+
242+
private static String getArchName() {
243+
return translateArchNameToFolderName(System.getProperty("os.arch"));
244+
}
245+
246+
private static String translateOSNameToFolderName(String osName) {
247+
if (osName.contains("Windows")) {
248+
return "Windows";
249+
} else if (osName.contains("Mac")) {
250+
return "Mac";
251+
} else if (osName.contains("Linux")) {
252+
return "Linux";
253+
} else {
254+
return osName.replaceAll("\\W", "");
255+
}
256+
}
257+
258+
private static String translateArchNameToFolderName(String archName) {
259+
return archName.replaceAll("\\W", "");
260+
}
261+
59262
}
Binary file not shown.

0 commit comments

Comments
 (0)