changeset 2574:cd5b08c32052

[PATCH] refactoring portable code part 2 Move more of the Linux "/proc" code into the portability package. Change pom files to detect linux using os name rather than os family. Reviewed-by: ebaron, neugens Review Thread:http://icedtea.classpath.org/pipermail/thermostat/2017-January/022054.html
author Simon Tooke <stooke@redhat.com>
date Mon, 30 Jan 2017 10:30:19 -0500
parents 006ac47d1506
children 902e2e96f4e8
files agent/ipc/server/src/main/java/com/redhat/thermostat/agent/ipc/server/internal/IPCConfigurationWriter.java common/portability/pom.xml common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableHostImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableMemoryStat.java common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessStat.java common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableVmIoStat.java common/portability/src/main/java/com/redhat/thermostat/common/portability/SysConf.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformation.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformationSource.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/EtcOsRelease.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableHostImpl.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/linux/LinuxPortableProcessStatBuilderImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessEnvironmentBuilderImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LsbRelease.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/LinuxVmIoStatBuilderImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoData.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoDataReader.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHostImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableHostImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsProcessImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsUserInfoBuilderImpl.java common/portability/src/main/java/com/redhat/thermostat/common/portability/linux/ProcDataSource.java common/portability/src/test/java/com/redhat/thermostat/common/portability/ProcessCheckerTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformationTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/EtcOsReleaseTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableHostImplTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessStatBuilderImplTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessEnvironmentBuilderImplTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LsbReleaseTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/TestLogHandler.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/vmio/LinuxVmIoStatBuilderTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoDataReaderTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImplTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsProcessUserInfoBuilderTest.java common/portability/src/test/java/com/redhat/thermostat/common/portability/linux/ProcDataSourceTest.java distribution/windows/scripts/thermostat-ipc-client-common.cmd host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java host-memory/agent/src/main/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatBuilder.java keyring/pom.xml keyring/src/main/java/com/redhat/thermostat/utils/keyring/internal/Activator.java laf-utils/pom.xml numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/Activator.java numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/NumaCollectorImpl.java numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/NumaWindowsCollectorImpl.java pom.xml process-handler/src/main/java/com/redhat/thermostat/service/internal/windows/WindowsProcessUtilities.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilderImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/InfoBuilderFactoryImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilderImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformation.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformationSource.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/EtcOsRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/HostInfoBuilderImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/LinuxInfoBuilderFactory.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/LsbRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/ProcessEnvironmentBuilderImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/models/InfoBuilderFactory.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsHostInfoBuilderImpl.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsInfoBuilderFactory.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsProcessEnvironmentBuilderImpl.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/InfoBuilderFactoryTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformationTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/EtcOsReleaseTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/HostInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/LsbReleaseTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/ProcessEnvironmentBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/TestLogHandler.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsHostInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsInfoBuilderFactoryTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsProcessEnvironmentBuilderTest.java vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/LinuxProcessStatusInfoBuilderImpl.java vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/ProcessStatusInfoBuilderImpl.java vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuBackend.java vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/WindowsProcessStatusInfoBuilderImpl.java vm-cpu/agent/src/test/java/com/redhat/thermostat/vm/cpu/agent/internal/LinuxProcessStatusInfoBuilderTest.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/LinuxVmIoStatBuilder.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoData.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoDataReader.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackend.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/VmIoStatBuilderImpl.java vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/WindowsVmIoStatBuilder.java vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/LinuxVmIoStatBuilderTest.java vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoDataReaderTest.java vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackendTest.java vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/VmIoStatBuilderTest.java vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/WindowsVmIoStatBuilderTest.java
diffstat 92 files changed, 3253 insertions(+), 3317 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ipc/server/src/main/java/com/redhat/thermostat/agent/ipc/server/internal/IPCConfigurationWriter.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/agent/ipc/server/src/main/java/com/redhat/thermostat/agent/ipc/server/internal/IPCConfigurationWriter.java	Mon Jan 30 10:30:19 2017 -0500
@@ -111,7 +111,7 @@
             // note: this is required for UNIX too
             if (OS.IS_WINDOWS) {
                 int uport = aport == 0 ? 0 : findUnusedTCPSocket( aport + 1, TEST_SOCKET_HIGH);
-                int uid = PortableProcessImpl.INSTANCE.getUid(0); // if pid=0, gets uid of current process
+                int uid = PortableProcessImpl.getInstance().getUid(0); // if pid=0, gets uid of current process
                 props.setProperty("agent-proxy-" + uid + PROP_TCP_SOCKET_SUFFIX, Integer.toString(uport));
             }
         }
--- a/common/portability/pom.xml	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/pom.xml	Mon Jan 30 10:30:19 2017 -0500
@@ -139,6 +139,7 @@
                         <Private-Package>
                             com.redhat.thermostat.common.portability.internal,
                             com.redhat.thermostat.common.portability.internal.linux,
+                            com.redhat.thermostat.common.portability.internal.linux.vmio,
                             com.redhat.thermostat.common.portability.internal.windows
                         </Private-Package>
                         <!-- Do not autogenerate uses clauses in Manifests -->
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableHostImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableHostImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -36,11 +36,21 @@
 
 package com.redhat.thermostat.common.portability;
 
-import com.redhat.thermostat.common.portability.internal.windows.WindowsHostImpl;
+import com.redhat.thermostat.common.portability.internal.linux.LinuxPortableHostImpl;
+import com.redhat.thermostat.common.portability.internal.windows.WindowsPortableHostImpl;
 import com.redhat.thermostat.shared.config.OS;
 
 public class PortableHostImpl {
 
-    public static final PortableHost INSTANCE = OS.IS_WINDOWS ? WindowsHostImpl.INSTANCE : null;
+    private static final PortableHost INSTANCE = createInstance();
+
+    private static PortableHost createInstance() {
+        return OS.IS_LINUX ? LinuxPortableHostImpl.createInstance()
+                : OS.IS_WINDOWS ? WindowsPortableHostImpl.createInstance()  : null;
+    }
+
+    public static PortableHost getInstance() {
+        return INSTANCE;
+    }
 }
 
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableMemoryStat.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableMemoryStat.java	Mon Jan 30 10:30:19 2017 -0500
@@ -84,6 +84,6 @@
     }
 
     public static PortableMemoryStat build() {
-        return PortableHostImpl.INSTANCE.getMemoryStat();
+        return PortableHostImpl.getInstance().getMemoryStat();
     }
 }
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -36,11 +36,20 @@
 
 package com.redhat.thermostat.common.portability;
 
-import com.redhat.thermostat.common.portability.internal.linux.LinuxProcessImpl;
-import com.redhat.thermostat.common.portability.internal.windows.WindowsHelperImpl;
-import com.redhat.thermostat.common.portability.internal.windows.WindowsProcessImpl;
+import com.redhat.thermostat.common.portability.internal.linux.LinuxPortableProcessImpl;
+import com.redhat.thermostat.common.portability.internal.windows.WindowsPortableProcessImpl;
 import com.redhat.thermostat.shared.config.OS;
 
 public final class PortableProcessImpl {
-    public static final PortableProcess INSTANCE = OS.IS_WINDOWS ? WindowsProcessImpl.INSTANCE : LinuxProcessImpl.INSTANCE;
+
+    private static final PortableProcess INSTANCE = createInstance();
+
+    private static PortableProcess createInstance() {
+        return OS.IS_LINUX ? LinuxPortableProcessImpl.createInstance()
+            : OS.IS_WINDOWS ? WindowsPortableProcessImpl.createInstance() : null;
+    }
+
+    public static PortableProcess getInstance() {
+        return INSTANCE;
+    }
 }
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessStat.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableProcessStat.java	Mon Jan 30 10:30:19 2017 -0500
@@ -71,7 +71,7 @@
     }
 
     public static PortableProcessStat build(int pid) {
-        return PortableProcessImpl.INSTANCE.getProcessStat(pid);
+        return PortableProcessImpl.getInstance().getProcessStat(pid);
     }
 }
 
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableVmIoStat.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/PortableVmIoStat.java	Mon Jan 30 10:30:19 2017 -0500
@@ -56,7 +56,7 @@
     }
 
     public static PortableVmIoStat build(Clock clock, int pid) {
-        return PortableProcessImpl.INSTANCE.getVmIoStat(clock, pid);
+        return PortableProcessImpl.getInstance().getVmIoStat(clock, pid);
     }
 
     public long getTimeStamp() {
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/SysConf.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/SysConf.java	Mon Jan 30 10:30:19 2017 -0500
@@ -58,7 +58,7 @@
     }
 
     private static long getWindowsClockTicksPerSecond() {
-        return PortableHostImpl.INSTANCE.getClockTicksPerSecond();
+        return PortableHostImpl.getInstance().getClockTicksPerSecond();
     }
 
     public static long getLinuxClockTicksPerSecond() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformation.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,107 @@
+/*
+ * 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 java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class DistributionInformation {
+
+    static final String UNKNOWN_NAME = "Unknown Distribution";
+    static final String UNKNOWN_VERSION = "Unknown Version";
+
+    private static final Logger logger = LoggingUtils.getLogger(DistributionInformation.class);
+
+    private final String name;
+    private final String version;
+
+    public DistributionInformation(String name, String version) {
+        this.name = name;
+        this.version = version;
+    }
+
+    public static DistributionInformation get() {
+        EtcOsRelease etcOsRelease = new EtcOsRelease();
+        LsbRelease lsbRelease = new LsbRelease();
+        return get(etcOsRelease, lsbRelease);
+    }
+    
+    // package-private for testing
+    static DistributionInformation get(EtcOsRelease etcOsRelease, LsbRelease lsbRelease) {
+        try {
+            DistributionInformation etcOsDistroInfo = etcOsRelease.getDistributionInformation();
+            // if both name and version are unknown defer to lsb fallback
+            if (!DistributionInformation.UNKNOWN_NAME.equals(etcOsDistroInfo.getName()) &&
+                !DistributionInformation.UNKNOWN_VERSION.equals(etcOsDistroInfo.getVersion())) {
+                return etcOsDistroInfo;
+            }
+            logger.log(Level.FINE, "/etc/os-release existing, but does not contain useful info");
+        } catch (IOException e) {
+            // Log only at level FINE, since we have the LSB fallback
+            logger.log(Level.FINE, "unable to use os-release", e);
+        }
+        try {
+            return lsbRelease.getDistributionInformation();
+        } catch (IOException e) {
+            // Log exception at level FINE only.
+            logger.log(Level.FINE, "unable to use lsb_release", e);
+            logger.log(Level.WARNING, "unable to use os-release AND lsb_release");
+        }
+        return new DistributionInformation(UNKNOWN_NAME, UNKNOWN_VERSION);
+    }
+
+    /**
+     * @return the name of the distribution, or {@link #UNKNOWN_NAME} if it can not be
+     * identified
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the release of the distribution or {@link #UNKNOWN_VERSION} if it can not be
+     * identified
+     */
+    public String getVersion() {
+        return version;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformationSource.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,46 @@
+/*
+ * 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 java.io.IOException;
+
+public interface DistributionInformationSource {
+
+    DistributionInformation getDistributionInformation() throws IOException;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/EtcOsRelease.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,112 @@
+/*
+ * 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 java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+public class EtcOsRelease implements DistributionInformationSource {
+
+    private static final String EMPTY_STRING = "";
+    private static final String OS_RELEASE = "/etc/os-release";
+    private final String osReleaseFile;
+    
+    EtcOsRelease() {
+        this.osReleaseFile = OS_RELEASE;
+    }
+    
+    // package-private for testing
+    EtcOsRelease(String osReleaseFile) {
+        this.osReleaseFile = osReleaseFile;
+    }
+    
+    @Override
+    public DistributionInformation getDistributionInformation() throws IOException {
+        return getFromOsRelease();
+    }
+
+    DistributionInformation getFromOsRelease() throws IOException {
+        return getFromOsRelease(osReleaseFile);
+    }
+
+    DistributionInformation getFromOsRelease(String releaseFile) throws IOException {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(releaseFile), StandardCharsets.UTF_8))) {
+            return getFromOsRelease(reader);
+        }
+    }
+
+    DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException {
+        String version = DistributionInformation.UNKNOWN_VERSION;
+        String name = DistributionInformation.UNKNOWN_NAME;
+        String line = null;
+        while ((line = reader.readLine()) != null) {
+            // skip whitespace only lines
+            line = line.trim();
+            if (line.equals(EMPTY_STRING)) {
+                continue;
+            }
+            if (line.matches("^NAME *=.*")) {
+                name = readShellVariable(line);
+            }
+            if (line.matches("^VERSION *=.*")) {
+                version = readShellVariable(line);
+            }
+        }
+        return new DistributionInformation(name, version);
+    }
+
+    /** Reads and parses a shell variable declaration: {@code FOO="bar"}
+     *
+     * @return the value of the shell variable
+     */
+    private String readShellVariable(String line) {
+        // TODO we should try to handle shell quotes better
+        String result = line.substring(line.indexOf("=")+1);
+        result = result.trim();
+        if (result.startsWith("\"") && result.endsWith("\"")) {
+            result = result.substring(1, result.length()-1);
+            result = result.trim();
+        }
+        return result;
+    }
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableHostImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,217 @@
+/*
+ * 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.Size;
+import com.redhat.thermostat.common.Size.Unit;
+import com.redhat.thermostat.common.portability.HostName;
+import com.redhat.thermostat.common.portability.PortableHost;
+import com.redhat.thermostat.common.portability.PortableMemoryStat;
+import com.redhat.thermostat.common.portability.internal.UnimplementedError;
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class LinuxPortableHostImpl implements PortableHost {
+
+    public static PortableHost INSTANCE = new LinuxPortableHostImpl(new ProcDataSource());
+
+    private static final Logger logger = LoggingUtils.getLogger(LinuxPortableHostImpl.class);
+
+    private static final String FALLBACK_LOCAL_HOSTNAME = "localhost";
+
+    private final ProcDataSource dataSource;
+
+    public static PortableHost createInstance() {
+        return new LinuxPortableHostImpl(new ProcDataSource());
+    }
+
+    static class HostCpuInfo {
+        final String model;
+        final int count;
+
+        HostCpuInfo(String model, int count) {
+            this.count = count;
+            this.model = model;
+        }
+    }
+
+    static class HostOsInfo {
+        final String kernel;
+        final String distribution;
+
+        HostOsInfo(String kernel, String distribution) {
+            this.kernel = kernel;
+            this.distribution = distribution;
+        }
+    }
+
+
+    LinuxPortableHostImpl(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    HostCpuInfo getCpuInfo() {
+        final String KEY_PROCESSOR_ID = "processor";
+        final String KEY_CPU_MODEL = "model name";
+        int cpuCount = 0;
+        String cpuModel = null;
+        try (BufferedReader bufferedReader = new BufferedReader(dataSource.getCpuInfoReader())) {
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                if (line.startsWith(KEY_PROCESSOR_ID)) {
+                    cpuCount++;
+                } else if (line.startsWith(KEY_CPU_MODEL)) {
+                    cpuModel = line.substring(line.indexOf(":") + 1).trim();
+                }
+            }
+        } catch (IOException ioe) {
+            logger.log(Level.WARNING, "unable to read cpu info");
+        }
+
+        logger.log(Level.FINEST, "cpuModel: " + cpuModel);
+        logger.log(Level.FINEST, "cpuCount: " + cpuCount);
+
+        return new HostCpuInfo(cpuModel, cpuCount);
+    }
+
+    Size getTotalMemorySize() {
+        Size totalMemory = null;
+        try (BufferedReader bufferedReader = new BufferedReader(dataSource.getMemInfoReader())) {
+            String[] memTotalParts = bufferedReader.readLine().split(" +");
+            long data = Long.valueOf(memTotalParts[1]);
+            String units = memTotalParts[2];
+            if (units.equals("kB")) {
+                totalMemory = new Size(data, Size.Unit.KiB);
+            }
+        } catch (IOException ioe) {
+            logger.log(Level.WARNING, "unable to read memory info");
+        }
+
+        logger.log(Level.FINEST, "totalMemory: " + (totalMemory != null ? totalMemory.toString() : "(null)"));
+        return totalMemory;
+    }
+
+    @Override
+    public String getHostName() {
+        String hostname = null;
+        
+        try {
+            InetAddress localAddress = InetAddress.getLocalHost();
+            hostname = getHostName(localAddress);
+        } catch (UnknownHostException uhe) {
+            logger.log(Level.WARNING, "unable to get hostname", uhe);
+        }
+        
+        // if fails, try to get hostname without dns lookup
+        if (hostname == null) {
+            hostname = HostName.getLocalHostName();
+        }
+        
+        // still null, use localhost
+        if (hostname == null) {
+            hostname = FALLBACK_LOCAL_HOSTNAME;
+
+        }
+        
+        return hostname;
+    }
+
+    HostOsInfo getOsInfo(DistributionInformation distroInfo) {
+        String osName = distroInfo.getName() + " " + distroInfo.getVersion();
+        logger.log(Level.FINEST, "osName: " + osName);
+        String osKernel = System.getProperty("os.name") + " " + System.getProperty("os.version");
+        logger.log(Level.FINEST, "osKernel: " + osKernel);
+        return new HostOsInfo(osKernel, osName);
+    }
+
+    private HostOsInfo getOsInfo() {
+        DistributionInformation distroInfo = DistributionInformation.get();
+        return  getOsInfo(distroInfo);
+    }
+
+    @Override
+    public String getOSName() {
+        return getOsInfo().distribution;
+    }
+
+    @Override
+    public String getOSVersion() {
+        return getOsInfo().kernel;
+    }
+
+    @Override
+    public String getCPUModel() {
+        return getCpuInfo().model;
+    }
+
+    @Override
+    public int getCPUCount() {
+        return getCpuInfo().count;
+    }
+
+    @Override
+    public long getTotalMemory() {
+        return (long) getTotalMemorySize().convertTo(Unit.B).getValue();
+    }
+
+    @Override
+    public long getClockTicksPerSecond() {
+        // TODO
+        throw new UnimplementedError("getClockTicksPerSecond()");
+    }
+
+    @Override
+    public PortableMemoryStat getMemoryStat() {
+        // TODO
+        throw new UnimplementedError("getMemoryStat()");
+    }
+
+    String getHostName(InetAddress localAddress) {
+        String hostname = localAddress.getCanonicalHostName();
+        logger.log(Level.FINEST, "hostname: " + hostname);
+        return hostname;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,114 @@
+/*
+ * 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.Clock;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.common.portability.PortableProcessStat;
+import com.redhat.thermostat.common.portability.PortableVmIoStat;
+import com.redhat.thermostat.common.portability.ProcessChecker;
+import com.redhat.thermostat.common.portability.internal.UnimplementedError;
+import com.redhat.thermostat.common.portability.internal.linux.vmio.LinuxVmIoStatBuilderImpl;
+import com.redhat.thermostat.common.portability.internal.linux.vmio.ProcIoDataReader;
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+
+import java.util.Map;
+
+public class LinuxPortableProcessImpl implements PortableProcess {
+
+    private LinuxPortableProcessStatBuilderImpl procStatHelper;
+    private LinuxProcessEnvironmentBuilderImpl procEnvHelper;
+    private LinuxVmIoStatBuilderImpl vmioHelper;
+
+    public static LinuxPortableProcessImpl INSTANCE = new LinuxPortableProcessImpl(new SystemClock(), new ProcDataSource());
+
+    public static PortableProcess createInstance() {
+        return new LinuxPortableProcessImpl(new SystemClock(), new ProcDataSource());
+    }
+
+    private LinuxPortableProcessImpl(Clock clock, ProcDataSource dataSource) {
+        procStatHelper = new LinuxPortableProcessStatBuilderImpl(dataSource);
+        procEnvHelper = new LinuxProcessEnvironmentBuilderImpl(dataSource);
+        vmioHelper = new LinuxVmIoStatBuilderImpl(clock, new ProcIoDataReader(dataSource));
+    }
+
+    @Override
+    public boolean exists(int pid) {
+        return new ProcessChecker().exists(pid);
+    }
+
+    @Override
+    public String getUserName(int pid) {
+        throw new UnimplementedError("getUserName()");
+    }
+
+    @Override
+    public int getUid(int pid) {
+        throw new UnimplementedError("getUid()");
+    }
+
+    @Override
+    public Map<String, String> getEnvironment(int pid) {
+        return procEnvHelper.build(pid);
+    }
+
+    @Override
+    public PortableProcessStat getProcessStat(int pid) {
+        return procStatHelper.build(pid);
+    }
+
+    @Override
+    public PortableVmIoStat getVmIoStat(Clock clock, int pid) {
+        return vmioHelper.build(pid);
+    }
+
+    @Override
+    public boolean terminateProcess(int pid) {
+        throw new UnimplementedError("terminateProcess()");
+    }
+
+    @Override
+    public boolean terminateProcess(int pid, boolean wait) {
+        throw new UnimplementedError("terminateProcess()");
+    }
+
+    @Override
+    public boolean terminateProcess(int pid, int exitcode, int waitMillis) {
+        throw new UnimplementedError("terminateProcess()");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessStatBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,121 @@
+/*
+ * 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.portability.PortableProcessStat;
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Extract status information about the process from /proc/. This is what tools
+ * like {@code ps} and {@code top} use.
+ *
+ * @see {@code proc(5)}
+ */
+public class LinuxPortableProcessStatBuilderImpl {
+
+    private static final Logger logger = LoggingUtils.getLogger(LinuxPortableProcessStatBuilderImpl.class);
+
+    private final ProcDataSource dataSource;
+
+    public LinuxPortableProcessStatBuilderImpl(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public PortableProcessStat build(int pid) {
+        try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) {
+            return build(reader);
+        } catch (IOException e) {
+            logger.log(Level.FINE, "Unable to read stat info for: " + pid);
+        }
+
+        return null;
+    }
+
+    PortableProcessStat build(Reader r) throws IOException {
+
+        int pid = -1;
+        long utime = -1;
+        long stime = -1;
+
+        Scanner scanner = null;
+
+        /* TODO map these (effectively c) data types to java types more sanely */
+
+        try (BufferedReader reader = new BufferedReader(r)) {
+            String statusLine = reader.readLine();
+
+            /* be prepared for process names like '1 ) 2 3 4 foo 5' */
+
+            scanner = new Scanner(statusLine);
+            pid = scanner.nextInt();
+            scanner.close();
+
+            int execEndNamePos = statusLine.lastIndexOf(')');
+
+            String cleanStatusLine = statusLine.substring(execEndNamePos + 1);
+
+            scanner = new Scanner(cleanStatusLine);
+            /* state = */scanner.next();
+            /* ppid = */scanner.nextInt();
+            /* pgrp = */scanner.nextInt();
+            /* session = */scanner.nextInt();
+            /* tty_nr = */scanner.nextInt();
+            /* tpgid = */scanner.nextInt();
+            /* flags = */scanner.nextInt();
+            /* minflt = */scanner.nextLong();
+            /* cminflt = */scanner.nextLong();
+            /* majflt = */scanner.nextLong();
+            /* cmajflt = */scanner.nextLong();
+            utime = scanner.nextLong();
+            stime = scanner.nextLong();
+            scanner.close();
+        }
+
+        return new PortableProcessStat(pid, utime, stime);
+
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessEnvironmentBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,126 @@
+/*
+ * 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 java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+class LinuxProcessEnvironmentBuilderImpl {
+
+    private static final Logger logger = LoggingUtils.getLogger(LinuxProcessEnvironmentBuilderImpl.class);
+
+    private final ProcDataSource dataSource;
+
+    LinuxProcessEnvironmentBuilderImpl(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public Map<String, String> build(int pid) {
+        try (Reader reader = dataSource.getEnvironReader(pid)) {
+            return build(reader);
+        } catch (IOException ioe) {
+            logger.log(Level.WARNING, "error reading env", ioe);
+        }
+
+        return Collections.emptyMap();
+    }
+
+    private Map<String,String> build(Reader reader) throws IOException {
+
+        Map<String, String> env = new HashMap<String, String>();
+
+        char[] fileBuffer = new char[1024];
+        int fileBufferIndex = 0;
+        char[] buffer = new char[1024];
+        int read = 0;
+        while (true) {
+            read = reader.read(buffer);
+            if (read == -1) {
+                break;
+            }
+
+            if (read + fileBufferIndex > fileBuffer.length) {
+                char[] newFileBuffer = new char[fileBuffer.length * 2];
+                System.arraycopy(fileBuffer, 0, newFileBuffer, 0, fileBufferIndex);
+                fileBuffer = newFileBuffer;
+            }
+            System.arraycopy(buffer, 0, fileBuffer, fileBufferIndex, read);
+            fileBufferIndex = fileBufferIndex + read;
+
+        }
+        List<String> parts = getParts(fileBuffer, fileBufferIndex);
+        for (String part : parts) {
+            int splitterPos = part.indexOf("=");
+            String key = part.substring(0, splitterPos);
+            String value = part.substring(splitterPos + 1);
+            env.put(key, value);
+        }
+
+        return env;
+    }
+
+    /**
+     * Split a char array, where items are separated by a null into into a list
+     * of strings
+     */
+    private List<String> getParts(char[] nullSeparatedBuffer, int bufferLength) {
+        int maxLength = Math.min(nullSeparatedBuffer.length, bufferLength);
+        List<String> parts = new ArrayList<String>();
+
+        int lastStart = 0;
+        for (int i = 0; i < maxLength; i++) {
+            if (nullSeparatedBuffer[i] == '\0') {
+                String string = new String(nullSeparatedBuffer, lastStart, (i - lastStart));
+                parts.add(string);
+                lastStart = i + 1;
+            }
+        }
+        return parts;
+    }
+
+}
+
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +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.common.portability.internal.linux;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.portability.*;
-import com.redhat.thermostat.common.portability.internal.UnimplementedError;
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-
-import java.util.Map;
-
-public class LinuxProcessImpl implements PortableProcess {
-
-    private final ProcDataSource dataSource;
-
-    public static LinuxProcessImpl INSTANCE = new LinuxProcessImpl(new ProcDataSource());
-
-    LinuxProcessImpl(ProcDataSource ds) {
-        this.dataSource = ds;
-    }
-
-    @Override
-    public boolean exists(int pid) {
-        return new ProcessChecker().exists(pid);
-    }
-
-    @Override
-    public String getUserName(int pid) {
-        throw new UnimplementedError("getUserName()");
-    }
-
-    @Override
-    public int getUid(int pid) {
-        throw new UnimplementedError("getUid()");
-    }
-
-    @Override
-    public Map<String, String> getEnvironment(int pid) {
-        throw new UnimplementedError("getEnvironment()");
-    }
-
-    @Override
-    public PortableProcessStat getProcessStat(int pid) {
-        throw new UnimplementedError("PortableProcessStat()");
-    }
-
-    @Override
-    public PortableVmIoStat getVmIoStat(Clock clock, int pid) {
-        throw new UnimplementedError("getVmIoStat()");
-    }
-
-    @Override
-    public boolean terminateProcess(int pid) {
-        throw new UnimplementedError("terminateProcess()");
-    }
-
-    @Override
-    public boolean terminateProcess(int pid, boolean wait) {
-        throw new UnimplementedError("terminateProcess()");
-    }
-
-    @Override
-    public boolean terminateProcess(int pid, int exitcode, int waitMillis) {
-        throw new UnimplementedError("terminateProcess()");
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/LsbRelease.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,123 @@
+/*
+ * 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+class LsbRelease implements DistributionInformationSource {
+
+    private static final Logger logger = LoggingUtils.getLogger(LsbRelease.class);
+
+    private static final String DISTRIBUTION_NAME = "distributor id";
+    private static final String DISTRIBUTION_VERSION = "release";
+    private static final String LSB_RELEASE_SCRIPT = "lsb_release";
+    
+    private final String lsbRelaseBin;
+    
+    LsbRelease() {
+        this.lsbRelaseBin = LSB_RELEASE_SCRIPT;
+    }
+    
+    // package-private for testing
+    LsbRelease(String lsbReleaseBin) {
+        this.lsbRelaseBin = lsbReleaseBin;
+    }
+
+    @Override
+    public DistributionInformation getDistributionInformation()
+            throws IOException {
+        return getFromLsbRelease();
+    }
+
+    private DistributionInformation getFromLsbRelease() throws IOException {
+        BufferedReader reader = null;
+        try {
+            Process lsbProc = Runtime.getRuntime().exec(new String[] { lsbRelaseBin, "-a" });
+            InputStream progOutput = lsbProc.getInputStream();
+            reader = new BufferedReader(new InputStreamReader(progOutput));
+            DistributionInformation result = getFromLsbRelease(reader);
+            int exitValue = lsbProc.waitFor();
+            if (exitValue != 0) {
+                logger.log(Level.WARNING, "unable to identify distribution, problems running 'lsb_release'");
+            }
+            return result;
+        } catch (InterruptedException e) {
+            throw new IOException(e);
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    logger.log(Level.WARNING, "unable to close a child's output stream");
+                }
+            }
+        }
+
+    }
+
+    DistributionInformation getFromLsbRelease(BufferedReader reader) throws IOException {
+        String name = DistributionInformation.UNKNOWN_NAME;
+        String version = DistributionInformation.UNKNOWN_VERSION;
+
+        String line;
+        while ((line = reader.readLine()) != null) {
+            int sepLocation = line.indexOf(":");
+            if (sepLocation != -1) {
+                String key = line.substring(0, sepLocation).toLowerCase();
+                if (key.equals(DISTRIBUTION_NAME)) {
+                    name = line.substring(sepLocation + 1).trim();
+                } else if (key.equals(DISTRIBUTION_VERSION)) {
+                    version = line.substring(sepLocation + 1).trim();
+                }
+            }
+        }
+
+        logger.log(Level.FINE, "distro-name: " + name);
+        logger.log(Level.FINE, "distro-version: " + version);
+
+        return new DistributionInformation(name, version);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/LinuxVmIoStatBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,61 @@
+/*
+ * 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.vmio;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.portability.PortableVmIoStat;
+
+public class LinuxVmIoStatBuilderImpl {
+
+    private final Clock clock;
+    private final ProcIoDataReader ioReader;
+
+    public LinuxVmIoStatBuilderImpl(Clock clock, ProcIoDataReader ioReader) {
+        this.clock = clock;
+        this.ioReader = ioReader;
+    }
+
+    public synchronized PortableVmIoStat build(Integer pid) {
+        ProcIoData data = ioReader.read(pid);
+        if (data == null) {
+            return null;
+        }
+        long miliTime = clock.getRealTimeMillis();
+        return new PortableVmIoStat(miliTime, data.syscr, data.syscw, data.rchar, data.wchar);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoData.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,66 @@
+/*
+ * 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.vmio;
+
+public class ProcIoData {
+
+    // This matches the proc file format. The file format is described at:
+    // http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt
+
+    public final long rchar;
+    public final long wchar;
+    public final long syscr;
+    public final long syscw;
+    public final long read_bytes;
+    public final long write_bytes;
+    public final long cancelled_write_bytes;
+
+    public ProcIoData(long rchar, long wchar,
+            long syscr, long syscw,
+            long read_bytes, long write_bytes,
+            long cancelled_write_bytes) {
+        this.rchar = rchar;
+        this.wchar = wchar;
+        this.syscr = syscr;
+        this.syscw = syscw;
+        this.read_bytes = read_bytes;
+        this.write_bytes = write_bytes;
+        this.cancelled_write_bytes = cancelled_write_bytes;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoDataReader.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,117 @@
+/*
+ * 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.vmio;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * Extract information from {@code /proc/<pid>/io}.
+ */
+public class ProcIoDataReader {
+
+    private static final Logger logger = LoggingUtils.getLogger(ProcIoDataReader.class);
+
+    private final ProcDataSource dataSource;
+
+    public ProcIoDataReader(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public ProcIoData read(int pid) {
+        try (BufferedReader reader = new BufferedReader(dataSource.getIoReader(pid))) {
+            return read(reader);
+        } catch (IOException e) {
+            logger.log(Level.FINE, "Unable to read io info for: " + pid);
+        }
+
+        return null;
+    }
+
+    private ProcIoData read(BufferedReader r) throws IOException {
+        // The file format is described at:
+        // http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt
+
+        final int UNKNOWN_VALUE = -1;
+        long rchar = UNKNOWN_VALUE;
+        long wchar = UNKNOWN_VALUE;
+        long syscr = UNKNOWN_VALUE;
+        long syscw = UNKNOWN_VALUE;
+        long read_bytes = UNKNOWN_VALUE;
+        long write_bytes = UNKNOWN_VALUE;
+        long cancelled_write_bytes = UNKNOWN_VALUE;
+
+        String line;
+        while ((line = r.readLine()) != null) {
+            String[] parts = line.split(":");
+            String key = parts[0].trim();
+            String value = parts[1].trim();
+            switch (key) {
+                case "rchar":
+                    rchar = Long.valueOf(value);
+                    break;
+                case "wchar":
+                    wchar = Long.valueOf(value);
+                    break;
+                case "syscr":
+                    syscr = Long.valueOf(value);
+                    break;
+                case "syscw":
+                    syscw = Long.valueOf(value);
+                    break;
+                case "read_bytes":
+                    read_bytes = Long.valueOf(value);
+                    break;
+                case "write_bytes":
+                    write_bytes = Long.valueOf(value);
+                    break;
+                case "cancelled_write_bytes":
+                    cancelled_write_bytes = Long.valueOf(value);
+                    break;
+            }
+        }
+
+        return new ProcIoData(rchar, wchar, syscr, syscw, read_bytes, write_bytes, cancelled_write_bytes);
+    }
+
+}
+
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHostImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +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.common.portability.internal.windows;
-
-import com.redhat.thermostat.common.portability.PortableHost;
-import com.redhat.thermostat.common.portability.PortableMemoryStat;
-
-public class WindowsHostImpl implements PortableHost {
-
-    public static final WindowsHostImpl INSTANCE = new WindowsHostImpl();
-    private static final WindowsHelperImpl helper = WindowsHelperImpl.INSTANCE;
-
-    @Override
-    public String getHostName() {
-        return helper.getHostName();
-    }
-
-    @Override
-    public String getOSName() {
-        return helper.getOSName();
-    }
-
-    @Override
-    public String getOSVersion() {
-        return helper.getOSVersion();
-    }
-
-    @Override
-    public String getCPUModel() {
-        return helper.getCPUModel();
-    }
-
-    @Override
-    public int getCPUCount() {
-        return helper.getCPUCount();
-    }
-
-    @Override
-    public long getTotalMemory() {
-        return helper.getTotalMemory();
-    }
-
-    @Override
-    public long getClockTicksPerSecond() {
-        return helper.getClockTicksPerSecond();
-    }
-
-    @Override
-    public PortableMemoryStat getMemoryStat() {
-        return new WindowsMemoryStat();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableHostImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.windows;
+
+import com.redhat.thermostat.common.portability.PortableHost;
+import com.redhat.thermostat.common.portability.PortableMemoryStat;
+
+public class WindowsPortableHostImpl implements PortableHost {
+
+    public static final WindowsPortableHostImpl INSTANCE = new WindowsPortableHostImpl();
+
+    public static PortableHost createInstance() {
+        return new WindowsPortableHostImpl();
+    }
+
+    private static final WindowsHelperImpl helper = WindowsHelperImpl.INSTANCE;
+
+    @Override
+    public String getHostName() {
+        return helper.getHostName();
+    }
+
+    @Override
+    public String getOSName() {
+        return helper.getOSName();
+    }
+
+    @Override
+    public String getOSVersion() {
+        return helper.getOSVersion();
+    }
+
+    @Override
+    public String getCPUModel() {
+        return helper.getCPUModel();
+    }
+
+    @Override
+    public int getCPUCount() {
+        return helper.getCPUCount();
+    }
+
+    @Override
+    public long getTotalMemory() {
+        return helper.getTotalMemory();
+    }
+
+    @Override
+    public long getClockTicksPerSecond() {
+        return helper.getClockTicksPerSecond();
+    }
+
+    @Override
+    public PortableMemoryStat getMemoryStat() {
+        return new WindowsMemoryStat();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsPortableProcessImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,102 @@
+/*
+ * 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.windows;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.common.portability.PortableProcessStat;
+import com.redhat.thermostat.common.portability.PortableVmIoStat;
+
+import java.util.Map;
+
+public class WindowsPortableProcessImpl implements PortableProcess {
+
+    public static final WindowsPortableProcessImpl INSTANCE = new WindowsPortableProcessImpl();
+    private static final WindowsHelperImpl helper = WindowsHelperImpl.INSTANCE;
+
+    public static PortableProcess createInstance() {
+        return new WindowsPortableProcessImpl();
+    }
+
+    @Override
+    public boolean exists(int pid) {
+        return helper.exists(pid);
+    }
+
+    @Override
+    public String getUserName(int pid) {
+        return helper.getUserName(pid);
+    }
+
+    @Override
+    public int getUid(int pid) {
+        return helper.getUid(pid);
+    }
+
+    @Override
+    public Map<String, String> getEnvironment(int pid) {
+        return helper.getEnvironment(pid);
+    }
+
+    @Override
+    public PortableProcessStat getProcessStat(int pid) {
+        final long[] info = helper.getProcessCPUInfo(pid);
+        final long utime = info[1];
+        final long stime = info[2];
+        return new PortableProcessStat(pid, utime, stime);
+    }
+
+    @Override
+    public PortableVmIoStat getVmIoStat(Clock clock, int pid) {
+        return new WindowsVmIoStat(clock, pid);
+    }
+
+    @Override
+    public boolean terminateProcess(int pid) {
+        return helper.terminateProcess(pid);
+    }
+
+    @Override
+    public boolean terminateProcess(int pid, boolean wait) {
+        return helper.terminateProcess(pid, wait);
+    }
+
+    @Override
+    public boolean terminateProcess(int pid, int exitcode, int waitMillis) {
+        return helper.terminateProcess(pid, exitcode, waitMillis);
+    }
+}
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsProcessImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +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.common.portability.internal.windows;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.portability.PortableProcess;
-import com.redhat.thermostat.common.portability.PortableProcessStat;
-import com.redhat.thermostat.common.portability.PortableVmIoStat;
-
-import java.util.Map;
-
-public class WindowsProcessImpl implements PortableProcess {
-
-    public static final WindowsProcessImpl INSTANCE = new WindowsProcessImpl();
-    private static final WindowsHelperImpl helper = WindowsHelperImpl.INSTANCE;
-
-    @Override
-    public boolean exists(int pid) {
-        return helper.exists(pid);
-    }
-
-    @Override
-    public String getUserName(int pid) {
-        return helper.getUserName(pid);
-    }
-
-    @Override
-    public int getUid(int pid) {
-        return helper.getUid(pid);
-    }
-
-    @Override
-    public Map<String, String> getEnvironment(int pid) {
-        return helper.getEnvironment(pid);
-    }
-
-    @Override
-    public PortableProcessStat getProcessStat(int pid) {
-        final long[] info = helper.getProcessCPUInfo(pid);
-        final long utime = info[1];
-        final long stime = info[2];
-        return new PortableProcessStat(pid, utime, stime);
-    }
-
-    @Override
-    public PortableVmIoStat getVmIoStat(Clock clock, int pid) {
-        return new WindowsVmIoStat(clock, pid);
-    }
-
-    @Override
-    public boolean terminateProcess(int pid) {
-        return helper.terminateProcess(pid);
-    }
-
-    @Override
-    public boolean terminateProcess(int pid, boolean wait) {
-        return helper.terminateProcess(pid, wait);
-    }
-
-    @Override
-    public boolean terminateProcess(int pid, int exitcode, int waitMillis) {
-        return helper.terminateProcess(pid, exitcode, waitMillis);
-    }
-}
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsUserInfoBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/internal/windows/WindowsUserInfoBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -56,7 +56,7 @@
     private static final Logger logger = LoggingUtils.getLogger(WindowsUserInfoBuilderImpl.class);
 
     public WindowsUserInfoBuilderImpl() {
-        this(PortableProcessImpl.INSTANCE);
+        this(PortableProcessImpl.getInstance());
     }
 
     WindowsUserInfoBuilderImpl(PortableProcess helper) {
--- a/common/portability/src/main/java/com/redhat/thermostat/common/portability/linux/ProcDataSource.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/main/java/com/redhat/thermostat/common/portability/linux/ProcDataSource.java	Mon Jan 30 10:30:19 2017 -0500
@@ -43,8 +43,8 @@
 /**
  * Wrapper for files under {@code /proc/}. See proc(5) for details about this.
  *
- * This class is inherently unportable, but a _lot_ of Linux code would need refactoring
- * before it can be unexported from the portability package.
+ * This class is inherently unportable, but a _lot_ of Linux code needs refactoring
+ * before it can be make package private
  *
  * Note that different Unix-like OSs may or may not have a /proc (and the format may be different)
  * for example Darwin/OSX doesn't have /proc
--- a/common/portability/src/test/java/com/redhat/thermostat/common/portability/ProcessCheckerTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/ProcessCheckerTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -42,7 +42,6 @@
 
 import java.io.File;
 
-import com.redhat.thermostat.common.portability.ProcessChecker;
 import org.junit.Test;
 
 public class ProcessCheckerTest {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/DistributionInformationTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,179 @@
+/*
+ * 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 java.io.IOException;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.shared.config.OS;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DistributionInformationTest {
+    
+    private Logger logger;
+    private TestLogHandler handler;
+    
+    @Before
+    public void setup() {
+        setupTestLogger();
+    }
+    
+    @After
+    public void tearDown() {
+        if (handler != null) {
+            logger.removeHandler(handler);
+            handler = null;
+        }
+    }
+    
+    private void setupTestLogger() {
+        logger = Logger.getLogger("com.redhat.thermostat");
+        handler = new TestLogHandler();
+        logger.addHandler(handler);
+    }
+    
+    /*
+     * Verifies that no warning gets logged if EtcOsRelease fails, but
+     * LsbRelease works. Since LsbRelease is the fallback, all is well.
+     * 
+     * see: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1628
+     */
+    @Test
+    public void testNoWarningLoggedOnFallback() {
+        // verify preconditions
+        assertFalse(handler.isEtcOsReleaseLogged());
+        assertTestHandlerRegistered();
+        
+        // Default LSB release
+        LsbRelease lsbRelease = new LsbRelease();
+        // EtcOsRelease with non existent file
+        EtcOsRelease etcOsRelease = new EtcOsRelease(EtcOsReleaseTest.NOT_EXISTING_OS_RELEASE_FILE);
+        DistributionInformation.get(etcOsRelease, lsbRelease);
+        assertFalse(handler.isEtcOsReleaseLogged());
+    }
+    
+    /*
+     * Verifies that a warning gets logged if os-release and lsb_release both
+     * fail.
+     * 
+     * see: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1628
+     */
+    @Test
+    public void testWarningLoggedIfBothFail() {
+        // verify preconditions
+        assertFalse(handler.isEtcOsReleaseLogged());
+        assertFalse(handler.isLsbReleaseLogged());
+        assertTestHandlerRegistered();
+        
+        // both etc-os-release and lsb-release don't exist for this test
+        EtcOsRelease etcOsRelease = new EtcOsRelease(EtcOsReleaseTest.NOT_EXISTING_OS_RELEASE_FILE);
+        LsbRelease lsbRelease = new LsbRelease(LsbReleaseTest.NOT_EXISTING_LSB_RELEASE);
+        
+        DistributionInformation info = DistributionInformation.get(etcOsRelease, lsbRelease);
+        assertFalse(handler.isEtcOsReleaseLogged());
+        assertTrue(handler.isLsbReleaseLogged());
+        assertNotNull(info);
+        assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
+        assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
+    }
+    
+    @Test
+    public void verifyFallbackToLsbWhenEtcOsReturnsUnknown() throws IOException {
+        EtcOsRelease mockEtcOsRelease = mock(EtcOsRelease.class);
+        DistributionInformation mockDistro = mock(DistributionInformation.class);
+        when(mockEtcOsRelease.getDistributionInformation()).thenReturn(mockDistro);
+        when(mockDistro.getName()).thenReturn(DistributionInformation.UNKNOWN_NAME);
+        when(mockDistro.getVersion()).thenReturn(DistributionInformation.UNKNOWN_VERSION);
+        
+        LsbRelease mockLsbRelease = mock(LsbRelease.class);
+        DistributionInformation mockLsbDistro = mock(DistributionInformation.class);
+        when(mockLsbRelease.getDistributionInformation()).thenReturn(mockLsbDistro);
+        
+        DistributionInformation info = DistributionInformation.get(mockEtcOsRelease, mockLsbRelease);
+        assertSame("Expected lsb info to be used since etc returns unknown",
+                   mockLsbDistro, info);
+    }
+
+    private void assertTestHandlerRegistered() {
+        assertNotNull(logger);
+        boolean testLogHandlerRegistered = false;
+        for (Handler h: logger.getHandlers()) {
+            if (h instanceof TestLogHandler) {
+                testLogHandlerRegistered = true;
+            }
+        }
+        assertTrue(testLogHandlerRegistered);
+    }
+
+    @Test
+    public void testName() {
+        if (OS.IS_LINUX) {
+            DistributionInformation info = DistributionInformation.get();
+            String name = info.getName();
+            assertNotNull(name);
+            assertTrue(name.length() > 0);
+            assertFalse(name.startsWith(":"));
+            assertFalse(name.equals(DistributionInformation.UNKNOWN_NAME));
+        }
+    }
+
+    @Test
+    public void testVersion() {
+        if (OS.IS_LINUX) {
+            DistributionInformation info = DistributionInformation.get();
+            String version = info.getVersion();
+            assertNotNull(version);
+            assertTrue(version.length()> 0);
+            assertFalse(version.startsWith(":"));
+            assertFalse(version.equals(DistributionInformation.UNKNOWN_VERSION));
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/EtcOsReleaseTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,125 @@
+/*
+ * 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.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.UUID;
+
+import com.redhat.thermostat.shared.config.OS;
+import org.junit.Assume;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.internal.test.Bug;
+
+public class EtcOsReleaseTest {
+    
+    static final String NOT_EXISTING_OS_RELEASE_FILE = "/thermostat-os-release-testing-"
+            + UUID.randomUUID();
+
+    @Test
+    public void testName() throws IOException, InterruptedException {
+        BufferedReader reader = new BufferedReader(new StringReader("NAME=\"Name\"\n"));
+        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
+        assertEquals("Name", info.getName());
+    }
+
+
+    @Test
+    public void testVersion() throws IOException {
+        BufferedReader reader = new BufferedReader(new StringReader("VERSION=\"Version\"\n"));
+        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
+        assertEquals("Version", info.getVersion());
+    }
+
+    @Bug(id="981",
+        summary="DistributionInformationTest fails on OpenSUSE Linux 12.1",
+        url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=981")
+    @Test
+    public void testFormattedOutput() throws IOException {
+        String output =
+            "NAME=openSUSE\n" +
+            "VERSION = 12.1 (Asparagus)\n" +
+            "VERSION_ID=\"12.1\"\n" +
+            "PRETTY_NAME=\"openSUSE 12.1 (Asparagus) (x86_64)\"\n" +
+            "ID=opensuse";
+        BufferedReader reader = new BufferedReader(new StringReader(output));
+        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
+
+        assertEquals("openSUSE", info.getName());
+        assertEquals("12.1 (Asparagus)", info.getVersion());
+    }
+    
+    /**
+     * DistributionInformation falls back on LSB when /etc/os-release contains
+     * inconclusive content (empty in this case). It should not return some
+     * info as "Linux".
+     * 
+     * @throws IOException
+     */
+    @Test
+    public void testEmpty() throws IOException {
+        String output = "";
+        BufferedReader reader = new BufferedReader(new StringReader(output));
+        
+        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
+        assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
+        assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
+    }
+    
+    @Test
+    public void getDistributionInformationThrowsIOExceptionIfFileNotThere() {
+        Assume.assumeTrue(OS.IS_LINUX);
+        EtcOsRelease etcOsRelease = new EtcOsRelease(NOT_EXISTING_OS_RELEASE_FILE);
+        try {
+            etcOsRelease.getDistributionInformation();
+            fail("Should have thrown IOException, since file is not there!");
+        } catch (IOException e) {
+            // pass
+            String message = e.getMessage();
+            assertTrue(message.contains("/thermostat-os-release-testing-"));
+            assertTrue(message.contains("(No such file or directory)"));
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableHostImplTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,126 @@
+/*
+ * 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.portability.PortableHost;
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.InetAddress;
+
+import com.redhat.thermostat.shared.config.OS;
+import org.junit.Assume;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Size;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class LinuxPortableHostImplTest {
+
+    final int KILOBYTES_TO_BYTES = 1024;
+
+    @Test
+    public void testSimpleBuild() {
+        Assume.assumeTrue(OS.IS_LINUX);
+        PortableHost info = new LinuxPortableHostImpl(new ProcDataSource());
+        assertNotNull(info);
+    }
+
+    @Test
+    public void testCpuInfo() throws IOException {
+        String cpuInfoString =
+                "processor: 1\n" +
+                "model name: Test Model\n" +
+                "processor: 0\n" +
+                "model name: Test Model\n";
+
+        StringReader cpuInfoReader = new StringReader(cpuInfoString);
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getCpuInfoReader()).thenReturn(cpuInfoReader);
+
+        LinuxPortableHostImpl.HostCpuInfo cpuInfo = new LinuxPortableHostImpl(dataSource).getCpuInfo();
+        assertEquals(2, cpuInfo.count);
+        assertEquals("Test Model", cpuInfo.model);
+        verify(dataSource).getCpuInfoReader();
+    }
+
+    @Test
+    public void testMemoryInfo() throws IOException {
+        String memoryInfoString =
+                "MemTotal: 12345 kB";
+
+        StringReader memoryInfoReader = new StringReader(memoryInfoString);
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getMemInfoReader()).thenReturn(memoryInfoReader);
+
+        LinuxPortableHostImpl memoryInfo = new LinuxPortableHostImpl(dataSource);
+        assertNotNull(memoryInfo);
+        assertEquals(Size.bytes(12345 * KILOBYTES_TO_BYTES), memoryInfo.getTotalMemorySize());
+        verify(dataSource).getMemInfoReader();
+
+    }
+
+    @Test
+    public void testOsInfo() {
+        DistributionInformation distroInfo = new DistributionInformation("distro-name", "distro-version");
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        LinuxPortableHostImpl.HostOsInfo osInfo = new LinuxPortableHostImpl(dataSource).getOsInfo(distroInfo);
+        assertEquals("distro-name distro-version", osInfo.distribution);
+        assertEquals(System.getProperty("os.name") + " " + System.getProperty("os.version"), osInfo.kernel);
+    }
+
+    @Test
+    public void testHostname() {
+
+        InetAddress address = mock(InetAddress.class);
+        when(address.getCanonicalHostName()).thenReturn("test-hostname");
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+
+        String name = new LinuxPortableHostImpl(dataSource).getHostName(address);
+        assertEquals("test-hostname", name);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxPortableProcessStatBuilderImplTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,144 @@
+/*
+ * 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 static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import com.redhat.thermostat.common.portability.PortableProcessStat;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+
+public class LinuxPortableProcessStatBuilderImplTest {
+
+    @Test
+    public void testSimpleProcessStatus() {
+        ProcDataSource dataSource = new ProcDataSource();
+        PortableProcessStat stat = new LinuxPortableProcessStatBuilderImpl(dataSource).build(1);
+        assertNotNull(stat);
+    }
+
+    @Test
+    public void testKnownProcessStatus() throws IOException {
+        final int PID = 10363;
+        String PROCESS_NAME = "(bash)";
+        String STATE = "S";
+        String PPID = "1737";
+        String PROCESS_GROUP_ID = "10363";
+        String SESSION_ID = "10363";
+        String TTY_NUMBER = "34817";
+        String TTY_PROCESS_GROUP_ID = "11404";
+        String FLAGS_WORD = "4202496";
+        String MINOR_FAULTS = "8093";
+        String MINOR_FAULTS_CHILDREN = "607263";
+        String MAJOR_FAULTS = "1";
+        String MAJOR_FAULTS_CHILDREN = "251";
+        final long USER_TIME_TICKS = 21;
+        final long KERNEL_TIME_TICKS = 7;
+        final long USER_TIME_CHILDREN = 10;
+        String KERNEL_TIME_CHILDREN = "1000";
+        String PRIORITY = "20";
+        String statString = "" +
+                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
+                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
+                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
+                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
+                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
+                KERNEL_TIME_CHILDREN + " " + PRIORITY;
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
+        LinuxPortableProcessStatBuilderImpl builder = new LinuxPortableProcessStatBuilderImpl(dataSource);
+        PortableProcessStat stat = builder.build(PID);
+
+        verify(dataSource).getStatReader(PID);
+        assertNotNull(stat);
+        assertEquals(PID, stat.getPid());
+        assertEquals(USER_TIME_TICKS, stat.getUserTime());
+        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
+    }
+
+    @Test
+    public void testBadProcessName() throws IOException {
+        final int PID = 10363;
+        String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)";
+        String STATE = "S";
+        String PPID = "1737";
+        String PROCESS_GROUP_ID = "10363";
+        String SESSION_ID = "10363";
+        String TTY_NUMBER = "34817";
+        String TTY_PROCESS_GROUP_ID = "11404";
+        String FLAGS_WORD = "4202496";
+        String MINOR_FAULTS = "8093";
+        String MINOR_FAULTS_CHILDREN = "607263";
+        String MAJOR_FAULTS = "1";
+        String MAJOR_FAULTS_CHILDREN = "251";
+        final long USER_TIME_TICKS = 21;
+        final long KERNEL_TIME_TICKS = 7;
+        final long USER_TIME_CHILDREN = 10;
+        String KERNEL_TIME_CHILDREN = "1000";
+        String PRIORITY = "20";
+        String statString = "" +
+                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
+                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
+                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
+                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
+                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
+                KERNEL_TIME_CHILDREN + " " + PRIORITY;
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
+        LinuxPortableProcessStatBuilderImpl builder = new LinuxPortableProcessStatBuilderImpl(dataSource);
+        PortableProcessStat stat = builder.build(PID);
+
+        verify(dataSource).getStatReader(PID);
+        assertNotNull(stat);
+        assertEquals(PID, stat.getPid());
+        assertEquals(USER_TIME_TICKS, stat.getUserTime());
+        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LinuxProcessEnvironmentBuilderImplTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,137 @@
+/*
+ * 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.portability.linux.ProcDataSource;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Map;
+import java.util.Random;
+
+import com.redhat.thermostat.shared.config.OS;
+import org.junit.Assume;
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.TestUtils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+
+public class LinuxProcessEnvironmentBuilderImplTest {
+
+    private final Random r = new Random();
+
+    @Test
+    public void testBasicBuild() {
+        Assume.assumeTrue(OS.IS_LINUX);
+        ProcDataSource dataSource = new ProcDataSource();
+        Map<String, String> result = new LinuxProcessEnvironmentBuilderImpl(dataSource).build(TestUtils.getProcessId());
+        assertNotNull(result);
+        assertFalse(result.isEmpty());
+        assertTrue(result.containsKey("USER"));
+    }
+
+    @Test
+    public void testCustomEnvironment() throws IOException {
+        byte[] data = ("USER=test\000HOME=house\000").getBytes();
+
+        Reader r = new InputStreamReader(new ByteArrayInputStream(data));
+        ProcDataSource dataSource = Mockito.mock(ProcDataSource.class);
+        Mockito.when(dataSource.getEnvironReader(Matchers.any(Integer.class))).thenReturn(r);
+
+        Map<String, String> result = new LinuxProcessEnvironmentBuilderImpl(dataSource).build(0);
+
+        Mockito.verify(dataSource).getEnvironReader(Matchers.eq(0));
+        assertEquals("test", result.get("USER"));
+        assertEquals("house", result.get("HOME"));
+    }
+
+    @Test
+    public void testLargeRandomEnvironment() throws IOException {
+        int TEST_ENV_SIZE = 1024 * 1024;
+        byte[] data = new byte[TEST_ENV_SIZE];
+        int currentPosition = 0;
+        do {
+            byte[] key = generateRandomBytes();
+            byte[] value = generateRandomBytes();
+            if (currentPosition + key.length + value.length + 2 >= data.length) {
+                break;
+            }
+            System.arraycopy(key, 0, data, currentPosition, key.length);
+            currentPosition += key.length;
+            data[currentPosition] = (byte) '=';
+            currentPosition++;
+            System.arraycopy(value, 0, data, currentPosition, value.length);
+            currentPosition += value.length;
+            data[currentPosition] = 0x00;
+            currentPosition++;
+        } while (true);
+        Reader r = new InputStreamReader(new ByteArrayInputStream(data, 0, currentPosition));
+        ProcDataSource dataSource = Mockito.mock(ProcDataSource.class);
+        Mockito.when(dataSource.getEnvironReader(Matchers.any(Integer.class))).thenReturn(r);
+
+        Map<String, String> result = new LinuxProcessEnvironmentBuilderImpl(dataSource).build(0);
+
+        Mockito.verify(dataSource).getEnvironReader(Matchers.eq(0));
+        assertNotNull(result);
+    }
+
+    private byte[] generateRandomBytes() {
+        byte start = (byte) 'a';
+        byte end = (byte) 'z' + 1;
+
+        byte[] alphabet = new byte[end - start];
+        for (int i = 0; i < (end-start); i++) {
+            alphabet[i] = (byte) (i + start);
+        }
+        int size = r.nextInt(15) + 10;
+        byte[] result = new byte[size];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = alphabet[r.nextInt(alphabet.length)];
+        }
+        return result;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/LsbReleaseTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.UUID;
+
+import com.redhat.thermostat.common.portability.internal.linux.DistributionInformation;
+import com.redhat.thermostat.common.portability.internal.linux.LsbRelease;
+import com.redhat.thermostat.shared.config.OS;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class LsbReleaseTest {
+    
+    static final String NOT_EXISTING_LSB_RELEASE = "lsb_release-"
+            + UUID.randomUUID();
+
+    @Test
+    public void testName() throws IOException, InterruptedException {
+        Assume.assumeTrue(OS.IS_LINUX);
+        BufferedReader reader = new BufferedReader(new StringReader("Distributor ID: Name"));
+        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
+        assertEquals("Name", info.getName());
+    }
+
+    @Test
+    public void testVersion() throws IOException {
+        Assume.assumeTrue(OS.IS_LINUX);
+        BufferedReader reader = new BufferedReader(new StringReader("Release: Version"));
+        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
+        assertEquals("Version", info.getVersion());
+    }
+    
+    @Test
+    public void getDistributionInformationThrowsIOExceptionIfScriptNotThere() {
+        Assume.assumeTrue(OS.IS_LINUX);
+        LsbRelease lsbRelease = new LsbRelease(NOT_EXISTING_LSB_RELEASE);
+        try {
+            lsbRelease.getDistributionInformation();
+            fail("Should have thrown IOException, since file is not there!");
+        } catch (IOException e) {
+            // pass
+            String message = e.getMessage();
+            assertTrue(message.contains("Cannot run program \"lsb_release-"));
+            assertTrue(message.contains("No such file or directory"));
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/TestLogHandler.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,87 @@
+/*
+ * 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 java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+/*
+ * Test log handler used for DistributionInformation log testing.
+ */
+public class TestLogHandler extends Handler {
+    
+    private boolean etcOsReleaseLogged;
+    private boolean lsbReleaseLogged;
+    private static final String EXPECTED_OS_RELEASE_FAIL_MSG =
+            "unable to use os-release";
+    private static final String EXPECTED_LSB_RELEASE_FAIL_MSG =
+            "unable to use os-release AND lsb_release";
+    
+    @Override
+    public void publish(LogRecord record) {
+        String logMessage = record.getMessage();
+        if (record.getLevel().intValue() >= Level.WARNING.intValue() && 
+                logMessage.equals(EXPECTED_OS_RELEASE_FAIL_MSG)) {
+            etcOsReleaseLogged = true;
+        };
+        if (record.getLevel().intValue() >= Level.WARNING.intValue() &&
+                logMessage.equals(EXPECTED_LSB_RELEASE_FAIL_MSG)) {
+            lsbReleaseLogged = true;
+        }
+    }
+
+    @Override
+    public void flush() {
+        // nothing
+    }
+
+    @Override
+    public void close() throws SecurityException {
+        // nothing
+    }
+    
+    boolean isEtcOsReleaseLogged() {
+        return etcOsReleaseLogged;
+    }
+    
+    boolean isLsbReleaseLogged() {
+        return lsbReleaseLogged;
+    }
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/vmio/LinuxVmIoStatBuilderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vmio;
+
+import com.redhat.thermostat.common.portability.PortableVmIoStat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Clock;
+
+public class LinuxVmIoStatBuilderTest {
+
+
+    @Test
+    public void testBuilderBuildsNullForUnknownPid() {
+        Clock clock = mock(Clock.class);
+        ProcIoDataReader procDataReader = mock(ProcIoDataReader.class);
+        LinuxVmIoStatBuilderImpl builder = new LinuxVmIoStatBuilderImpl(clock, procDataReader);
+        PortableVmIoStat result = builder.build(0);
+        assertNull(result);
+    }
+
+    @Test
+    public void testBuildWithSufficientInformation() {
+        final int PID = 0;
+
+        int rchar = 1;
+        int wchar = 2;
+        int syscr = 3;
+        int syscw = 4;
+        int read_bytes = 5;
+        int write_bytes = 6;
+        int cancelled_write_bytes = 7;
+
+        final ProcIoData data = new ProcIoData(rchar, wchar, syscr, syscw,
+                read_bytes, write_bytes, cancelled_write_bytes);
+
+        ProcIoDataReader ioReader = mock(ProcIoDataReader.class);
+        when(ioReader.read(PID)).thenReturn(data);
+        Clock clock = mock(Clock.class);
+
+        LinuxVmIoStatBuilderImpl builder = new LinuxVmIoStatBuilderImpl(clock, ioReader);
+
+        PortableVmIoStat ioData = builder.build(PID);
+        assertNotNull(ioData);
+        assertEquals(rchar, ioData.getCharactersRead());
+        assertEquals(wchar, ioData.getCharactersWritten());
+        assertEquals(syscr, ioData.getReadSyscalls());
+        assertEquals(syscw, ioData.getWriteSyscalls());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/linux/vmio/ProcIoDataReaderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,76 @@
+/*
+ * 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.vmio;
+
+import java.io.StringReader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ProcIoDataReaderTest {
+
+    @Test
+    public void verifyIsParsedCorrectly() throws Exception {
+        final int SOME_PID = 0;
+        String fileContents = "" +
+                "rchar: 19961133\n" +
+                "wchar: 2451715\n" +
+                "syscr: 17880\n" +
+                "syscw: 13870\n" +
+                "read_bytes: 21004288\n" +
+                "write_bytes: 811008\n" +
+                "cancelled_write_bytes: 16384\n";
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getIoReader(SOME_PID)).thenReturn(new StringReader(fileContents));
+
+        ProcIoData parsedData = new ProcIoDataReader(dataSource).read(SOME_PID);
+
+        assertEquals(19961133, parsedData.rchar);
+        assertEquals(2451715, parsedData.wchar);
+        assertEquals(17880, parsedData.syscr);
+        assertEquals(13870, parsedData.syscw);
+        assertEquals(21004288, parsedData.read_bytes);
+        assertEquals(811008, parsedData.write_bytes);
+        assertEquals(16384, parsedData.cancelled_write_bytes);
+
+    }
+}
--- a/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImplTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsHelperImplTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -38,7 +38,6 @@
 
 import com.redhat.thermostat.shared.config.OS;
 
-import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -61,21 +60,21 @@
     public void loadNativeLib() {
         Assume.assumeTrue(OS.IS_WINDOWS);
         final WindowsHelperImpl impl = WindowsHelperImpl.INSTANCE;
-        Assert.assertNotNull(impl);
+        assertNotNull(impl);
     }
 
     @Test
     public void testGetHostInfo() {
         Assume.assumeTrue(OS.IS_WINDOWS);
         final WindowsHelperImpl impl = WindowsHelperImpl.INSTANCE;
-        Assert.assertNotNull(impl);
+        assertNotNull(impl);
         assertContainsData(impl.getHostName());
         assertContainsData(impl.getOSName());
-        Assert.assertTrue(impl.getOSName().toLowerCase().contains("win"));
+        assertTrue(impl.getOSName().toLowerCase().contains("win"));
         assertContainsData(impl.getOSVersion());
         assertContainsData(impl.getCPUModel());
-        Assert.assertTrue(impl.getCPUCount() > 0);
-        Assert.assertTrue(impl.getTotalMemory() > 0);
+        assertTrue(impl.getCPUCount() > 0);
+        assertTrue(impl.getTotalMemory() > 0);
     }
 
     @Test
@@ -83,17 +82,17 @@
     public void testGetProcessInfo() {
         Assume.assumeTrue(OS.IS_WINDOWS);
         final WindowsHelperImpl impl = WindowsHelperImpl.INSTANCE;
-        Assert.assertNotNull(impl);
+        assertNotNull(impl);
         int pid = /*TODO: retrieve current process identifier*/0;
         assertContainsData(impl.getUserName(pid));
-        Assert.assertTrue(impl.getUid(pid) >= 0);
+        assertTrue(impl.getUid(pid) >= 0);
         Map<String,String> envMap = impl.getEnvironment(pid);
-        Assert.assertNotNull(envMap);
-        Assert.assertFalse(envMap.isEmpty());
+        assertNotNull(envMap);
+        assertFalse(envMap.isEmpty());
     }
 
     private static void assertContainsData( final String s ) {
-        Assert.assertNotNull(s);
-        Assert.assertFalse(s.isEmpty());
+        assertNotNull(s);
+        assertFalse(s.isEmpty());
     }
 }
--- a/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsProcessUserInfoBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/internal/windows/WindowsProcessUserInfoBuilderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -41,7 +41,6 @@
 import com.redhat.thermostat.common.portability.PortableProcess;
 import com.redhat.thermostat.shared.config.OS;
 
-import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -81,7 +80,7 @@
     public void testSimpleBuild() {
         Assume.assumeTrue(OS.IS_WINDOWS);
         ProcessUserInfo info = new WindowsUserInfoBuilderImpl().build(FAKE_PID);
-        Assert.assertNotNull(info);
+        assertNotNull(info);
     }
 
     @Test
@@ -96,7 +95,7 @@
     public void testGetInfoFromBadPid() {
         final ProcessUserInfoBuilder ib = new WindowsUserInfoBuilderImpl(whelp);
         final ProcessUserInfo hi = ib.build(FAKE_PID+1);
-        Assert.assertNotSame(FAKE_USERNAME,hi.getUsername());
-        Assert.assertNotSame(FAKE_UID, hi.getUid());
+        assertNotSame(FAKE_USERNAME,hi.getUsername());
+        assertNotSame(FAKE_UID, hi.getUid());
     }
 }
--- a/common/portability/src/test/java/com/redhat/thermostat/common/portability/linux/ProcDataSourceTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/common/portability/src/test/java/com/redhat/thermostat/common/portability/linux/ProcDataSourceTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -36,44 +36,43 @@
 
 package com.redhat.thermostat.common.portability.linux;
 
-import static org.junit.Assert.*;
-
 import java.io.IOException;
 import java.io.Reader;
 
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
 import com.redhat.thermostat.shared.config.OS;
+
+import com.redhat.thermostat.testutils.TestUtils;
+
 import org.junit.Assume;
 import org.junit.Test;
-
-import com.redhat.thermostat.testutils.TestUtils;
+import static org.junit.Assert.assertNotNull;
 
 public class ProcDataSourceTest {
 
     @Test
     public void testGetCpuInfoReader() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         Reader r = new ProcDataSource().getCpuInfoReader();
         assertNotNull(r);
     }
 
     @Test
     public void testGetCpuLoadReader() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         Reader r = new ProcDataSource().getCpuLoadReader();
         assertNotNull(r);
     }
 
     @Test
     public void testGetMemInfoReader() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         Reader r = new ProcDataSource().getMemInfoReader();
         assertNotNull(r);
     }
 
     @Test
     public void testGetStatReader() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         int pid = TestUtils.getProcessId();
         Reader r = new ProcDataSource().getStatReader(pid);
         assertNotNull(r);
@@ -81,7 +80,7 @@
 
     @Test
     public void testGetEnvironReader() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         int pid = TestUtils.getProcessId();
         Reader r = new ProcDataSource().getEnvironReader(pid);
         assertNotNull(r);
@@ -89,7 +88,7 @@
 
     @Test
     public void testIoReader() throws Exception {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         int pid = TestUtils.getProcessId();
         Reader r = new ProcDataSource().getIoReader(pid);
         assertNotNull(r);
@@ -97,7 +96,7 @@
 
     @Test
     public void testStatReader() throws Exception {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         int pid = TestUtils.getProcessId();
         Reader r = new ProcDataSource().getStatReader(pid);
         assertNotNull(r);
@@ -105,7 +104,7 @@
 
     @Test
     public void testStatusReader() throws Exception {
-        Assume.assumeTrue(OS.IS_UNIX);
+        Assume.assumeTrue(OS.IS_LINUX);
         int pid = TestUtils.getProcessId();
         Reader r = new ProcDataSource().getStatusReader(pid);
         assertNotNull(r);
--- a/distribution/windows/scripts/thermostat-ipc-client-common.cmd	Thu Jan 26 12:14:51 2017 -0500
+++ b/distribution/windows/scripts/thermostat-ipc-client-common.cmd	Mon Jan 30 10:30:19 2017 -0500
@@ -52,7 +52,7 @@
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\jnr-ffi-@jnr-ffi.version@.jar
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\jnr-x86asm-@jnr-x86asm.version@.jar
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\jffi-@jffi.version@.jar
-set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\jffi-@jffi.version%-native.jar
+set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\jffi-@jffi.version@-native.jar
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\asm-@asm.version@.jar
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\asm-commons-@asm.version@.jar
 set IPC_CLASSPATH=%IPC_CLASSPATH%;%THERMOSTAT_LIBS%\asm-util-@asm.version@.jar
--- a/host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java	Mon Jan 30 10:30:19 2017 -0500
@@ -74,12 +74,8 @@
             throw new IllegalStateException("already initialized");
         }
 
-        if (OS.IS_WINDOWS) {
-            logger.log(Level.WARNING, "CPU backend is not yet ported to Windows");
-        }
-
         previousTime = clock.getMonotonicTimeNanos();
-        previousCpuTicks = OS.IS_LINUX ? getCurrentCpuTicksLinux() : getCurrentCpuTicksWindows();
+        previousCpuTicks = OS.IS_LINUX ? getCurrentCpuTicksLinux() : getCurrentCpuTicks();
         initialized = true;
     }
 
@@ -90,7 +86,7 @@
 
         long currentRealTime = clock.getRealTimeMillis();
         long currentTime = clock.getMonotonicTimeNanos();
-        long[] currentValues = OS.IS_LINUX ? getCurrentCpuTicksLinux() : getCurrentCpuTicksWindows();
+        long[] currentValues = OS.IS_LINUX ? getCurrentCpuTicksLinux() : getCurrentCpuTicks();
 
         double[] cpuUsage = new double[currentValues.length];
 
@@ -137,7 +133,7 @@
         return values;
     }
 
-    private long[] getCurrentCpuTicksWindows() {
+    private long[] getCurrentCpuTicks() {
         long[] values = new long[1];
         values[0] = clock.getMonotonicTimeNanos();
         return values;
--- a/host-memory/agent/src/main/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatBuilder.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/host-memory/agent/src/main/java/com/redhat/thermostat/host/memory/agent/internal/MemoryStatBuilder.java	Mon Jan 30 10:30:19 2017 -0500
@@ -57,7 +57,7 @@
 
     private static final long UNAVAILABLE = -1;
 
-    private static final boolean IS_UNIX = OS.IS_UNIX;
+    private static final boolean IS_LINUX = OS.IS_LINUX;
 
     private static final String KEY_MEMORY_TOTAL = "MemTotal";
     private static final String KEY_MEMORY_FREE = "MemFree";
@@ -75,13 +75,10 @@
     public MemoryStatBuilder(ProcDataSource dataSource, WriterID writerId) {
         this.dataSource = dataSource;
         this.writerId = writerId;
-        if (OS.IS_WINDOWS) {
-            logger.log(Level.WARNING, "Memory backend is not yet ported to Windows");
-        }
     }
 
     protected MemoryStat build() {
-        return IS_UNIX ? buildFromLinuxProc() : buildFromWindows();
+        return IS_LINUX ? buildFromLinuxProc() : buildPortably();
     }
 
     private MemoryStat buildFromLinuxProc() {
@@ -127,7 +124,7 @@
     }
 
 
-    private MemoryStat buildFromWindows() {
+    private MemoryStat buildPortably() {
         long timestamp = System.currentTimeMillis();
 
         PortableMemoryStat memstat = PortableMemoryStat.build();
--- a/keyring/pom.xml	Thu Jan 26 12:14:51 2017 -0500
+++ b/keyring/pom.xml	Mon Jan 30 10:30:19 2017 -0500
@@ -52,12 +52,12 @@
     <profile>
       <id>linux</id>
       <activation>
-        <os><family>Unix</family></os>
+        <os><name>linux</name></os>
       </activation>
       <properties>
         <script.extension>.sh</script.extension>
         <c.compiler>gcc</c.compiler>
-        <cflags></cflags>
+        <cflags/>
         <jni.platform>linux</jni.platform>
         <sharedlib.prefix>lib</sharedlib.prefix>
         <sharedlib.suffix>.so</sharedlib.suffix>
@@ -102,12 +102,6 @@
                   <arguments>
                     <argument>all</argument>
                   </arguments>
-                  <systemProperties>
-                    <systemProperty>
-                      <key>JAVA_HOME</key>
-                      <value>${java.home}</value>
-                    </systemProperty>
-                  </systemProperties>
                 </configuration>
               </execution>
             </executions>
@@ -169,7 +163,7 @@
                     </goals>
                   </pluginExecutionFilter>
                   <action>
-                    <ignore></ignore>
+                    <ignore/>
                   </action>
                 </pluginExecution>
               </pluginExecutions>
--- a/keyring/src/main/java/com/redhat/thermostat/utils/keyring/internal/Activator.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/keyring/src/main/java/com/redhat/thermostat/utils/keyring/internal/Activator.java	Mon Jan 30 10:30:19 2017 -0500
@@ -79,7 +79,7 @@
         try {
             theKeyring = new KeyringImpl();
         } catch (UnsatisfiedLinkError e) {
-            if (OS.IS_UNIX) {
+            if (OS.IS_LINUX) {
                 theKeyring = new DummyKeyringImpl();
             }
             else {
--- a/laf-utils/pom.xml	Thu Jan 26 12:14:51 2017 -0500
+++ b/laf-utils/pom.xml	Mon Jan 30 10:30:19 2017 -0500
@@ -53,7 +53,7 @@
     <profile>
       <id>linux</id>
       <activation>
-        <os><family>unix</family></os>
+        <os><name>linux</name></os>
       </activation>
       <build>
         <plugins>
@@ -136,7 +136,7 @@
                     </goals>
                   </pluginExecutionFilter>
                   <action>
-                    <ignore></ignore>
+                    <ignore/>
                   </action>
                 </pluginExecution>
               </pluginExecutions>
--- a/numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/Activator.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/Activator.java	Mon Jan 30 10:30:19 2017 -0500
@@ -80,10 +80,10 @@
                 NumaDAO numaDAO = services.get(NumaDAO.class);
                 Version version = new Version(context.getBundle());
                 WriterID writerId = services.get(WriterID.class);
-                NumaCollector collector = OS.IS_LINUX ? new NumaLinuxCollectorImpl() : new NumaWindowsCollectorImpl();
+                NumaCollector collector = OS.IS_LINUX ? new NumaLinuxCollectorImpl() : new NumaCollectorImpl();
                 backend = new NumaBackend(appService, numaDAO, collector, version, writerId);
                 reg = context.registerService(Backend.class, backend, null);
-                if (OS.IS_WINDOWS) {
+                if (!OS.IS_LINUX) {
                     logger.log(Level.WARNING, "NUMA backend is not yet ported to Windows");
                 }
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/NumaCollectorImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,57 @@
+/*
+ * 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.numa.agent.internal;
+
+import com.redhat.thermostat.numa.common.NumaNodeStat;
+
+import java.io.IOException;
+
+public class NumaCollectorImpl implements NumaCollector {
+
+    @Override
+    public NumaNodeStat[] collectData() throws IOException {
+        final NumaNodeStat[] nsa = new NumaNodeStat[1];
+        final NumaNodeStat ns = new NumaNodeStat();
+        nsa[0] = ns;
+        return nsa;
+    }
+
+    @Override
+    public int getNumberOfNumaNodes() {
+        return 1;
+    }
+}
--- a/numa/agent/src/main/java/com/redhat/thermostat/numa/agent/internal/NumaWindowsCollectorImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +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.numa.agent.internal;
-
-import com.redhat.thermostat.numa.common.NumaNodeStat;
-
-import java.io.IOException;
-
-public class NumaWindowsCollectorImpl implements NumaCollector {
-
-    @Override
-    public NumaNodeStat[] collectData() throws IOException {
-        final NumaNodeStat[] nsa = new NumaNodeStat[1];
-        final NumaNodeStat ns = new NumaNodeStat();
-        nsa[0] = ns;
-        return nsa;
-    }
-
-    @Override
-    public int getNumberOfNumaNodes() {
-        return 1;
-    }
-}
--- a/pom.xml	Thu Jan 26 12:14:51 2017 -0500
+++ b/pom.xml	Mon Jan 30 10:30:19 2017 -0500
@@ -61,12 +61,12 @@
     <profile>
       <id>linux</id>
       <activation>
-        <os><family>Unix</family></os>
+        <os><name>linux</name></os>
       </activation>
       <properties>
         <script.extension>.sh</script.extension>
         <c.compiler>gcc</c.compiler>
-        <cflags></cflags>
+        <cflags/>
         <jni.platform>linux</jni.platform>
         <sharedlib.prefix>lib</sharedlib.prefix>
         <sharedlib.suffix>.so</sharedlib.suffix>
--- a/process-handler/src/main/java/com/redhat/thermostat/service/internal/windows/WindowsProcessUtilities.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/process-handler/src/main/java/com/redhat/thermostat/service/internal/windows/WindowsProcessUtilities.java	Mon Jan 30 10:30:19 2017 -0500
@@ -74,7 +74,7 @@
 
     @Override
     public void sendSignal(Integer pid, UNIXSignal signal) {
-        PortableProcessImpl.INSTANCE.terminateProcess(pid);
+        PortableProcessImpl.getInstance().terminateProcess(pid);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,73 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.common.portability.PortableHost;
+import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
+import com.redhat.thermostat.common.portability.PortableHostImpl;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.model.HostInfo;
+
+/**
+ * Build Host information via helper classes
+ */
+class HostInfoBuilderImpl implements HostInfoBuilder {
+
+    private final WriterID writerID;
+    private final PortableHost helper;
+
+    HostInfoBuilderImpl(final WriterID writerID) {
+        this(writerID, PortableHostImpl.getInstance());
+    }
+
+    HostInfoBuilderImpl(final WriterID writerID, PortableHost helper) {
+        this.writerID = writerID;
+        this.helper = helper;
+    }
+
+    @Override
+    public HostInfo build() {
+        String wId = writerID.getWriterID();
+        return new HostInfo(wId,
+                helper.getHostName(),
+                helper.getOSName(),
+                helper.getOSVersion(),
+                helper.getCPUModel(),
+                helper.getCPUCount(),
+                helper.getTotalMemory());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/InfoBuilderFactoryImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,67 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.common.portability.ProcessUserInfo;
+import com.redhat.thermostat.common.portability.ProcessUserInfoBuilder;
+import com.redhat.thermostat.common.portability.UserNameUtil;
+import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
+import com.redhat.thermostat.backend.system.internal.models.InfoBuilderFactory;
+import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
+import com.redhat.thermostat.common.portability.linux.ProcDataSource;
+import com.redhat.thermostat.storage.core.WriterID;
+
+/**
+ * Allows callers to access Windows-specific builders portably
+ */
+public class InfoBuilderFactoryImpl implements InfoBuilderFactory {
+
+    public InfoBuilderFactoryImpl() {
+    }
+
+    public HostInfoBuilder createHostInfoBuilder(final WriterID writerID) {
+        return new HostInfoBuilderImpl(writerID);
+    }
+
+    public ProcessEnvironmentBuilder createProcessEnvironmentBuilder() {
+        return new ProcessEnvironmentBuilderImpl();
+    }
+
+    public ProcessUserInfoBuilder createProcessUserInfoBuilder(final UserNameUtil userNameUtil) {
+        return ProcessUserInfo.createBuilder(new ProcDataSource(), userNameUtil);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,64 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.common.portability.PortableProcessImpl;
+
+import java.util.Map;
+
+/**
+ * Build process environment information via portable helper classes
+ */
+class ProcessEnvironmentBuilderImpl implements ProcessEnvironmentBuilder {
+
+    private final PortableProcess helper;
+
+    ProcessEnvironmentBuilderImpl() {
+        this(PortableProcessImpl.getInstance());
+    }
+
+    ProcessEnvironmentBuilderImpl(PortableProcess wh) {
+        helper = wh;
+    }
+
+    @Override
+    public Map<String, String> build(int pid) {
+        return helper.getEnvironment(pid);
+    }
+}
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformation.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +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.backend.system.internal.linux;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class DistributionInformation {
-
-    public static final String UNKNOWN_NAME = "Unknown Distribution";
-    public static final String UNKNOWN_VERSION = "Unknown Version";
-
-    private static final Logger logger = LoggingUtils.getLogger(DistributionInformation.class);
-
-    private final String name;
-    private final String version;
-
-    public DistributionInformation(String name, String version) {
-        this.name = name;
-        this.version = version;
-    }
-
-    public static DistributionInformation get() {
-        EtcOsRelease etcOsRelease = new EtcOsRelease();
-        LsbRelease lsbRelease = new LsbRelease();
-        return get(etcOsRelease, lsbRelease);
-    }
-    
-    // package-private for testing
-    static DistributionInformation get(EtcOsRelease etcOsRelease, LsbRelease lsbRelease) {
-        try {
-            DistributionInformation etcOsDistroInfo = etcOsRelease.getDistributionInformation();
-            // if both name and version are unknown defer to lsb fallback
-            if (!DistributionInformation.UNKNOWN_NAME.equals(etcOsDistroInfo.getName()) &&
-                !DistributionInformation.UNKNOWN_VERSION.equals(etcOsDistroInfo.getVersion())) {
-                return etcOsDistroInfo;
-            }
-            logger.log(Level.FINE, "/etc/os-release existing, but does not contain useful info");
-        } catch (IOException e) {
-            // Log only at level FINE, since we have the LSB fallback
-            logger.log(Level.FINE, "unable to use os-release", e);
-        }
-        try {
-            return lsbRelease.getDistributionInformation();
-        } catch (IOException e) {
-            // Log exception at level FINE only.
-            logger.log(Level.FINE, "unable to use lsb_release", e);
-            logger.log(Level.WARNING, "unable to use os-release AND lsb_release");
-        }
-        return new DistributionInformation(UNKNOWN_NAME, UNKNOWN_VERSION);
-    }
-
-    /**
-     * @return the name of the distribution, or {@link #UNKNOWN_NAME} if it can not be
-     * identified
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @return the release of the distribution or {@link #UNKNOWN_VERSION} if it can not be
-     * identified
-     */
-    public String getVersion() {
-        return version;
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformationSource.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.backend.system.internal.linux;
-
-import java.io.IOException;
-
-public interface DistributionInformationSource {
-
-    public DistributionInformation getDistributionInformation() throws IOException;
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/EtcOsRelease.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +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.backend.system.internal.linux;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-public class EtcOsRelease implements DistributionInformationSource {
-
-    private static final String EMPTY_STRING = "";
-    private static final String OS_RELEASE = "/etc/os-release";
-    private final String osReleaseFile;
-    
-    public EtcOsRelease() {
-        this.osReleaseFile = OS_RELEASE;
-    }
-    
-    // package-private for testing
-    EtcOsRelease(String osReleaseFile) {
-        this.osReleaseFile = osReleaseFile;
-    }
-    
-    @Override
-    public DistributionInformation getDistributionInformation() throws IOException {
-        return getFromOsRelease();
-    }
-
-    public DistributionInformation getFromOsRelease() throws IOException {
-        return getFromOsRelease(osReleaseFile);
-    }
-
-    public DistributionInformation getFromOsRelease(String releaseFile) throws IOException {
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(releaseFile), StandardCharsets.UTF_8))) {
-            return getFromOsRelease(reader);
-        }
-    }
-
-    public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException {
-        String version = DistributionInformation.UNKNOWN_VERSION;
-        String name = DistributionInformation.UNKNOWN_NAME;
-        String line = null;
-        while ((line = reader.readLine()) != null) {
-            // skip whitespace only lines
-            line = line.trim();
-            if (line.equals(EMPTY_STRING)) {
-                continue;
-            }
-            if (line.matches("^NAME *=.*")) {
-                name = readShellVariable(line);
-            }
-            if (line.matches("^VERSION *=.*")) {
-                version = readShellVariable(line);
-            }
-        }
-        return new DistributionInformation(name, version);
-    }
-
-    /** Reads and parses a shell variable declaration: {@code FOO="bar"}
-     *
-     * @return the value of the shell variable
-     */
-    private String readShellVariable(String line) {
-        // TODO we should try to handle shell quotes better
-        String result = line.substring(line.indexOf("=")+1);
-        result = result.trim();
-        if (result.startsWith("\"") && result.endsWith("\"")) {
-            result = result.substring(1, result.length()-1);
-            result = result.trim();
-        }
-        return result;
-    }
-
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/HostInfoBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +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.backend.system.internal.linux;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.common.portability.HostName;
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.common.Size;
-import com.redhat.thermostat.common.Size.Unit;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.HostInfo;
-
-public class HostInfoBuilderImpl implements HostInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilderImpl.class);
-
-    private static final String FALLBACK_LOCAL_HOSTNAME = "localhost";
-
-    static class HostCpuInfo {
-        final String model;
-        final int count;
-
-        HostCpuInfo(String model, int count) {
-            this.count = count;
-            this.model = model;
-        }
-    }
-
-    static class HostOsInfo {
-        final String kernel;
-        final String distribution;
-
-        HostOsInfo(String kernel, String distribution) {
-            this.kernel = kernel;
-            this.distribution = distribution;
-        }
-    }
-
-    static class HostMemoryInfo {
-        final Size totalMemory;
-
-        HostMemoryInfo(Size totalMemory) {
-            this.totalMemory = totalMemory;
-        }
-    }
-
-    private final ProcDataSource dataSource;
-    private final WriterID writerId;
-
-    HostInfoBuilderImpl(ProcDataSource dataSource, WriterID writerId) {
-        this.dataSource = dataSource;
-        this.writerId = writerId;
-    }
-
-    public HostInfo build() {
-        String hostname = getHostName();
-        HostCpuInfo cpuInfo = getCpuInfo();
-        HostMemoryInfo memoryInfo = getMemoryInfo();
-        long totalMemorySize = (long) memoryInfo.totalMemory.convertTo(Unit.B).getValue();
-        HostOsInfo osInfo = getOsInfo();
-        String wId = writerId.getWriterID();
-        return new HostInfo(wId, hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, totalMemorySize);
-    }
-
-    HostCpuInfo getCpuInfo() {
-        final String KEY_PROCESSOR_ID = "processor";
-        final String KEY_CPU_MODEL = "model name";
-        int cpuCount = 0;
-        String cpuModel = null;
-        try (BufferedReader bufferedReader = new BufferedReader(dataSource.getCpuInfoReader())) {
-            String line = null;
-            while ((line = bufferedReader.readLine()) != null) {
-                if (line.startsWith(KEY_PROCESSOR_ID)) {
-                    cpuCount++;
-                } else if (line.startsWith(KEY_CPU_MODEL)) {
-                    cpuModel = line.substring(line.indexOf(":") + 1).trim();
-                }
-            }
-        } catch (IOException ioe) {
-            logger.log(Level.WARNING, "unable to read cpu info");
-        }
-
-        logger.log(Level.FINEST, "cpuModel: " + cpuModel);
-        logger.log(Level.FINEST, "cpuCount: " + cpuCount);
-
-        return new HostCpuInfo(cpuModel, cpuCount);
-    }
-
-    HostMemoryInfo getMemoryInfo() {
-        Size totalMemory = null;
-        try (BufferedReader bufferedReader = new BufferedReader(dataSource.getMemInfoReader())) {
-            String[] memTotalParts = bufferedReader.readLine().split(" +");
-            long data = Long.valueOf(memTotalParts[1]);
-            String units = memTotalParts[2];
-            if (units.equals("kB")) {
-                totalMemory = new Size(data, Size.Unit.KiB);
-            }
-        } catch (IOException ioe) {
-            logger.log(Level.WARNING, "unable to read memory info");
-        }
-
-        logger.log(Level.FINEST, "totalMemory: " + (totalMemory != null ? totalMemory.toString() : "(null)"));
-        return new HostMemoryInfo(totalMemory);
-    }
-
-    HostOsInfo getOsInfo() {
-        return getOsInfo(DistributionInformation.get());
-    }
-
-    HostOsInfo getOsInfo(DistributionInformation distroInfo) {
-        String osName = distroInfo.getName() + " " + distroInfo.getVersion();
-        logger.log(Level.FINEST, "osName: " + osName);
-
-        String osKernel = System.getProperty("os.name") + " " + System.getProperty("os.version");
-        logger.log(Level.FINEST, "osKernel: " + osKernel);
-
-        return new HostOsInfo(osKernel, osName);
-    }
-
-    String getHostName() {
-        String hostname = null;
-        
-        try {
-            InetAddress localAddress = null;
-            localAddress = InetAddress.getLocalHost();
-            hostname = getHostName(localAddress);
-        } catch (UnknownHostException uhe) {
-            logger.log(Level.WARNING, "unable to get hostname", uhe);
-        }
-        
-        // if fails, try to get hostname without dns lookup
-        if (hostname == null) {
-            hostname = HostName.getLocalHostName();
-        }
-        
-        // still null, use localhost
-        if (hostname == null) {
-            hostname = FALLBACK_LOCAL_HOSTNAME;
-
-        }
-        
-        return hostname;
-    }
-
-    String getHostName(InetAddress localAddress) {
-        String hostname = localAddress.getCanonicalHostName();
-        logger.log(Level.FINEST, "hostname: " + hostname);
-        return hostname;
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/LinuxInfoBuilderFactory.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +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.backend.system.internal.linux;
-
-import com.redhat.thermostat.common.portability.ProcessUserInfo;
-import com.redhat.thermostat.common.portability.ProcessUserInfoBuilder;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.common.portability.UserNameUtil;
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.backend.system.internal.models.InfoBuilderFactory;
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import com.redhat.thermostat.storage.core.WriterID;
-
-/**
- * Allows callers to access Linux-specific builders portably
- */
-public class LinuxInfoBuilderFactory implements InfoBuilderFactory {
-
-    private final ProcDataSource dataSource;
-
-    public LinuxInfoBuilderFactory() {
-        dataSource = new ProcDataSource();
-    }
-
-    public LinuxInfoBuilderFactory(final ProcDataSource ds) {
-        dataSource = ds;
-    }
-
-    public HostInfoBuilder createHostInfoBuilder(final WriterID writerID) {
-        return new HostInfoBuilderImpl(dataSource, writerID);
-    }
-
-    public ProcessEnvironmentBuilder createProcessEnvironmentBuilder() {
-        return new ProcessEnvironmentBuilderImpl(dataSource);
-    }
-
-    public ProcessUserInfoBuilder createProcessUserInfoBuilder(final UserNameUtil userNameUtil) {
-        return ProcessUserInfo.createBuilder(dataSource, userNameUtil);
-    }
-}
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/LsbRelease.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +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.backend.system.internal.linux;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-class LsbRelease implements DistributionInformationSource {
-
-    private static final Logger logger = LoggingUtils.getLogger(LsbRelease.class);
-
-    private static final String DISTRIBUTION_NAME = "distributor id";
-    private static final String DISTRIBUTION_VERSION = "release";
-    private static final String LSB_RELEASE_SCRIPT = "lsb_release";
-    
-    private final String lsbRelaseBin;
-    
-    LsbRelease() {
-        this.lsbRelaseBin = LSB_RELEASE_SCRIPT;
-    }
-    
-    // package-private for testing
-    LsbRelease(String lsbReleaseBin) {
-        this.lsbRelaseBin = lsbReleaseBin;
-    }
-
-    @Override
-    public DistributionInformation getDistributionInformation()
-            throws IOException {
-        return getFromLsbRelease();
-    }
-
-    DistributionInformation getFromLsbRelease() throws IOException {
-        BufferedReader reader = null;
-        try {
-            Process lsbProc = Runtime.getRuntime().exec(new String[] { lsbRelaseBin, "-a" });
-            InputStream progOutput = lsbProc.getInputStream();
-            reader = new BufferedReader(new InputStreamReader(progOutput));
-            DistributionInformation result = getFromLsbRelease(reader);
-            int exitValue = lsbProc.waitFor();
-            if (exitValue != 0) {
-                logger.log(Level.WARNING, "unable to identify distribution, problems running 'lsb_release'");
-            }
-            return result;
-        } catch (InterruptedException e) {
-            throw new IOException(e);
-        } finally {
-            if (reader != null) {
-                try {
-                    reader.close();
-                } catch (IOException e) {
-                    logger.log(Level.WARNING, "unable to close a child's output stream");
-                }
-            }
-        }
-
-    }
-
-    DistributionInformation getFromLsbRelease(BufferedReader reader) throws IOException {
-        String name = DistributionInformation.UNKNOWN_NAME;
-        String version = DistributionInformation.UNKNOWN_VERSION;
-
-        String line;
-        while ((line = reader.readLine()) != null) {
-            int sepLocation = line.indexOf(":");
-            if (sepLocation != -1) {
-                String key = line.substring(0, sepLocation).toLowerCase();
-                if (key.equals(DISTRIBUTION_NAME)) {
-                    name = line.substring(sepLocation + 1).trim();
-                } else if (key.equals(DISTRIBUTION_VERSION)) {
-                    version = line.substring(sepLocation + 1).trim();
-                }
-            }
-        }
-
-        logger.log(Level.FINE, "distro-name: " + name);
-        logger.log(Level.FINE, "distro-version: " + version);
-
-        return new DistributionInformation(name, version);
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/linux/ProcessEnvironmentBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +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.backend.system.internal.linux;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-class ProcessEnvironmentBuilderImpl implements ProcessEnvironmentBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(ProcessEnvironmentBuilderImpl.class);
-
-    private final ProcDataSource dataSource;
-
-    ProcessEnvironmentBuilderImpl(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public Map<String, String> build(int pid) {
-        try (Reader reader = dataSource.getEnvironReader(pid)) {
-            return build(reader);
-        } catch (IOException ioe) {
-            logger.log(Level.WARNING, "error reading env", ioe);
-        }
-
-        return Collections.emptyMap();
-    }
-
-    private Map<String,String> build(Reader reader) throws IOException {
-
-        Map<String, String> env = new HashMap<String, String>();
-
-        char[] fileBuffer = new char[1024];
-        int fileBufferIndex = 0;
-        char[] buffer = new char[1024];
-        int read = 0;
-        while (true) {
-            read = reader.read(buffer);
-            if (read == -1) {
-                break;
-            }
-
-            if (read + fileBufferIndex > fileBuffer.length) {
-                char[] newFileBuffer = new char[fileBuffer.length * 2];
-                System.arraycopy(fileBuffer, 0, newFileBuffer, 0, fileBufferIndex);
-                fileBuffer = newFileBuffer;
-            }
-            System.arraycopy(buffer, 0, fileBuffer, fileBufferIndex, read);
-            fileBufferIndex = fileBufferIndex + read;
-
-        }
-        List<String> parts = getParts(fileBuffer, fileBufferIndex);
-        for (String part : parts) {
-            int splitterPos = part.indexOf("=");
-            String key = part.substring(0, splitterPos);
-            String value = part.substring(splitterPos + 1);
-            env.put(key, value);
-        }
-
-        return env;
-    }
-
-    /**
-     * Split a char array, where items are separated by a null into into a list
-     * of strings
-     */
-    private List<String> getParts(char[] nullSeparatedBuffer, int bufferLength) {
-        int maxLength = Math.min(nullSeparatedBuffer.length, bufferLength);
-        List<String> parts = new ArrayList<String>();
-
-        int lastStart = 0;
-        for (int i = 0; i < maxLength; i++) {
-            if (nullSeparatedBuffer[i] == '\0') {
-                String string = new String(nullSeparatedBuffer, lastStart, (i - lastStart));
-                parts.add(string);
-                lastStart = i + 1;
-            }
-        }
-        return parts;
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/models/InfoBuilderFactory.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/models/InfoBuilderFactory.java	Mon Jan 30 10:30:19 2017 -0500
@@ -38,9 +38,7 @@
 
 import com.redhat.thermostat.common.portability.ProcessUserInfoBuilder;
 import com.redhat.thermostat.common.portability.UserNameUtil;
-import com.redhat.thermostat.backend.system.internal.linux.LinuxInfoBuilderFactory;
-import com.redhat.thermostat.backend.system.internal.windows.WindowsInfoBuilderFactory;
-import com.redhat.thermostat.shared.config.OS;
+import com.redhat.thermostat.backend.system.internal.InfoBuilderFactoryImpl;
 import com.redhat.thermostat.storage.core.WriterID;
 
 /**
@@ -48,7 +46,7 @@
  */
 public interface InfoBuilderFactory {
 
-    static InfoBuilderFactory INSTANCE = OS.IS_UNIX ? new LinuxInfoBuilderFactory() : new WindowsInfoBuilderFactory();
+    static InfoBuilderFactory INSTANCE = new InfoBuilderFactoryImpl();
 
     public HostInfoBuilder createHostInfoBuilder(final WriterID writerID);
 
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsHostInfoBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.common.portability.PortableHost;
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.common.portability.PortableHostImpl;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.HostInfo;
-
-/**
- * Build Host information via Windows helper classes
- */
-class WindowsHostInfoBuilderImpl implements HostInfoBuilder {
-
-    private final WriterID writerID;
-    private final PortableHost helper;
-
-    WindowsHostInfoBuilderImpl(final WriterID writerID) {
-        this(writerID, PortableHostImpl.INSTANCE);
-    }
-
-    WindowsHostInfoBuilderImpl(final WriterID writerID, PortableHost helper) {
-        this.writerID = writerID;
-        this.helper = helper;
-    }
-
-    @Override
-    public HostInfo build() {
-        String wId = writerID.getWriterID();
-        return new HostInfo(wId,
-                helper.getHostName(),
-                helper.getOSName(),
-                helper.getOSVersion(),
-                helper.getCPUModel(),
-                helper.getCPUCount(),
-                helper.getTotalMemory());
-    }
-}
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsInfoBuilderFactory.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.common.portability.ProcessUserInfo;
-import com.redhat.thermostat.common.portability.ProcessUserInfoBuilder;
-import com.redhat.thermostat.common.portability.UserNameUtil;
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.backend.system.internal.models.InfoBuilderFactory;
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import com.redhat.thermostat.storage.core.WriterID;
-
-/**
- * Allows callers to access Windows-specific builders portably
- */
-public class WindowsInfoBuilderFactory implements InfoBuilderFactory {
-
-    public WindowsInfoBuilderFactory() {
-    }
-
-    public HostInfoBuilder createHostInfoBuilder(final WriterID writerID) {
-        return new WindowsHostInfoBuilderImpl(writerID);
-    }
-
-    public ProcessEnvironmentBuilder createProcessEnvironmentBuilder() {
-        return new WindowsProcessEnvironmentBuilderImpl();
-    }
-
-    public ProcessUserInfoBuilder createProcessUserInfoBuilder(final UserNameUtil userNameUtil) {
-        return ProcessUserInfo.createBuilder(null, userNameUtil);
-    }
-}
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/windows/WindowsProcessEnvironmentBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import com.redhat.thermostat.common.portability.PortableProcess;
-import com.redhat.thermostat.common.portability.PortableProcessImpl;
-
-import java.util.Map;
-
-/**
- * Build process environment information via Windows helper classes
- */
-class WindowsProcessEnvironmentBuilderImpl implements ProcessEnvironmentBuilder {
-
-    private final PortableProcess helper;
-
-    WindowsProcessEnvironmentBuilderImpl() {
-        this(PortableProcessImpl.INSTANCE);
-    }
-
-    WindowsProcessEnvironmentBuilderImpl(PortableProcess wh) {
-        helper = wh;
-    }
-
-    @Override
-    public Map<String, String> build(int pid) {
-        return helper.getEnvironment(pid);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,92 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.common.portability.PortableHost;
+import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
+import com.redhat.thermostat.shared.config.OS;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.model.HostInfo;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class HostInfoBuilderTest {
+
+    private WriterID writerId;
+    private PortableHost helper;
+
+    @Before
+    public void setup() {
+        writerId = mock(WriterID.class);
+        helper = mock(PortableHost.class);
+        when(helper.getHostName()).thenReturn("testhost");
+        when(helper.getOSName()).thenReturn("testos");
+        when(helper.getOSVersion()).thenReturn("testversion");
+        when(helper.getCPUModel()).thenReturn("testcpu");
+        when(helper.getCPUCount()).thenReturn(4567);
+        when(helper.getTotalMemory()).thenReturn(9876L);
+    }
+
+    // TODO - This test currently fails on Windows because the helper DLL isn't on the execution path
+    @Test
+    @Ignore
+    public void testSimpleBuild() {
+        Assume.assumeTrue(OS.IS_WINDOWS);
+        HostInfo info = new HostInfoBuilderImpl(writerId).build();
+        assertNotNull(info);
+    }
+
+    @Test
+    public void testGetInfo() {
+        final HostInfoBuilder ib = new HostInfoBuilderImpl(writerId, helper);
+        final HostInfo hi = ib.build();
+        assertEquals("testhost",hi.getHostname());
+        assertEquals("testos", hi.getOsName());
+        assertEquals("testcpu", hi.getCpuModel());
+        assertEquals("testversion", hi.getOsKernel());
+        assertEquals(4567, hi.getCpuCount());
+        assertEquals(9876L, hi.getTotalMemory());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/InfoBuilderFactoryTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,64 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
+import com.redhat.thermostat.backend.system.internal.models.InfoBuilderFactory;
+import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class InfoBuilderFactoryTest {
+
+    @Test
+    public void testCreateHostInfoBuilder() {
+        final InfoBuilderFactory builder = new InfoBuilderFactoryImpl();
+        final HostInfoBuilder hib = builder.createHostInfoBuilder(null);
+        assertNotNull(hib);
+        assertTrue(hib instanceof HostInfoBuilderImpl);
+    }
+
+    @Test
+    public void testCreateProcessEnvironmentBuilder() {
+        final InfoBuilderFactory builder = new InfoBuilderFactoryImpl();
+        final ProcessEnvironmentBuilder hib = builder.createProcessEnvironmentBuilder();
+        assertNotNull(hib);
+        assertTrue(hib instanceof ProcessEnvironmentBuilderImpl);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,105 @@
+/*
+ * 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.backend.system.internal;
+
+import com.redhat.thermostat.common.portability.PortableProcess;
+import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
+import com.redhat.thermostat.shared.config.OS;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * test windows process env builder
+ */
+public class ProcessEnvironmentBuilderTest {
+
+    private PortableProcess whelp;
+
+    private static final int FAKE_PID = 4567;
+    private static final String PATH_KEY = "PATH";
+    private static final String FAKE_PATH = "testpath";
+
+    private static final Map<String,String> goodMap = new HashMap<>();
+
+    @Before
+    public void setup() {
+        whelp = mock(PortableProcess.class);
+        goodMap.put(PATH_KEY, FAKE_PATH);
+        when(whelp.getEnvironment(anyInt())).thenReturn(null);
+        when(whelp.getEnvironment(eq(FAKE_PID))).thenReturn(goodMap);
+    }
+
+    // TODO - This test currently fails on Windows because the helper DLL isn't on the execution path
+    @Test
+    @Ignore
+    public void testSimpleBuild() {
+        Assume.assumeTrue(OS.IS_WINDOWS);
+        final Map<String,String> info = new ProcessEnvironmentBuilderImpl().build(FAKE_PID);
+        assertNotNull(info);
+    }
+
+    @Test
+    public void testGetInfoFromGoodPid() {
+        final ProcessEnvironmentBuilder ib = new ProcessEnvironmentBuilderImpl(whelp);
+        final Map<String,String> info  = ib.build(FAKE_PID);
+        assertFalse(info.isEmpty());
+        assertTrue(info.containsKey(PATH_KEY));
+        assertEquals(FAKE_PATH, info.get(PATH_KEY));
+    }
+
+    @Test
+    public void testGetInfoFromBadPid() {
+        final ProcessEnvironmentBuilder ib = new ProcessEnvironmentBuilderImpl(whelp);
+        final Map<String,String> info  = ib.build(FAKE_PID+1);
+        assertTrue(info == null || info.isEmpty());
+    }
+}
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/DistributionInformationTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +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.backend.system.internal.linux;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.util.logging.Handler;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.shared.config.OS;
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-
-public class DistributionInformationTest {
-    
-    private Logger logger;
-    private TestLogHandler handler;
-    
-    @Before
-    public void setup() {
-        setupTestLogger();
-    }
-    
-    @After
-    public void tearDown() {
-        if (handler != null) {
-            logger.removeHandler(handler);
-            handler = null;
-        }
-    }
-    
-    private void setupTestLogger() {
-        logger = Logger.getLogger("com.redhat.thermostat");
-        handler = new TestLogHandler();
-        logger.addHandler(handler);
-    }
-    
-    /*
-     * Verifies that no warning gets logged if EtcOsRelease fails, but
-     * LsbRelease works. Since LsbRelease is the fallback, all is well.
-     * 
-     * see: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1628
-     */
-    @Test
-    public void testNoWarningLoggedOnFallback() {
-        // verify preconditions
-        assertFalse(handler.isEtcOsReleaseLogged());
-        assertTestHandlerRegistered();
-        
-        // Default LSB release
-        LsbRelease lsbRelease = new LsbRelease();
-        // EtcOsRelease with non existent file
-        EtcOsRelease etcOsRelease = new EtcOsRelease(EtcOsReleaseTest.NOT_EXISTING_OS_RELEASE_FILE);
-        DistributionInformation.get(etcOsRelease, lsbRelease);
-        assertFalse(handler.isEtcOsReleaseLogged());
-    }
-    
-    /*
-     * Verifies that a warning gets logged if os-release and lsb_release both
-     * fail.
-     * 
-     * see: http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1628
-     */
-    @Test
-    public void testWarningLoggedIfBothFail() {
-        // verify preconditions
-        assertFalse(handler.isEtcOsReleaseLogged());
-        assertFalse(handler.isLsbReleaseLogged());
-        assertTestHandlerRegistered();
-        
-        // both etc-os-release and lsb-release don't exist for this test
-        EtcOsRelease etcOsRelease = new EtcOsRelease(EtcOsReleaseTest.NOT_EXISTING_OS_RELEASE_FILE);
-        LsbRelease lsbRelease = new LsbRelease(LsbReleaseTest.NOT_EXISTING_LSB_RELEASE);
-        
-        DistributionInformation info = DistributionInformation.get(etcOsRelease, lsbRelease);
-        assertFalse(handler.isEtcOsReleaseLogged());
-        assertTrue(handler.isLsbReleaseLogged());
-        assertNotNull(info);
-        assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
-        assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
-    }
-    
-    @Test
-    public void verifyFallbackToLsbWhenEtcOsReturnsUnknown() throws IOException {
-        EtcOsRelease mockEtcOsRelease = mock(EtcOsRelease.class);
-        DistributionInformation mockDistro = mock(DistributionInformation.class);
-        when(mockEtcOsRelease.getDistributionInformation()).thenReturn(mockDistro);
-        when(mockDistro.getName()).thenReturn(DistributionInformation.UNKNOWN_NAME);
-        when(mockDistro.getVersion()).thenReturn(DistributionInformation.UNKNOWN_VERSION);
-        
-        LsbRelease mockLsbRelease = mock(LsbRelease.class);
-        DistributionInformation mockLsbDistro = mock(DistributionInformation.class);
-        when(mockLsbRelease.getDistributionInformation()).thenReturn(mockLsbDistro);
-        
-        DistributionInformation info = DistributionInformation.get(mockEtcOsRelease, mockLsbRelease);
-        assertSame("Expected lsb info to be used since etc returns unknown",
-                   mockLsbDistro, info);
-    }
-
-    private void assertTestHandlerRegistered() {
-        assertNotNull(logger);
-        boolean testLogHandlerRegistered = false;
-        for (Handler h: logger.getHandlers()) {
-            if (h instanceof TestLogHandler) {
-                testLogHandlerRegistered = true;
-            }
-        }
-        assertTrue(testLogHandlerRegistered);
-    }
-
-    @Test
-    public void testName() {
-        if (OS.IS_LINUX) {
-            DistributionInformation info = DistributionInformation.get();
-            String name = info.getName();
-            assertNotNull(name);
-            assertTrue(name.length() > 0);
-            assertFalse(name.startsWith(":"));
-            assertFalse(name.equals(DistributionInformation.UNKNOWN_NAME));
-        }
-    }
-
-    @Test
-    public void testVersion() {
-        if (OS.IS_LINUX) {
-            DistributionInformation info = DistributionInformation.get();
-            String version = info.getVersion();
-            assertNotNull(version);
-            assertTrue(version.length()> 0);
-            assertFalse(version.startsWith(":"));
-            assertFalse(version.equals(DistributionInformation.UNKNOWN_VERSION));
-        }
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/EtcOsReleaseTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +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.backend.system.internal.linux;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.UUID;
-
-import com.redhat.thermostat.backend.system.internal.linux.DistributionInformation;
-import com.redhat.thermostat.backend.system.internal.linux.EtcOsRelease;
-import com.redhat.thermostat.shared.config.OS;
-import org.junit.Assume;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.internal.test.Bug;
-
-public class EtcOsReleaseTest {
-    
-    static final String NOT_EXISTING_OS_RELEASE_FILE = "/thermostat-os-release-testing-"
-            + UUID.randomUUID();
-
-    @Test
-    public void testName() throws IOException, InterruptedException {
-        BufferedReader reader = new BufferedReader(new StringReader("NAME=\"Name\"\n"));
-        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
-        assertEquals("Name", info.getName());
-    }
-
-
-    @Test
-    public void testVersion() throws IOException {
-        BufferedReader reader = new BufferedReader(new StringReader("VERSION=\"Version\"\n"));
-        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
-        assertEquals("Version", info.getVersion());
-    }
-
-    @Bug(id="981",
-        summary="DistributionInformationTest fails on OpenSUSE Linux 12.1",
-        url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=981")
-    @Test
-    public void testFormattedOutput() throws IOException {
-        String output =
-            "NAME=openSUSE\n" +
-            "VERSION = 12.1 (Asparagus)\n" +
-            "VERSION_ID=\"12.1\"\n" +
-            "PRETTY_NAME=\"openSUSE 12.1 (Asparagus) (x86_64)\"\n" +
-            "ID=opensuse";
-        BufferedReader reader = new BufferedReader(new StringReader(output));
-        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
-
-        assertEquals("openSUSE", info.getName());
-        assertEquals("12.1 (Asparagus)", info.getVersion());
-    }
-    
-    /**
-     * DistributionInformation falls back on LSB when /etc/os-release contains
-     * inconclusive content (empty in this case). It should not return some
-     * info as "Linux".
-     * 
-     * @throws IOException
-     */
-    @Test
-    public void testEmpty() throws IOException {
-        String output = "";
-        BufferedReader reader = new BufferedReader(new StringReader(output));
-        
-        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
-        assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
-        assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
-    }
-    
-    @Test
-    public void getDistributionInformationThrowsIOExceptionIfFileNotThere() {
-        Assume.assumeTrue(OS.IS_UNIX);
-        EtcOsRelease etcOsRelease = new EtcOsRelease(NOT_EXISTING_OS_RELEASE_FILE);
-        try {
-            etcOsRelease.getDistributionInformation();
-            fail("Should have thrown IOException, since file is not there!");
-        } catch (IOException e) {
-            // pass
-            String message = e.getMessage();
-            assertTrue(message.contains("/thermostat-os-release-testing-"));
-            assertTrue(message.contains("(No such file or directory)"));
-        }
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/HostInfoBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +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.backend.system.internal.linux;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.net.InetAddress;
-
-import com.redhat.thermostat.shared.config.OS;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.backend.system.internal.linux.HostInfoBuilderImpl.HostCpuInfo;
-import com.redhat.thermostat.backend.system.internal.linux.HostInfoBuilderImpl.HostMemoryInfo;
-import com.redhat.thermostat.backend.system.internal.linux.HostInfoBuilderImpl.HostOsInfo;
-import com.redhat.thermostat.common.Size;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.HostInfo;
-
-public class HostInfoBuilderTest {
-
-    final int KILOBYTES_TO_BYTES = 1024;
-    private WriterID writerId;
-    
-    @Before
-    public void setup() {
-        writerId = mock(WriterID.class);
-    }
-
-    @Test
-    public void testSimpleBuild() {
-        Assume.assumeTrue(OS.IS_UNIX);
-        HostInfo info = new HostInfoBuilderImpl(new ProcDataSource(), writerId).build();
-        assertNotNull(info);
-    }
-
-    @Test
-    public void testCpuInfo() throws IOException {
-        String cpuInfoString =
-                "processor: 1\n" +
-                "model name: Test Model\n" +
-                "processor: 0\n" +
-                "model name: Test Model\n";
-
-        StringReader cpuInfoReader = new StringReader(cpuInfoString);
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getCpuInfoReader()).thenReturn(cpuInfoReader);
-
-        HostCpuInfo cpuInfo = new HostInfoBuilderImpl(dataSource, writerId).getCpuInfo();
-        assertEquals(2, cpuInfo.count);
-        assertEquals("Test Model", cpuInfo.model);
-        verify(dataSource).getCpuInfoReader();
-    }
-
-    @Test
-    public void testMemoryInfo() throws IOException {
-        String memoryInfoString =
-                "MemTotal: 12345 kB";
-
-        StringReader memoryInfoReader = new StringReader(memoryInfoString);
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getMemInfoReader()).thenReturn(memoryInfoReader);
-
-        HostMemoryInfo memoryInfo = new HostInfoBuilderImpl(dataSource, writerId).getMemoryInfo();
-        assertNotNull(memoryInfo);
-        assertEquals(Size.bytes(12345 * KILOBYTES_TO_BYTES), memoryInfo.totalMemory);
-        verify(dataSource).getMemInfoReader();
-
-    }
-
-    @Test
-    public void testOsInfo() {
-        DistributionInformation distroInfo = new DistributionInformation("distro-name", "distro-version");
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        HostOsInfo osInfo = new HostInfoBuilderImpl(dataSource, writerId).getOsInfo(distroInfo);
-        assertEquals("distro-name distro-version", osInfo.distribution);
-        assertEquals(System.getProperty("os.name") + " " + System.getProperty("os.version"), osInfo.kernel);
-    }
-
-    @Test
-    public void testHostname() {
-
-        InetAddress address = mock(InetAddress.class);
-        when(address.getCanonicalHostName()).thenReturn("test-hostname");
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-
-        String name = new HostInfoBuilderImpl(dataSource, writerId).getHostName(address);
-        assertEquals("test-hostname", name);
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/LsbReleaseTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +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.backend.system.internal.linux;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.UUID;
-
-import com.redhat.thermostat.backend.system.internal.linux.DistributionInformation;
-import com.redhat.thermostat.backend.system.internal.linux.LsbRelease;
-import com.redhat.thermostat.shared.config.OS;
-import org.junit.Assume;
-import org.junit.Test;
-
-public class LsbReleaseTest {
-    
-    static final String NOT_EXISTING_LSB_RELEASE = "lsb_release-"
-            + UUID.randomUUID();
-
-    @Test
-    public void testName() throws IOException, InterruptedException {
-        Assume.assumeTrue(OS.IS_UNIX);
-        BufferedReader reader = new BufferedReader(new StringReader("Distributor ID: Name"));
-        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
-        assertEquals("Name", info.getName());
-    }
-
-    @Test
-    public void testVersion() throws IOException {
-        Assume.assumeTrue(OS.IS_UNIX);
-        BufferedReader reader = new BufferedReader(new StringReader("Release: Version"));
-        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
-        assertEquals("Version", info.getVersion());
-    }
-    
-    @Test
-    public void getDistributionInformationThrowsIOExceptionIfScriptNotThere() {
-        Assume.assumeTrue(OS.IS_UNIX);
-        LsbRelease lsbRelease = new LsbRelease(NOT_EXISTING_LSB_RELEASE);
-        try {
-            lsbRelease.getDistributionInformation();
-            fail("Should have thrown IOException, since file is not there!");
-        } catch (IOException e) {
-            // pass
-            String message = e.getMessage();
-            assertTrue(message.contains("Cannot run program \"lsb_release-"));
-            assertTrue(message.contains("No such file or directory"));
-        }
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/ProcessEnvironmentBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +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.backend.system.internal.linux;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Map;
-import java.util.Random;
-
-import com.redhat.thermostat.shared.config.OS;
-import org.junit.Assume;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.testutils.TestUtils;
-
-public class ProcessEnvironmentBuilderTest {
-
-    private final Random r = new Random();
-
-    @Test
-    public void testBasicBuild() {
-        Assume.assumeTrue(OS.IS_UNIX);
-        ProcDataSource dataSource = new ProcDataSource();
-        Map<String, String> result = new ProcessEnvironmentBuilderImpl(dataSource).build(TestUtils.getProcessId());
-        assertNotNull(result);
-        assertFalse(result.isEmpty());
-        assertTrue(result.containsKey("USER"));
-    }
-
-    @Test
-    public void testCustomEnvironment() throws IOException {
-        byte[] data = ("USER=test\000HOME=house\000").getBytes();
-
-        Reader r = new InputStreamReader(new ByteArrayInputStream(data));
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r);
-
-        Map<String, String> result = new ProcessEnvironmentBuilderImpl(dataSource).build(0);
-
-        verify(dataSource).getEnvironReader(eq(0));
-        assertEquals("test", result.get("USER"));
-        assertEquals("house", result.get("HOME"));
-    }
-
-    @Test
-    public void testLargeRandomEnvironment() throws IOException {
-        int TEST_ENV_SIZE = 1024 * 1024;
-        byte[] data = new byte[TEST_ENV_SIZE];
-        int currentPosition = 0;
-        do {
-            byte[] key = generateRandomBytes();
-            byte[] value = generateRandomBytes();
-            if (currentPosition + key.length + value.length + 2 >= data.length) {
-                break;
-            }
-            System.arraycopy(key, 0, data, currentPosition, key.length);
-            currentPosition += key.length;
-            data[currentPosition] = (byte) '=';
-            currentPosition++;
-            System.arraycopy(value, 0, data, currentPosition, value.length);
-            currentPosition += value.length;
-            data[currentPosition] = 0x00;
-            currentPosition++;
-        } while (true);
-        Reader r = new InputStreamReader(new ByteArrayInputStream(data, 0, currentPosition));
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getEnvironReader(any(Integer.class))).thenReturn(r);
-
-        Map<String, String> result = new ProcessEnvironmentBuilderImpl(dataSource).build(0);
-
-        verify(dataSource).getEnvironReader(eq(0));
-        assertNotNull(result);
-    }
-
-    private byte[] generateRandomBytes() {
-        byte start = (byte) 'a';
-        byte end = (byte) 'z' + 1;
-
-        byte[] alphabet = new byte[end - start];
-        for (int i = 0; i < (end-start); i++) {
-            alphabet[i] = (byte) (i + start);
-        }
-        int size = r.nextInt(15) + 10;
-        byte[] result = new byte[size];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = alphabet[r.nextInt(alphabet.length)];
-        }
-        return result;
-    }
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/linux/TestLogHandler.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +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.backend.system.internal.linux;
-
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
-/*
- * Test log handler used for DistributionInformation log testing.
- */
-public class TestLogHandler extends Handler {
-    
-    private boolean etcOsReleaseLogged;
-    private boolean lsbReleaseLogged;
-    private static final String EXPECTED_OS_RELEASE_FAIL_MSG =
-            "unable to use os-release";
-    private static final String EXPECTED_LSB_RELEASE_FAIL_MSG =
-            "unable to use os-release AND lsb_release";
-    
-    @Override
-    public void publish(LogRecord record) {
-        String logMessage = record.getMessage();
-        if (record.getLevel().intValue() >= Level.WARNING.intValue() && 
-                logMessage.equals(EXPECTED_OS_RELEASE_FAIL_MSG)) {
-            etcOsReleaseLogged = true;
-        };
-        if (record.getLevel().intValue() >= Level.WARNING.intValue() &&
-                logMessage.equals(EXPECTED_LSB_RELEASE_FAIL_MSG)) {
-            lsbReleaseLogged = true;
-        }
-    }
-
-    @Override
-    public void flush() {
-        // nothing
-    }
-
-    @Override
-    public void close() throws SecurityException {
-        // nothing
-    }
-    
-    boolean isEtcOsReleaseLogged() {
-        return etcOsReleaseLogged;
-    }
-    
-    boolean isLsbReleaseLogged() {
-        return lsbReleaseLogged;
-    }
-    
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsHostInfoBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.common.portability.PortableHost;
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.shared.config.OS;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.HostInfo;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class WindowsHostInfoBuilderTest {
-
-    private WriterID writerId;
-    private PortableHost helper;
-
-    @Before
-    public void setup() {
-        writerId = mock(WriterID.class);
-        helper = mock(PortableHost.class);
-        when(helper.getHostName()).thenReturn("testhost");
-        when(helper.getOSName()).thenReturn("testos");
-        when(helper.getOSVersion()).thenReturn("testversion");
-        when(helper.getCPUModel()).thenReturn("testcpu");
-        when(helper.getCPUCount()).thenReturn(4567);
-        when(helper.getTotalMemory()).thenReturn(9876L);
-    }
-
-    // TODO - This test currently fails on Windows because the helper DLL isn't on the execution path
-    @Test
-    @Ignore
-    public void testSimpleBuild() {
-        Assume.assumeTrue(OS.IS_WINDOWS);
-        HostInfo info = new WindowsHostInfoBuilderImpl(writerId).build();
-        assertNotNull(info);
-    }
-
-    @Test
-    public void testGetInfo() {
-        final HostInfoBuilder ib = new WindowsHostInfoBuilderImpl(writerId, helper);
-        final HostInfo hi = ib.build();
-        assertEquals("testhost",hi.getHostname());
-        assertEquals("testos", hi.getOsName());
-        assertEquals("testcpu", hi.getCpuModel());
-        assertEquals("testversion", hi.getOsKernel());
-        assertEquals(4567, hi.getCpuCount());
-        assertEquals(9876L, hi.getTotalMemory());
-    }
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsInfoBuilderFactoryTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.backend.system.internal.models.HostInfoBuilder;
-import com.redhat.thermostat.backend.system.internal.models.InfoBuilderFactory;
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import org.junit.Test;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class WindowsInfoBuilderFactoryTest {
-
-    @Test
-    public void testCreateHostInfoBuilder() {
-        final InfoBuilderFactory builder = new WindowsInfoBuilderFactory();
-        final HostInfoBuilder hib = builder.createHostInfoBuilder(null);
-        assertNotNull(hib);
-        assertTrue(hib instanceof WindowsHostInfoBuilderImpl);
-    }
-
-    @Test
-    public void testCreateProcessEnvironmentBuilder() {
-        final InfoBuilderFactory builder = new WindowsInfoBuilderFactory();
-        final ProcessEnvironmentBuilder hib = builder.createProcessEnvironmentBuilder();
-        assertNotNull(hib);
-        assertTrue(hib instanceof WindowsProcessEnvironmentBuilderImpl);
-    }
-}
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/windows/WindowsProcessEnvironmentBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +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.backend.system.internal.windows;
-
-import com.redhat.thermostat.common.portability.PortableProcess;
-import com.redhat.thermostat.backend.system.internal.models.ProcessEnvironmentBuilder;
-import com.redhat.thermostat.shared.config.OS;
-
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * test windows process env builder
- */
-public class WindowsProcessEnvironmentBuilderTest {
-
-    private PortableProcess whelp;
-
-    private static final int FAKE_PID = 4567;
-    private static final String PATH_KEY = "PATH";
-    private static final String FAKE_PATH = "testpath";
-
-    private static final Map<String,String> goodMap = new HashMap<>();
-
-    @Before
-    public void setup() {
-        whelp = mock(PortableProcess.class);
-        goodMap.put(PATH_KEY, FAKE_PATH);
-        when(whelp.getEnvironment(anyInt())).thenReturn(null);
-        when(whelp.getEnvironment(eq(FAKE_PID))).thenReturn(goodMap);
-    }
-
-    // TODO - This test currently fails on Windows because the helper DLL isn't on the execution path
-    @Test
-    @Ignore
-    public void testSimpleBuild() {
-        Assume.assumeTrue(OS.IS_WINDOWS);
-        final Map<String,String> info = new WindowsProcessEnvironmentBuilderImpl().build(FAKE_PID);
-        assertNotNull(info);
-    }
-
-    @Test
-    public void testGetInfoFromGoodPid() {
-        final ProcessEnvironmentBuilder ib = new WindowsProcessEnvironmentBuilderImpl(whelp);
-        final Map<String,String> info  = ib.build(FAKE_PID);
-        assertFalse(info.isEmpty());
-        assertTrue(info.containsKey(PATH_KEY));
-        assertEquals(FAKE_PATH, info.get(PATH_KEY));
-    }
-
-    @Test
-    public void testGetInfoFromBadPid() {
-        final ProcessEnvironmentBuilder ib = new WindowsProcessEnvironmentBuilderImpl(whelp);
-        final Map<String,String> info  = ib.build(FAKE_PID+1);
-        assertTrue(info == null || info.isEmpty());
-    }
-}
--- a/vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/LinuxProcessStatusInfoBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +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.vm.cpu.agent.internal;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Scanner;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Extract status information about the process from /proc/. This is what tools
- * like {@code ps} and {@code top} use.
- *
- * @see {@code proc(5)}
- */
-public class LinuxProcessStatusInfoBuilderImpl implements ProcessStatusInfoBuilder{
-
-    private static final Logger logger = LoggingUtils.getLogger(LinuxProcessStatusInfoBuilderImpl.class);
-
-    private final ProcDataSource dataSource;
-
-    public LinuxProcessStatusInfoBuilderImpl(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public ProcessStatusInfo build(int pid) {
-        try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) {
-            return build(reader);
-        } catch (IOException e) {
-            logger.log(Level.FINE, "Unable to read stat info for: " + pid);
-        }
-
-        return null;
-    }
-
-    private ProcessStatusInfo build(Reader r) throws IOException {
-
-        int pid = -1;
-        long utime = -1;
-        long stime = -1;
-
-        Scanner scanner = null;
-
-        /* TODO map these (effectively c) data types to java types more sanely */
-
-        try (BufferedReader reader = new BufferedReader(r)) {
-            String statusLine = reader.readLine();
-
-            /* be prepared for process names like '1 ) 2 3 4 foo 5' */
-
-            scanner = new Scanner(statusLine);
-            pid = scanner.nextInt();
-            scanner.close();
-
-            int execEndNamePos = statusLine.lastIndexOf(')');
-
-            String cleanStatusLine = statusLine.substring(execEndNamePos + 1);
-
-            scanner = new Scanner(cleanStatusLine);
-            /* state = */scanner.next();
-            /* ppid = */scanner.nextInt();
-            /* pgrp = */scanner.nextInt();
-            /* session = */scanner.nextInt();
-            /* tty_nr = */scanner.nextInt();
-            /* tpgid = */scanner.nextInt();
-            /* flags = */scanner.nextInt();
-            /* minflt = */scanner.nextLong();
-            /* cminflt = */scanner.nextLong();
-            /* majflt = */scanner.nextLong();
-            /* cmajflt = */scanner.nextLong();
-            utime = scanner.nextLong();
-            stime = scanner.nextLong();
-            scanner.close();
-        }
-
-        return new ProcessStatusInfo(pid, utime, stime);
-
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/ProcessStatusInfoBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -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.vm.cpu.agent.internal;
+
+import com.redhat.thermostat.common.portability.PortableProcessImpl;
+import com.redhat.thermostat.common.portability.PortableProcessStat;
+
+/**
+ * Extract status information about the process
+ */
+public class ProcessStatusInfoBuilderImpl implements ProcessStatusInfoBuilder {
+
+    ProcessStatusInfoBuilderImpl() {
+    }
+
+    public ProcessStatusInfo build(int pid) {
+
+        final PortableProcessStat info =  PortableProcessImpl.getInstance().getProcessStat(pid);
+
+        return info != null ? new ProcessStatusInfo(pid, info.getUserTime(), info.getKernelTime()) : null;
+    }
+
+}
+
--- a/vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuBackend.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuBackend.java	Mon Jan 30 10:30:19 2017 -0500
@@ -89,12 +89,9 @@
             long ticksPerSecond = SysConf.getClockTicksPerSecond();
             ProcDataSource source = new ProcDataSource();
             int numCpus = getCpuCount(source);
-            ProcessStatusInfoBuilder PSIBuilder = OS.IS_LINUX ? new LinuxProcessStatusInfoBuilderImpl(source) : new WindowsProcessStatusInfoBuilderImpl();
+            ProcessStatusInfoBuilder PSIBuilder = new ProcessStatusInfoBuilderImpl();
             builder = new VmCpuStatBuilder(clock, numCpus, ticksPerSecond, PSIBuilder, id);
             this.dao = dao;
-            if (OS.IS_WINDOWS) {
-                LOGGER.log(Level.WARNING, "VmCpu backend is not yet ported to Windows");
-            }
         }
 
         @Override
@@ -110,18 +107,18 @@
         }
 
         private int getCpuCount(ProcDataSource dataSource) {
-            return OS.IS_WINDOWS ? getWindowsCpuCount() : getLinuxCpuCount(dataSource);
+            return OS.IS_LINUX ? getLinuxCpuCount(dataSource) : getCpuCount();
         }
 
-        private int getWindowsCpuCount() {
-            return PortableHostImpl.INSTANCE.getCPUCount();
+        private int getCpuCount() {
+            return PortableHostImpl.getInstance().getCPUCount();
         }
 
         private int getLinuxCpuCount(ProcDataSource dataSource) {
             final String KEY_PROCESSOR_ID = "processor";
             int cpuCount = 0;
             try (BufferedReader bufferedReader = new BufferedReader(dataSource.getCpuInfoReader())) {
-                String line = null;
+                String line;
                 while ((line = bufferedReader.readLine()) != null) {
                     if (line.startsWith(KEY_PROCESSOR_ID)) {
                         cpuCount++;
--- a/vm-cpu/agent/src/main/java/com/redhat/thermostat/vm/cpu/agent/internal/WindowsProcessStatusInfoBuilderImpl.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +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.vm.cpu.agent.internal;
-
-import com.redhat.thermostat.common.portability.PortableProcessImpl;
-import com.redhat.thermostat.common.portability.PortableProcessStat;
-
-/**
- * Extract status information about the process
- */
-public class WindowsProcessStatusInfoBuilderImpl implements ProcessStatusInfoBuilder {
-
-    WindowsProcessStatusInfoBuilderImpl() {
-    }
-
-    public ProcessStatusInfo build(int pid) {
-
-        final PortableProcessStat info =  PortableProcessImpl.INSTANCE.getProcessStat(pid);
-
-        return new ProcessStatusInfo(pid, info.getUserTime(), info.getKernelTime());
-    }
-
-}
-
--- a/vm-cpu/agent/src/test/java/com/redhat/thermostat/vm/cpu/agent/internal/LinuxProcessStatusInfoBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +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.vm.cpu.agent.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-
-public class LinuxProcessStatusInfoBuilderTest {
-
-    @Test
-    public void testSimpleProcessStatus() {
-        ProcDataSource dataSource = new ProcDataSource();
-        ProcessStatusInfo stat = new LinuxProcessStatusInfoBuilderImpl(dataSource).build(1);
-        assertNotNull(stat);
-    }
-
-    @Test
-    public void testKnownProcessStatus() throws IOException {
-        final int PID = 10363;
-        String PROCESS_NAME = "(bash)";
-        String STATE = "S";
-        String PPID = "1737";
-        String PROCESS_GROUP_ID = "10363";
-        String SESSION_ID = "10363";
-        String TTY_NUMBER = "34817";
-        String TTY_PROCESS_GROUP_ID = "11404";
-        String FLAGS_WORD = "4202496";
-        String MINOR_FAULTS = "8093";
-        String MINOR_FAULTS_CHILDREN = "607263";
-        String MAJOR_FAULTS = "1";
-        String MAJOR_FAULTS_CHILDREN = "251";
-        final long USER_TIME_TICKS = 21;
-        final long KERNEL_TIME_TICKS = 7;
-        final long USER_TIME_CHILDREN = 10;
-        String KERNEL_TIME_CHILDREN = "1000";
-        String PRIORITY = "20";
-        String statString = "" +
-                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
-                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
-                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
-                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
-                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
-                KERNEL_TIME_CHILDREN + " " + PRIORITY;
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
-        ProcessStatusInfoBuilder builder = new LinuxProcessStatusInfoBuilderImpl(dataSource);
-        ProcessStatusInfo stat = builder.build(PID);
-
-        verify(dataSource).getStatReader(PID);
-        assertNotNull(stat);
-        assertEquals(PID, stat.getPid());
-        assertEquals(USER_TIME_TICKS, stat.getUserTime());
-        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
-    }
-
-    @Test
-    public void testBadProcessName() throws IOException {
-        final int PID = 10363;
-        String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)";
-        String STATE = "S";
-        String PPID = "1737";
-        String PROCESS_GROUP_ID = "10363";
-        String SESSION_ID = "10363";
-        String TTY_NUMBER = "34817";
-        String TTY_PROCESS_GROUP_ID = "11404";
-        String FLAGS_WORD = "4202496";
-        String MINOR_FAULTS = "8093";
-        String MINOR_FAULTS_CHILDREN = "607263";
-        String MAJOR_FAULTS = "1";
-        String MAJOR_FAULTS_CHILDREN = "251";
-        final long USER_TIME_TICKS = 21;
-        final long KERNEL_TIME_TICKS = 7;
-        final long USER_TIME_CHILDREN = 10;
-        String KERNEL_TIME_CHILDREN = "1000";
-        String PRIORITY = "20";
-        String statString = "" +
-                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
-                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
-                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
-                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
-                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
-                KERNEL_TIME_CHILDREN + " " + PRIORITY;
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
-        ProcessStatusInfoBuilder builder = new LinuxProcessStatusInfoBuilderImpl(dataSource);
-        ProcessStatusInfo stat = builder.build(PID);
-
-        verify(dataSource).getStatReader(PID);
-        assertNotNull(stat);
-        assertEquals(PID, stat.getPid());
-        assertEquals(USER_TIME_TICKS, stat.getUserTime());
-        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
-    }
-
-}
-
--- a/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/LinuxVmIoStatBuilder.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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.vm.io.agent.internal;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.vm.io.common.VmIoStat;
-
-public class LinuxVmIoStatBuilder implements VmIoStatBuilder {
-
-    private final Clock clock;
-    private final ProcIoDataReader ioReader;
-    private final String writerId;
-
-    LinuxVmIoStatBuilder(Clock clock, ProcIoDataReader ioReader, WriterID writerId) {
-        this.clock = clock;
-        this.ioReader = ioReader;
-
-        this.writerId = writerId.getWriterID();
-    }
-
-    public synchronized VmIoStat build(String vmId, Integer pid) {
-        ProcIoData data = ioReader.read(pid);
-        if (data == null) {
-            return null;
-        }
-        long miliTime = clock.getRealTimeMillis();
-        return new VmIoStat(writerId, vmId, miliTime, data.rchar, data.wchar, data.syscr, data.syscw);
-    }
-
-}
--- a/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoData.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +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.vm.io.agent.internal;
-
-public class ProcIoData {
-
-    // This matches the proc file format. The file format is described at:
-    // http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt
-
-    public final long rchar;
-    public final long wchar;
-    public final long syscr;
-    public final long syscw;
-    public final long read_bytes;
-    public final long write_bytes;
-    public final long cancelled_write_bytes;
-
-    public ProcIoData(long rchar, long wchar,
-            long syscr, long syscw,
-            long read_bytes, long write_bytes,
-            long cancelled_write_bytes) {
-        this.rchar = rchar;
-        this.wchar = wchar;
-        this.syscr = syscr;
-        this.syscw = syscw;
-        this.read_bytes = read_bytes;
-        this.write_bytes = write_bytes;
-        this.cancelled_write_bytes = cancelled_write_bytes;
-    }
-
-}
-
--- a/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoDataReader.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +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.vm.io.agent.internal;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * Extract information from {@code /proc/<pid>/io}.
- */
-public class ProcIoDataReader {
-
-    private static final Logger logger = LoggingUtils.getLogger(ProcIoDataReader.class);
-
-    private final ProcDataSource dataSource;
-
-    public ProcIoDataReader(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public ProcIoData read(int pid) {
-        try (BufferedReader reader = new BufferedReader(dataSource.getIoReader(pid))) {
-            return read(reader);
-        } catch (IOException e) {
-            logger.log(Level.FINE, "Unable to read io info for: " + pid);
-        }
-
-        return null;
-    }
-
-    private ProcIoData read(BufferedReader r) throws IOException {
-        // The file format is described at:
-        // http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt
-
-        final int UNKNOWN_VALUE = -1;
-        long rchar = UNKNOWN_VALUE;
-        long wchar = UNKNOWN_VALUE;
-        long syscr = UNKNOWN_VALUE;
-        long syscw = UNKNOWN_VALUE;
-        long read_bytes = UNKNOWN_VALUE;
-        long write_bytes = UNKNOWN_VALUE;
-        long cancelled_write_bytes = UNKNOWN_VALUE;
-
-        String line;
-        while ((line = r.readLine()) != null) {
-            String[] parts = line.split(":");
-            String key = parts[0].trim();
-            String value = parts[1].trim();
-            switch (key) {
-                case "rchar":
-                    rchar = Long.valueOf(value);
-                    break;
-                case "wchar":
-                    wchar = Long.valueOf(value);
-                    break;
-                case "syscr":
-                    syscr = Long.valueOf(value);
-                    break;
-                case "syscw":
-                    syscw = Long.valueOf(value);
-                    break;
-                case "read_bytes":
-                    read_bytes = Long.valueOf(value);
-                    break;
-                case "write_bytes":
-                    write_bytes = Long.valueOf(value);
-                    break;
-                case "cancelled_write_bytes":
-                    cancelled_write_bytes = Long.valueOf(value);
-                    break;
-            }
-        }
-
-        return new ProcIoData(rchar, wchar, syscr, syscw, read_bytes, write_bytes, cancelled_write_bytes);
-    }
-
-}
-
--- a/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackend.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackend.java	Mon Jan 30 10:30:19 2017 -0500
@@ -37,13 +37,11 @@
 package com.redhat.thermostat.vm.io.agent.internal;
 
 import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
 import com.redhat.thermostat.backend.VmListenerBackend;
 import com.redhat.thermostat.backend.VmUpdate;
 import com.redhat.thermostat.backend.VmUpdateListener;
 import com.redhat.thermostat.common.Clock;
 import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.shared.config.OS;
 import com.redhat.thermostat.storage.core.WriterID;
 import com.redhat.thermostat.vm.io.common.Constants;
 import com.redhat.thermostat.vm.io.common.VmIoStat;
@@ -59,8 +57,7 @@
             VmStatusListenerRegistrar registrar, WriterID writerId) {
         this(version,
                 vmIoStatDao,
-                OS.IS_LINUX ? new LinuxVmIoStatBuilder(clock, new ProcIoDataReader(new ProcDataSource()), writerId)
-                        : new WindowsVmIoStatBuilder(clock, writerId),
+                new VmIoStatBuilderImpl(clock, writerId),
                 registrar, writerId);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/VmIoStatBuilderImpl.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.io.agent.internal;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.portability.PortableVmIoStat;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.vm.io.common.VmIoStat;
+
+public class VmIoStatBuilderImpl implements VmIoStatBuilder {
+
+    private final Clock clock;
+    private final String writerId;
+
+    VmIoStatBuilderImpl(Clock clock, WriterID writerId) {
+        this.clock = clock;
+        this.writerId = writerId.getWriterID();
+    }
+
+    public synchronized VmIoStat build(String vmId, Integer pid) {
+
+        PortableVmIoStat data = PortableVmIoStat.build(clock, pid);
+        return (data != null) ? new VmIoStat(writerId, vmId, data.getTimeStamp(), data.getCharactersRead(), data.getCharactersWritten(), data.getReadSyscalls(), data.getWriteSyscalls()) : null;
+    }
+
+}
--- a/vm-io/agent/src/main/java/com/redhat/thermostat/vm/io/agent/internal/WindowsVmIoStatBuilder.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +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.vm.io.agent.internal;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.portability.PortableVmIoStat;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.vm.io.common.VmIoStat;
-
-public class WindowsVmIoStatBuilder implements VmIoStatBuilder {
-
-    private final Clock clock;
-    private final String writerId;
-
-    WindowsVmIoStatBuilder(Clock clock, WriterID writerId) {
-        this.clock = clock;
-        this.writerId = writerId.getWriterID();
-    }
-
-    public synchronized VmIoStat build(String vmId, Integer pid) {
-
-        PortableVmIoStat data = PortableVmIoStat.build(clock, pid);
-        return new VmIoStat(writerId, vmId, data.getTimeStamp(), data.getCharactersRead(), data.getCharactersWritten(), data.getReadSyscalls(), data.getWriteSyscalls());
-    }
-
-}
--- a/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/LinuxVmIoStatBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +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.vm.io.agent.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.vm.io.common.VmIoStat;
-
-public class LinuxVmIoStatBuilderTest {
-
-    private WriterID writerID;
-
-    @Before
-    public void setup() {
-        writerID = mock(WriterID.class);
-    }
-
-    @Test
-    public void testBuilderBuildsNullForUnknownPid() {
-        Clock clock = mock(Clock.class);
-        ProcIoDataReader procDataReader = mock(ProcIoDataReader.class);
-        LinuxVmIoStatBuilder builder = new LinuxVmIoStatBuilder(clock, procDataReader, writerID);
-        VmIoStat result = builder.build("vmId", 0);
-        assertNull(result);
-    }
-
-    @Test
-    public void testBuildWithSufficientInformation() {
-        final int PID = 0;
-
-        int rchar = 1;
-        int wchar = 2;
-        int syscr = 3;
-        int syscw = 4;
-        int read_bytes = 5;
-        int write_bytes = 6;
-        int cancelled_write_bytes = 7;
-
-        final ProcIoData data = new ProcIoData(rchar, wchar, syscr, syscw,
-                read_bytes, write_bytes, cancelled_write_bytes);
-
-        ProcIoDataReader ioReader = mock(ProcIoDataReader.class);
-        when(ioReader.read(PID)).thenReturn(data);
-        Clock clock = mock(Clock.class);
-
-        LinuxVmIoStatBuilder builder = new LinuxVmIoStatBuilder(clock, ioReader, writerID);
-
-        VmIoStat ioData = builder.build("vmId", PID);
-        assertNotNull(ioData);
-        assertEquals(rchar, ioData.getCharactersRead());
-        assertEquals(wchar, ioData.getCharactersWritten());
-        assertEquals(syscr, ioData.getReadSyscalls());
-        assertEquals(syscw, ioData.getWriteSyscalls());
-    }
-
-}
-
--- a/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/ProcIoDataReaderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +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.vm.io.agent.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.portability.linux.ProcDataSource;
-
-public class ProcIoDataReaderTest {
-
-    @Test
-    public void verifyIsParsedCorrectly() throws Exception {
-        final int SOME_PID = 0;
-        String fileContents = "" +
-                "rchar: 19961133\n" +
-                "wchar: 2451715\n" +
-                "syscr: 17880\n" +
-                "syscw: 13870\n" +
-                "read_bytes: 21004288\n" +
-                "write_bytes: 811008\n" +
-                "cancelled_write_bytes: 16384\n";
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getIoReader(SOME_PID)).thenReturn(new StringReader(fileContents));
-
-        ProcIoData parsedData = new ProcIoDataReader(dataSource).read(SOME_PID);
-
-        assertEquals(19961133, parsedData.rchar);
-        assertEquals(2451715, parsedData.wchar);
-        assertEquals(17880, parsedData.syscr);
-        assertEquals(13870, parsedData.syscw);
-        assertEquals(21004288, parsedData.read_bytes);
-        assertEquals(811008, parsedData.write_bytes);
-        assertEquals(16384, parsedData.cancelled_write_bytes);
-
-    }
-}
--- a/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackendTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ b/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/VmIoBackendTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -44,7 +44,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import com.redhat.thermostat.shared.config.OS;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -71,7 +70,7 @@
         registrar = mock(VmStatusListenerRegistrar.class);
 
         WriterID id = mock(WriterID.class);
-        ioStatBuilder = OS.IS_LINUX ? mock(LinuxVmIoStatBuilder.class) : mock(WindowsVmIoStatBuilder.class);
+        ioStatBuilder = mock(VmIoStatBuilderImpl.class);
         backend = new VmIoBackend(version, vmIoStatDao, ioStatBuilder, registrar, id);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/VmIoStatBuilderTest.java	Mon Jan 30 10:30:19 2017 -0500
@@ -0,0 +1,67 @@
+/*
+ * 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.vm.io.agent.internal;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.vm.io.common.VmIoStat;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+
+public class VmIoStatBuilderTest {
+
+    private WriterID writerID;
+
+    @Before
+    public void setup() {
+        writerID = mock(WriterID.class);
+    }
+
+    @Test
+    public void testBuilderBuildsNullForUnknownPid() {
+        Clock clock = mock(Clock.class);
+        VmIoStatBuilder builder = new VmIoStatBuilderImpl(clock, writerID);
+        VmIoStat result = builder.build("vmId", 0);
+        assertNull(result);
+    }
+
+}
+
--- a/vm-io/agent/src/test/java/com/redhat/thermostat/vm/io/agent/internal/WindowsVmIoStatBuilderTest.java	Thu Jan 26 12:14:51 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +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.vm.io.agent.internal;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.shared.config.OS;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.vm.io.common.VmIoStat;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class WindowsVmIoStatBuilderTest {
-
-    private WriterID writerID;
-
-    @Before
-    public void setup() {
-        writerID = mock(WriterID.class);
-    }
-
-    @Test
-    public void testBuilderBuildsNullForUnknownPid() {
-        Assume.assumeTrue(OS.IS_WINDOWS);
-        Clock clock = mock(Clock.class);
-        VmIoStatBuilder builder = new WindowsVmIoStatBuilder(clock, writerID);
-        VmIoStat result = builder.build("vmId", 0);
-        assertNull(result);
-    }
-
-}
-