changeset 2753:2f33764996f8

Port native library plugin to Windows This patch adds Windows compatibility for the native library plugin code, and moves the Linux code to common-portability module. Reviewed-by: sgehwolf Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-September/024893.html
author Simon Tooke <stooke@redhat.com>
date Tue, 12 Sep 2017 08:41:11 -0400
parents 7d4b09df34d4
children 6018bc5f92b3
files common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcess.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/PosixHelperImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxNativeLibsExtractor.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/macos/MacOSProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableProcessImpl.java common/portability/src/main/native/WindowsHelperImpl.c common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxNativeLibsExtractorTest.java common/portability/src/test/resources/native_lib_empty common/portability/src/test/resources/native_lib_no_libs common/portability/src/test/resources/native_lib_three_libs plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmLinuxNativeLibsExtractor.java plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorFactory.java plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorImpl.java plugins/jvm-overview/agent/src/test/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmLinuxNativeLibsExtractorTest.java plugins/jvm-overview/agent/src/test/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorImplTest.java plugins/jvm-overview/agent/src/test/resources/native_lib_empty plugins/jvm-overview/agent/src/test/resources/native_lib_no_libs plugins/jvm-overview/agent/src/test/resources/native_lib_three_libs
diffstat 20 files changed, 412 insertions(+), 218 deletions(-) [+]
line wrap: on
line diff
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcess.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcess.java	Tue Sep 12 08:41:11 2017 -0400
@@ -61,4 +61,6 @@
     boolean terminateProcess(int pid, int exitcode, int waitMillis);
 
     int getCurrentProcessPid();
+
+    String[] getNativeLibs(int pid);
 }
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/PosixHelperImpl.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/PosixHelperImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.portability.internal;
 
-public class PosixHelperImpl {
+public class PosixHelperImpl extends PortableNativeLibraryLoader{
 
     public int getCurrentProcessPid() {
         return getCurrentProcessID0();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxNativeLibsExtractor.java	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.portability.internal.linux;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LinuxNativeLibsExtractor {
+
+    private static final Logger LOGGER
+            = LoggingUtils.getLogger(LinuxNativeLibsExtractor.class);
+
+    public static String[] getNativeLibs(int pid) {
+        return getNativeLibsFromReader(new File(String.format("/proc/%d/maps", pid)));
+    }
+
+    // for testing purposes only
+    static String[] getNativeLibs(File testFile) {
+        return getNativeLibsFromReader(testFile);
+    }
+
+    private static String[] getNativeLibsFromReader(File nativeLibFile) {
+        final String soGrep = ".+\\.so.*";
+        Set<String> result = new HashSet<>();
+        try (BufferedReader br
+                     = new BufferedReader(new FileReader(nativeLibFile))) {
+            String next = br.readLine();
+            while (next != null) {
+                next = next.trim();
+                if (next.matches(soGrep)) {
+                    String candidate = next.substring(next.lastIndexOf(' ') + 1);
+                    result.add(candidate);
+                }
+                next = br.readLine();
+            }
+            return result.toArray(new String[0]);
+        } catch (IOException ex) {
+            LOGGER.log(Level.WARNING, "Unable to retrieve native libraries.");
+            LOGGER.log(Level.INFO, ex.getMessage());
+            return new String[0];
+        }
+    }
+}
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessImpl.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -119,4 +119,9 @@
     public int getCurrentProcessPid() {
         return posixHelper.getCurrentProcessPid();
     }
+
+    @Override
+    public String[] getNativeLibs(int pid) {
+        return LinuxNativeLibsExtractor.getNativeLibs(pid);
+    }
 }
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/macos/MacOSProcessImpl.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/macos/MacOSProcessImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -41,6 +41,7 @@
 import com.redhat.thermostat.common.portability.PortableProcessStat;
 import com.redhat.thermostat.common.portability.PortableVmIoStat;
 import com.redhat.thermostat.common.portability.internal.PosixHelperImpl;
+import com.redhat.thermostat.common.portability.internal.UnimplementedError;
 
 import java.util.Map;
 
@@ -102,4 +103,9 @@
     public int getCurrentProcessPid() {
         return posixHelper.getCurrentProcessPid();
     }
+
+    @Override
+    public String[] getNativeLibs(int pid) {
+        throw new UnimplementedError("getNativeLibs() is unsupported on macOS");
+    }
 }
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImpl.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -45,7 +45,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-
 /**
  * Utility class to access Windows native code
  */
@@ -307,6 +306,15 @@
         return terminateProcess0(pid, exitcode, waitMillis);
     }
 
+    /**
+     * returns a list ofprocess modules.
+     * @param pid process id (input) if 0, use current process
+     * @return array of process moudles (DLLs and executable), module 0 is executable binary.  NULL if there was an error.
+     */
+    public String[] getProcessModules(int pid) {
+        return getModules0(pid);
+    }
+
     private static native String getHostName0(boolean prependDomain);
     private static native void getOSVersion0(long[] versionAndBuild);
     private static native boolean getGlobalMemoryStatus0(long[] info);
@@ -321,11 +329,15 @@
 
     private static native String getProcessSID0(int pid);
     private static native String getUserName0(int pid, boolean prependDomain);
-    private static native Object getEnvironment0(long hProcess, int mode); // mode = 0 returns DirectByteBuffer, 1 = String cwd, 2 = String execuatable, 3 = String command line
     private static native boolean getProcessInfo0(int pid, long[] info);
     private static native boolean getProcessIOInfo0(int pid, long[] info);
     private static native int exists0(int pid);
 
+    // mode = 0 returns DirectByteBuffer, 1 = String cwd, 2 = String executable, 3 = String command line
+    private static native Object getEnvironment0(long hProcess, int mode);
+
+    private static native String[] getModules0(int pid);
+
     private static native int getCurrentProcessID0();
     private static native long getCurrentProcessHandle0();
     private static native long getProcessHandle0(int pid);
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableProcessImpl.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableProcessImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -106,4 +106,9 @@
     public int getCurrentProcessPid() {
         return helper.getCurrentProcessPid();
     }
+
+    @Override
+    public String[] getNativeLibs(int pid) {
+        return helper.getProcessModules(pid);
+    }
 }
--- a/common/portability/src/main/native/WindowsHelperImpl.c	Mon Sep 11 15:58:32 2017 +0200
+++ b/common/portability/src/main/native/WindowsHelperImpl.c	Tue Sep 12 08:41:11 2017 -0400
@@ -1007,3 +1007,48 @@
     void *buffer = (*env)->GetDirectBufferAddress(env, bytebuffer);
     free(buffer);
 }
+
+/*
+ * Class:     com_redhat_thermostat_common_portability_internal_windows_WindowsHelperImpl
+ * Method:    getModules0
+ * Signature: (J)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_redhat_thermostat_common_portability_internal_windows_WindowsHelperImpl_getModules0
+  (JNIEnv *env, jclass klass, jint pid) {
+
+    // Get a handle to the process (current process if pid = 0)
+    HANDLE hProcess = (pid == 0) ? GetCurrentProcess() : OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
+    if (NULL == hProcess) {
+        return NULL;
+    }
+
+    jobjectArray ret = NULL;
+
+    // Get a list of all the modules in this process.
+    DWORD cbNeeded = 0;
+    if (EnumProcessModules(hProcess, NULL, 0, &cbNeeded)) {
+        HMODULE* hMods = malloc(cbNeeded);
+        DWORD retBytes = 0;
+        // potential chase here: the library list can change size between these two calls.
+        if (EnumProcessModules(hProcess, hMods, cbNeeded, &retBytes)) {
+            int nModules = (retBytes / sizeof(HMODULE));
+            ret = (jobjectArray) (*env)->NewObjectArray(env, nModules, (*env)->FindClass(env, "java/lang/String"), NULL);
+            for (int i = 0; i < nModules; i++) {
+                TCHAR szModName[MAX_PATH];
+                // Get the full path to the module's file.
+                int nchar = GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR));
+                if (nchar > 0) {
+                    // Print the module name and handle value.
+                    jstring s = (*env)->NewString(env, (const jchar *)szModName, (jsize)wcslen(szModName));
+                    s = (*env)->NewStringUTF(env, szModName);
+                    (*env)->SetObjectArrayElement(env, ret, i, s);
+                }
+            }
+        }
+        free(hMods);
+    }
+
+    // Release the handle to the process.
+    CloseHandle( hProcess );
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxNativeLibsExtractorTest.java	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.portability.internal.linux;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Test;
+
+public class LinuxNativeLibsExtractorTest {
+
+    private final File THREE_LIBS = getFileFromTestSources("native_lib_three_libs");
+    private final File NO_LIBS = getFileFromTestSources("native_lib_no_libs");
+    private final File EMPTY = getFileFromTestSources("native_lib_empty");
+
+    private File getFileFromTestSources(String path) {
+        path = '/' + path;
+        return new File(decodeFilePath(this.getClass().getResource(path)));
+    }
+
+    private String decodeFilePath(URL url) {
+        try {
+            return URLDecoder.decode(url.getFile(), "UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    @Test
+    public void threeLibs() {
+        HashSet<String> expectedLibs = new HashSet<>(Arrays.asList("/usr/foo/libhello.so",
+                "/usr/bar/libworld.so.0.18.0", "/tmp/libnew.so.so"));
+
+        // Cannot compare arrays directly since the implementation internally gathers libs
+        // to a Set, which might yield a different ordering of items in the collection in the end
+        assertEquals(expectedLibs, new HashSet<>(Arrays.asList(LinuxNativeLibsExtractor.getNativeLibs(THREE_LIBS))));
+    }
+
+    @Test
+    public void noLibs() {
+        String[] result = LinuxNativeLibsExtractor.getNativeLibs(NO_LIBS);
+        int numExpectedLibs = 0;
+
+        assertNotNull(result);
+        assertEquals(result.length, numExpectedLibs);
+
+    }
+
+    @Test
+    public void empty() {
+        String[] result = LinuxNativeLibsExtractor.getNativeLibs(EMPTY);
+        int numExpectedLibs = 0;
+
+        assertNotNull(result);
+        assertEquals(result.length, numExpectedLibs);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/resources/native_lib_empty	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/resources/native_lib_no_libs	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,3 @@
+000000000000-00000000f000 r-xp 00000000 fd:01 1234567                    /usr/foo/libhello
+00000000f000-000000050000 ---p 00085000 fd:02 1234567                    /usr/bar/libworld
+000000050000-000000e00000 r--p 00085000 fd:03 1234567                    /tmp/libnew
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/resources/native_lib_three_libs	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,4 @@
+000000000000-00000000f000 r-xp 00000000 fd:01 1234567                    /usr/foo/libhello.so
+00000000f000-000000050000 ---p 00085000 fd:02 1234567                    /usr/bar/libworld.so.0.18.0
+000000050000-000000e00000 r--p 00085000 fd:03 1234567                    /tmp/libnew.so.so
+
--- a/plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmLinuxNativeLibsExtractor.java	Mon Sep 11 15:58:32 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.jvm.overview.agent.internal.model;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-public class VmLinuxNativeLibsExtractor implements VmNativeLibsExtractor {
-
-    private static final Logger LOGGER
-            = LoggingUtils.getLogger(VmInfoDAOImpl.class);
-
-    private final Integer pid;
-
-    public VmLinuxNativeLibsExtractor(Integer pid) {
-        Objects.requireNonNull(pid);
-        this.pid = pid;
-    }
-
-    private String[] getNativeLibsFromReader(File nativeLibFile) {
-        final String soGrep = ".+\\.so.*";
-        Set<String> result = new HashSet<>();
-        try (BufferedReader br
-                = new BufferedReader(new FileReader(nativeLibFile))) {
-            String next = br.readLine();
-            while (next != null) {
-                next = next.trim();
-                if (next.matches(soGrep)) {
-                    String candidate = next.substring(next.lastIndexOf(' ') + 1);
-                    result.add(candidate);
-                }
-                next = br.readLine();
-            }
-            return result.toArray(new String[0]);
-        } catch (IOException ex) {
-            LOGGER.log(Level.WARNING, "Unable to retrieve native libraries.");
-            LOGGER.log(Level.INFO, ex.getMessage());
-            return new String[0];
-        }
-    }
-
-    @Override
-    public String[] getNativeLibs() {
-        return getNativeLibsFromReader(new File(String.format("/proc/%d/maps", pid)));
-    }
-
-    // for testing purposes only
-    String[] getNativeLibs(File testFile) {
-        return getNativeLibsFromReader(testFile);
-    }
-}
--- a/plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorFactory.java	Mon Sep 11 15:58:32 2017 +0200
+++ b/plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorFactory.java	Tue Sep 12 08:41:11 2017 -0400
@@ -41,10 +41,6 @@
 public final class VmNativeLibsExtractorFactory {
 
     public static VmNativeLibsExtractor getInstance(Integer pid) {
-        if (OS.IS_LINUX) {
-            return new VmLinuxNativeLibsExtractor(pid);
-        } else {
-            throw new UnsupportedOperationException("Extractor for the given OS not supported yet.");
-        }
+        return new VmNativeLibsExtractorImpl(pid);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jvm-overview/agent/src/main/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorImpl.java	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.jvm.overview.agent.internal.model;
+
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.common.portability.PortableProcessFactory;
+
+import java.util.Objects;
+
+public class VmNativeLibsExtractorImpl implements VmNativeLibsExtractor {
+
+    private final Integer pid;
+    private final PortableProcess helper = PortableProcessFactory.getInstance();
+
+    public VmNativeLibsExtractorImpl(Integer pid) {
+        Objects.requireNonNull(pid);
+        this.pid = pid;
+    }
+
+    @Override
+    public String[] getNativeLibs() {
+        return helper.getNativeLibs(pid);
+    }
+}
--- a/plugins/jvm-overview/agent/src/test/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmLinuxNativeLibsExtractorTest.java	Mon Sep 11 15:58:32 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.jvm.overview.agent.internal.model;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.Arrays;
-import java.util.HashSet;
-import org.junit.Before;
-import org.junit.Test;
-
-public class VmLinuxNativeLibsExtractorTest {
-
-    private VmLinuxNativeLibsExtractor extractor;
-
-    private static final Integer VM_PID = 0;
-
-    private final File THREE_LIBS = getFileFromTestSources("native_lib_three_libs");
-    private final File NO_LIBS = getFileFromTestSources("native_lib_no_libs");
-    private final File EMPTY = getFileFromTestSources("native_lib_empty");
-
-    private File getFileFromTestSources(String path) {
-        path = '/' + path;
-        return new File(decodeFilePath(this.getClass().getResource(path)));
-    }
-
-    private String decodeFilePath(URL url) {
-        try {
-            return URLDecoder.decode(url.getFile(), "UTF-8");
-        } catch (UnsupportedEncodingException ex) {
-            throw new AssertionError(ex);
-        }
-    }
-
-    @Before
-    public void setup() {
-        extractor = new VmLinuxNativeLibsExtractor(VM_PID);
-    }
-
-    @Test
-    public void threeLibs() {
-        HashSet<String> expectedLibs = new HashSet<>(Arrays.asList("/usr/foo/libhello.so",
-                "/usr/bar/libworld.so.0.18.0", "/tmp/libnew.so.so"));
-
-        // Cannot compare arrays directly since the implementation internally gathers libs
-        // to a Set, which might yield a different ordering of items in the collection in the end
-        assertEquals(expectedLibs, new HashSet<>(Arrays.asList(extractor.getNativeLibs(THREE_LIBS))));
-    }
-
-    @Test
-    public void noLibs() {
-        String[] result = extractor.getNativeLibs(NO_LIBS);
-        int numExpectedLibs = 0;
-
-        assertNotNull(result);
-        assertEquals(result.length, numExpectedLibs);
-
-    }
-
-    @Test
-    public void empty() {
-        String[] result = extractor.getNativeLibs(EMPTY);
-        int numExpectedLibs = 0;
-
-        assertNotNull(result);
-        assertEquals(result.length, numExpectedLibs);
-
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/jvm-overview/agent/src/test/java/com/redhat/thermostat/jvm/overview/agent/internal/model/VmNativeLibsExtractorImplTest.java	Tue Sep 12 08:41:11 2017 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.jvm.overview.agent.internal.model;
+
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.common.portability.PortableProcessFactory;
+import com.redhat.thermostat.shared.config.OS;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class VmNativeLibsExtractorImplTest {
+
+    private PortableProcess procHelper = PortableProcessFactory.getInstance();
+
+    @Before
+    public void setup() {
+        procHelper = PortableProcessFactory.getInstance();
+    }
+
+    @Test
+    public void currentProcessTest() {
+        final int pid = procHelper.getCurrentProcessPid();
+        VmNativeLibsExtractorImpl extractor = new VmNativeLibsExtractorImpl(pid);
+        checkLibs(extractor.getNativeLibs());
+    }
+
+    private void checkLibs(final String[] libArray) {
+        assertNotNull(libArray);
+        Set<String> libs = new HashSet<String>();
+        for (String s : libArray) {
+            File f = new File(s);
+            libs.add(f.getName().toLowerCase());
+        }
+        if (OS.IS_WINDOWS) {
+            assertTrue(libs.contains("jvm.dll"));
+        } else if (OS.IS_MACOS) {
+            assertTrue(libs.contains("libjvm.dylib"));
+        } else {
+            assertTrue(libs.contains("libjvm.so"));
+        }
+    }
+}
--- a/plugins/jvm-overview/agent/src/test/resources/native_lib_empty	Mon Sep 11 15:58:32 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/plugins/jvm-overview/agent/src/test/resources/native_lib_no_libs	Mon Sep 11 15:58:32 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-000000000000-00000000f000 r-xp 00000000 fd:01 1234567                    /usr/foo/libhello
-00000000f000-000000050000 ---p 00085000 fd:02 1234567                    /usr/bar/libworld
-000000050000-000000e00000 r--p 00085000 fd:03 1234567                    /tmp/libnew
--- a/plugins/jvm-overview/agent/src/test/resources/native_lib_three_libs	Mon Sep 11 15:58:32 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-000000000000-00000000f000 r-xp 00000000 fd:01 1234567                    /usr/foo/libhello.so
-00000000f000-000000050000 ---p 00085000 fd:02 1234567                    /usr/bar/libworld.so.0.18.0
-000000050000-000000e00000 r--p 00085000 fd:03 1234567                    /tmp/libnew.so.so
-