From 0d185e4de2ceba43b6f4d77ac620eac67afb6859 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 13 Mar 2016 16:08:21 +0100 Subject: [PATCH] Better extraction and use of UDT natives --- src/com/barchart/udt/SocketUDT.java | 153 +++++++++++++++--- .../linux_32/libbarchart-udt-core-2.3.2.so | Bin .../linux_64/libbarchart-udt-core-2.3.2.so | Bin .../libbarchart-udt-core-2.3.2.dylib | Bin .../libbarchart-udt-core-2.3.2.dylib | Bin .../windows_32/libbarchart-udt-core-2.3.2.dll | Bin .../windows_64/libbarchart-udt-core-2.3.2.dll | Bin 7 files changed, 132 insertions(+), 21 deletions(-) rename {natives => src/com/barchart/udt/natives}/linux_32/libbarchart-udt-core-2.3.2.so (100%) rename {natives => src/com/barchart/udt/natives}/linux_64/libbarchart-udt-core-2.3.2.so (100%) rename {natives => src/com/barchart/udt/natives}/macosx_32/libbarchart-udt-core-2.3.2.dylib (100%) rename {natives => src/com/barchart/udt/natives}/macosx_64/libbarchart-udt-core-2.3.2.dylib (100%) rename {natives => src/com/barchart/udt/natives}/windows_32/libbarchart-udt-core-2.3.2.dll (100%) rename {natives => src/com/barchart/udt/natives}/windows_64/libbarchart-udt-core-2.3.2.dll (100%) diff --git a/src/com/barchart/udt/SocketUDT.java b/src/com/barchart/udt/SocketUDT.java index 0e747117..83e5e8f3 100644 --- a/src/com/barchart/udt/SocketUDT.java +++ b/src/com/barchart/udt/SocketUDT.java @@ -17,13 +17,31 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; +import java.math.BigInteger; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URL; +import java.net.URLDecoder; import java.nio.ByteBuffer; import java.nio.IntBuffer; +import java.security.CodeSource; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.Enumeration; import java.util.List; +import java.util.Locale; import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * UDT native socket wrapper @@ -140,35 +158,129 @@ class SocketUDT { } // if we are natively deployed, we automatically load the native libraries as part of the startup procedure + // if we are not, we are either from a jar or as source if (!isNativeDeployed) { - final Logger logger = LoggerFactory.getLogger(SocketUDT.class); + ProtectionDomain pDomain = SocketUDT.class.getProtectionDomain(); + CodeSource cSource = pDomain.getCodeSource(); - String moduleDir = System.getProperty("user.dir"); - File libraryDir = FileUtil.normalize(new File(moduleDir, "natives")); - - - if (!libraryDir.isDirectory()) { - throw new IllegalStateException("Invalid library location '" + libraryDir.getAbsolutePath() + "'"); - } + // file:/X:/workspace/XYZ/classes/ when it's in ide/flat + // jar:/X:/workspace/XYZ/jarname.jar when it's jar + URL loc = cSource.getLocation(); + final String path = loc.getPath(); + final boolean isJar = path.endsWith(".jar"); + final OsType os = OS.get(); + String osName = os.getName(); boolean loaded = false; - try { - logger.info("Loading release libraries."); - final OsType os = OS.get(); + if (isJar) { + // have to extract our correct file to temp then load it, ONLY if we are not already loaded! - String osName = os.getName(); - File libPath = new File(libraryDir, osName).getAbsoluteFile(); - if (libPath.canRead()) { - List libs = FileUtil.parseDir(libPath, os.getLibraryNames()); - for (File lib : libs) { - System.load(lib.getAbsolutePath()); + try { + MessageDigest digest = MessageDigest.getInstance("MD5"); + digest.update(TypeUDT.class.getName() + .getBytes()); + + // convert to alpha-numeric. see https://stackoverflow.com/questions/29183818/why-use-tostring32-and-not-tostring36 + final String outputFileName = "UDT_driver_" + new BigInteger(1, digest.digest()).toString(32) + .toUpperCase(Locale.US); + + final String tempDir = System.getProperty("java.io.tmpdir"); + + final File file = new File(tempDir, outputFileName); + if (!file.canRead()) { + // we need to iterate this jar to get the files + + final String packageName = TypeUDT.class.getPackage() + .getName() + .replaceAll("\\.", "/"); + + final String prefix = packageName + "/natives/" + osName + "/"; + final List list = Arrays.asList(os.getLibraryNames()); + + final String jarFileName = URLDecoder.decode(loc.getPath(), "UTF-8"); + JarFile jar = new JarFile(jarFileName); + Enumeration entries = jar.entries(); + JAR_READ: + while (entries.hasMoreElements()) { + final JarEntry jarEntry = entries.nextElement(); + String name = jarEntry.getName(); + + if (name.startsWith(prefix)) { + for (String s : list) { + if (name.endsWith(s)) { + // there is only one! + + // now we copy it out + final InputStream inputStream = jar.getInputStream(jarEntry); + + OutputStream outStream = null; + try { + outStream = new FileOutputStream(file); + + byte[] buffer = new byte[2048]; + int read; + while ((read = inputStream.read(buffer)) > 0) { + outStream.write(buffer, 0, read); + } + } catch (IOException e) { + log.error("Error extracting library from: " + jarFileName, e.getMessage()); + } finally { + try { + inputStream.close(); + } catch (Exception ignored) { + } + try { + if (outStream != null) { + outStream.close(); + } + } catch (Exception ignored) { + } + } + break JAR_READ; + } + } + } + } + + jar.close(); } - logger.info("Release libraries loaded."); + + log.info("Loading release libraries."); + + System.load(file.getAbsolutePath()); + log.info("Release libraries loaded."); loaded = true; + } catch (NoSuchAlgorithmException e) { + log.error("Error loading MD5 checksum.", e.getMessage()); + } catch (UnsupportedEncodingException e) { + log.error("Error parsing text.", e.getMessage()); + } catch (IOException e) { + log.error("Error extracting library.", e.getMessage()); + } + } + else { + try { + log.info("Loading release libraries."); + + final URI uri = TypeUDT.class.getResource("natives/" + osName + "/") + .toURI(); + final String host = uri.getPath(); + + File libPath = new File(host).getAbsoluteFile(); + if (libPath.canRead()) { + List libs = FileUtil.parseDir(libPath, os.getLibraryNames()); + for (File lib : libs) { + // load the libs in that dir (there will be only one) + System.load(lib.getAbsolutePath()); + break; + } + log.info("Release libraries loaded."); + loaded = true; + } + } catch (final Throwable e) { + log.error("Release libraries missing: {}", e.getMessage()); } - } catch (final Throwable e) { - logger.error("Release libraries missing: {}", e.getMessage()); } if (!loaded) { @@ -911,7 +1023,6 @@ class SocketUDT { /** * @see #getOption0(int, Class) */ - @SuppressWarnings("unchecked") public T getOption(final OptionUDT option) throws ExceptionUDT { diff --git a/natives/linux_32/libbarchart-udt-core-2.3.2.so b/src/com/barchart/udt/natives/linux_32/libbarchart-udt-core-2.3.2.so similarity index 100% rename from natives/linux_32/libbarchart-udt-core-2.3.2.so rename to src/com/barchart/udt/natives/linux_32/libbarchart-udt-core-2.3.2.so diff --git a/natives/linux_64/libbarchart-udt-core-2.3.2.so b/src/com/barchart/udt/natives/linux_64/libbarchart-udt-core-2.3.2.so similarity index 100% rename from natives/linux_64/libbarchart-udt-core-2.3.2.so rename to src/com/barchart/udt/natives/linux_64/libbarchart-udt-core-2.3.2.so diff --git a/natives/macosx_32/libbarchart-udt-core-2.3.2.dylib b/src/com/barchart/udt/natives/macosx_32/libbarchart-udt-core-2.3.2.dylib similarity index 100% rename from natives/macosx_32/libbarchart-udt-core-2.3.2.dylib rename to src/com/barchart/udt/natives/macosx_32/libbarchart-udt-core-2.3.2.dylib diff --git a/natives/macosx_64/libbarchart-udt-core-2.3.2.dylib b/src/com/barchart/udt/natives/macosx_64/libbarchart-udt-core-2.3.2.dylib similarity index 100% rename from natives/macosx_64/libbarchart-udt-core-2.3.2.dylib rename to src/com/barchart/udt/natives/macosx_64/libbarchart-udt-core-2.3.2.dylib diff --git a/natives/windows_32/libbarchart-udt-core-2.3.2.dll b/src/com/barchart/udt/natives/windows_32/libbarchart-udt-core-2.3.2.dll similarity index 100% rename from natives/windows_32/libbarchart-udt-core-2.3.2.dll rename to src/com/barchart/udt/natives/windows_32/libbarchart-udt-core-2.3.2.dll diff --git a/natives/windows_64/libbarchart-udt-core-2.3.2.dll b/src/com/barchart/udt/natives/windows_64/libbarchart-udt-core-2.3.2.dll similarity index 100% rename from natives/windows_64/libbarchart-udt-core-2.3.2.dll rename to src/com/barchart/udt/natives/windows_64/libbarchart-udt-core-2.3.2.dll