changeset 2285:9886546c9092

Code Consistency: Private packages should have 'internal' in pkg-name. Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-May/018709.html PR2138
author Severin Gehwolf <sgehwolf@redhat.com>
date Tue, 03 May 2016 15:49:54 +0200
parents 24356daad9c5
children e5c64ae6f6f3
files README.api client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/AgentInfoCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ConnectCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/DisconnectCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListAgentsCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListVMsCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VMInfoCommandTest.java client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VmStatCommandTest.java client/command/pom.xml client/command/src/main/java/com/redhat/thermostat/client/command/cli/PingCommand.java client/command/src/main/java/com/redhat/thermostat/client/command/internal/Activator.java client/command/src/main/java/com/redhat/thermostat/client/command/internal/PingCommand.java client/command/src/test/java/com/redhat/thermostat/client/command/cli/PingCommandTest.java client/command/src/test/java/com/redhat/thermostat/client/command/internal/PingCommandTest.java client/living-vm-filter/core/pom.xml client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingHostFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingVMFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterMenuAction.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterMenuAction.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterTest.java client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java client/living-vm-filter/swing/pom.xml client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelMenuAction.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostVmMainLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/IconUtils.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/LocaleResources.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/ThermostatVmMainLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/DeadHostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelMenuAction.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostVmMainLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/IconUtils.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/LocaleResources.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/ThermostatVmMainLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/DeadVMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/LocaleResources.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMFilterActivator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelMenuAction.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelMenuAction.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LocaleResources.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMIconDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelMenuAction.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelDecorator.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelMenuAction.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/ThermostatVmMainLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/DeadHostIconDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/HostIconDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/ThermostatVmMainLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/AbstractToggleableMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/HostNetworkInterfaceLabelMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMFilterActivatorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/AbstractToggleableMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/HostNetworkInterfaceLabelMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelMenuActionTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelDecoratorTest.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelMenuActionTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/UIResourcesTest.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/ClientConfigurationSwingTest.java common/core/pom.xml common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java common/core/src/main/java/com/redhat/thermostat/common/Size.java common/core/src/main/java/com/redhat/thermostat/common/Version.java common/core/src/main/java/com/redhat/thermostat/common/internal/LocaleResources.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/Bug.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/ExceptionThrowingInputStream.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/FreePortFinder.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestCommandContextFactory.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestCommandRegistry.java common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestTimerFactory.java common/core/src/main/java/com/redhat/thermostat/common/locale/LocaleResources.java common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java common/core/src/main/java/com/redhat/thermostat/common/utils/HostPortsParser.java common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java common/core/src/main/java/com/redhat/thermostat/test/Bug.java common/core/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java common/core/src/main/java/com/redhat/thermostat/test/FreePortFinder.java common/core/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java common/core/src/main/java/com/redhat/thermostat/test/TestCommandRegistry.java common/core/src/main/java/com/redhat/thermostat/test/TestTimerFactory.java common/core/src/test/java/com/redhat/thermostat/common/ApplicationInfoTest.java common/core/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/VersionTest.java common/core/src/test/java/com/redhat/thermostat/common/internal/LocaleResourcesTest.java common/core/src/test/java/com/redhat/thermostat/common/internal/test/ExceptionThrowingInputStreamTest.java common/core/src/test/java/com/redhat/thermostat/common/internal/test/TestCommandContextFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/internal/test/TestTimerFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/locale/LocaleResourcesTest.java common/core/src/test/java/com/redhat/thermostat/test/ExceptionThrowingInputStreamTest.java common/core/src/test/java/com/redhat/thermostat/test/TestCommandContextFactoryTest.java common/core/src/test/java/com/redhat/thermostat/test/TestTimerFactoryTest.java dev/archetype-ext/src/main/resources/archetype-resources/src/test/java/ExampleCommandTest.java dev/schema-info-command/command/pom.xml dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/internal/LocaleResources.java dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/internal/SchemaInfoCommand.java dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/locale/LocaleResources.java dev/schema-info-command/command/src/test/java/com/redhat/thermostat/schemainfo/command/SchemaInfoCommandTest.java dev/schema-info-command/command/src/test/java/com/redhat/thermostat/schemainfo/command/internal/SchemaInfoCommandTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java killvm/client-swing/pom.xml killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/KillVMAction.java killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/LocaleResources.java killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/SwingVMKilledListener.java killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/locale/LocaleResources.java killvm/client-swing/src/test/java/com/redhat/thermostat/killvm/client/internal/TranslateTest.java killvm/client-swing/src/test/java/com/redhat/thermostat/killvm/client/locale/TranslateTest.java killvm/command/pom.xml killvm/command/src/main/java/com/redhat/thermostat/killvm/command/KillVMCommand.java killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/KillVMCommand.java killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/LocaleResources.java killvm/command/src/main/java/com/redhat/thermostat/killvm/command/locale/LocaleResources.java killvm/command/src/test/java/com/redhat/thermostat/killvm/command/KillVmCommandTest.java killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/ActivatorTest.java killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/KillVmCommandTest.java killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/LocaleResourcesTest.java killvm/command/src/test/java/com/redhat/thermostat/killvm/command/locale/LocaleResourcesTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleLoaderTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/HelpCommandTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherImplTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java local/command/src/main/java/com/redhat/thermostat/local/command/internal/LocalCommand.java local/command/src/main/java/com/redhat/thermostat/local/command/internal/LocaleResources.java local/command/src/main/java/com/redhat/thermostat/local/command/internal/ServiceLauncher.java local/command/src/main/java/com/redhat/thermostat/local/command/locale/LocaleResources.java local/command/src/test/java/com/redhat/thermostat/local/command/internal/LocaleResourcesTest.java local/command/src/test/java/com/redhat/thermostat/local/command/internal/ServiceLauncherTest.java local/command/src/test/java/com/redhat/thermostat/local/command/locale/LocaleResourcesTest.java notes/client-cli/src/test/java/com/redhat/thermostat/notes/client/cli/internal/AbstractNotesCommandTest.java platform/core/pom.xml platform/core/src/main/java/com/redhat/thermostat/platform/annotations/processor/PlatformConfigurationProcessor.java platform/core/src/main/java/com/redhat/thermostat/platform/command/PlatformCommand.java platform/core/src/main/java/com/redhat/thermostat/platform/command/PlatformCommandDelegate.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/annotations/processor/PlatformConfigurationProcessor.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommand.java platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegate.java platform/core/src/main/resources/META-INF/services/javax.annotation.processing.Processor platform/core/src/test/java/com/redhat/thermostat/platform/command/PlatformCommandDelegateTest.java platform/core/src/test/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegateTest.java pom.xml setup/command/pom.xml setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/InputCredentialPanel.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/LocaleResources.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCompleteView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/CLISetup.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/PasswordCredentialsReader.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/UsernameCredentialsReader.java setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/LocaleResourcesTest.java setup/command/src/test/java/com/redhat/thermostat/setup/command/locale/LocaleResourcesTest.java storage/core/pom.xml storage/core/src/main/java/com/redhat/thermostat/storage/config/FileStorageCredentials.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/LocaleResources.java storage/core/src/main/java/com/redhat/thermostat/storage/locale/LocaleResources.java storage/core/src/test/java/com/redhat/thermostat/storage/internal/LocaleResourcesTest.java storage/core/src/test/java/com/redhat/thermostat/storage/locale/LocaleResourcesTest.java system-backend/pom.xml system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java system-backend/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java system-backend/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessUserInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackendActivator.java system-backend/src/main/java/com/redhat/thermostat/backend/system/VmStatusChangeNotifier.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/DistributionInformation.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/DistributionInformationSource.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/EtcOsRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatDataExtractor.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListener.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/LsbRelease.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/NetworkInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessUserInfoBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/SystemBackend.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/SystemBackendActivator.java system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/VmStatusChangeNotifier.java system-backend/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/ProcessUserInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/TestLogHandler.java system-backend/src/test/java/com/redhat/thermostat/backend/system/VmStatusChangeNotifierTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/DistributionInformationTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/EtcOsReleaseTest.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/JvmStatDataExtractorTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListenerTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/LsbReleaseTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/NetworkInfoBuilderTest.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/ProcessUserInfoBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/SystemBackendTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/TestLogHandler.java system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/VmStatusChangeNotifierTest.java thermostat-plugin-validator/pom.xml thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/ValidationErrorsFormatter.java thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/LocaleResources.java thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/locale/LocaleResources.java thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/internal/LocaleResourcesTest.java thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/locale/LocaleResourcesTest.java thread/harvester/pom.xml thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/Activator.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/DeadlockHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/Harvester.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/HarvesterHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/LockInfoBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/LockInfoUpdater.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadCountBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadCountUpdater.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHarvester.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSessionHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadStateHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/Activator.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/DeadlockHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/Harvester.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/HarvesterHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/LockInfoBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/LockInfoUpdater.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountUpdater.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadHarvester.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadSessionHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadStateHelper.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadSummaryHelper.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ActivatorTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/DeadlockHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/LockInfoBackendTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/LockInfoUpdaterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadBackendTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadCountUpdaterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHarvesterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadStateHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ActivatorTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/DeadlockHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/HarvesterHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/HarvesterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/LockInfoBackendTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/LockInfoUpdaterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadBackendTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountUpdaterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadHarvesterTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadStateHelperTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadSummaryHelperTest.java validate-command/command/pom.xml validate-command/command/src/main/java/com/redhat/thermostat/validate/command/ValidateCommand.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/Activator.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/LocaleResources.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/ValidateCommand.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/locale/LocaleResources.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/ValidateCommandTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ActivatorTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/LocaleResourcesTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ValidateCommandTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/locale/LocaleResourcesTest.java vm-classstat/client-swing/pom.xml vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/Activator.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/SwingVmClassStatViewProvider.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanel.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/Activator.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/SwingVmClassStatViewProvider.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/VmClassStatPanel.java vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/ActivatorTest.java vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanelTest.java vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/internal/client/swing/ActivatorTest.java vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/internal/client/swing/VmClassStatPanelTest.java vm-compiler/client-swing/pom.xml vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/Activator.java vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatView.java vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatViewProvider.java vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/Activator.java vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatView.java vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatViewProvider.java vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/ActivatorTest.java vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatViewTest.java vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/internal/ActivatorTest.java vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatViewTest.java vm-cpu/agent/src/test/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuStatBuilderTest.java vm-find/command/pom.xml vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommand.java vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/LocaleResources.java vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/UnrecognizedArgumentException.java vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/VmCriterion.java vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/locale/LocaleResources.java vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommandTest.java vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/internal/LocaleResourcesTest.java vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/locale/LocaleResourcesTest.java vm-gc/command/pom.xml vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommand.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListener.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/LocaleResources.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResources.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/LocaleResourcesTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommandTest.java vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResourcesTest.java vm-gc/common/pom.xml vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/LocaleResources.java vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/locale/LocaleResources.java vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/GcParamsMapper.java vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/ValidationErrorsFormatter.java vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/LocaleResourcesTest.java vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/locale/LocaleResourcesTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindObjectsCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindRootCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ListHeapDumpsCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ObjectInfoCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/SaveHeapDumpToFileCommandTest.java vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ShowHeapHistogramCommandTest.java vm-profiler/client-cli/src/test/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommandTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java
diffstat 362 files changed, 14693 insertions(+), 14732 deletions(-) [+]
line wrap: on
line diff
--- a/README.api	Mon May 02 18:43:01 2016 +0200
+++ b/README.api	Tue May 03 15:49:54 2016 +0200
@@ -59,4 +59,3 @@
  - c.r.t.*.internal (and subpackages)
  - c.r.t.storage.mongodb (and subpackages)
  - c.r.t.web (and subpackages)
- - c.r.t.client.filter.vm.core
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/AgentInfoCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/AgentInfoCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -51,13 +51,13 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.BackendInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.BackendInformation;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 
 public class AgentInfoCommandTest {
 
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ConnectCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ConnectCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -54,12 +54,12 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
 import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.config.SSLConfiguration;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.DbService;
 import com.redhat.thermostat.storage.core.DbServiceFactory;
 import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.utils.keyring.Keyring;
 
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/DisconnectCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/DisconnectCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -50,9 +50,9 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.DbService;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class DisconnectCommandTest {
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListAgentsCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListAgentsCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -50,10 +50,10 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 
 public class ListAgentsCommandTest {
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListVMsCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/ListVMsCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -57,13 +57,13 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class ListVMsCommandTest {
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VMInfoCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VMInfoCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -56,6 +56,8 @@
 import com.redhat.thermostat.client.cli.VmArgument;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.Bug;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
@@ -64,8 +66,6 @@
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.Bug;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class VMInfoCommandTest {
--- a/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VmStatCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/cli/src/test/java/com/redhat/thermostat/client/cli/internal/VmStatCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -66,13 +66,13 @@
 import com.redhat.thermostat.common.Timer;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestTimerFactory;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.TimeStampedPojo;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.test.TestTimerFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class VmStatCommandTest {
--- a/client/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/client/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -133,7 +133,6 @@
               com.redhat.thermostat.client.command,
             </Export-Package>
             <Private-Package>
-              com.redhat.thermostat.client.command.cli,
               com.redhat.thermostat.client.command.internal,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/client/command/src/main/java/com/redhat/thermostat/client/command/cli/PingCommand.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.command.cli;
-
-import java.io.PrintStream;
-import java.net.InetSocketAddress;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-
-import com.redhat.thermostat.client.command.RequestQueue;
-import com.redhat.thermostat.client.command.internal.LocaleResources;
-import com.redhat.thermostat.common.cli.AbstractCommand;
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Request.RequestType;
-import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.AgentId;
-import com.redhat.thermostat.storage.dao.AgentInfoDAO;
-
-/*
- * FIXME: extract PingCommand out into a ping plugin with its own thermostat-plugin.xml, rather than being a
- * hardcoded/built-in command
- */
-public class PingCommand extends AbstractCommand {
-    
-    private static final String PING_ACTION_NAME = "ping";
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    static class PongListener implements RequestResponseListener {
-
-        private PrintStream out;
-        private final Semaphore responseBarrier;
-        private final Translate<LocaleResources> t;
-
-        PongListener(PrintStream out, Semaphore responseBarrier, Translate<LocaleResources> t) {
-            this.out = out;
-            this.responseBarrier = responseBarrier;
-            this.t = t;
-        }
-
-        @Override
-        public void fireComplete(Request request, Response response) {
-            switch (response.getType()) {
-            case ERROR:
-                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_ERROR, request.getTarget().toString()).getContents());
-                break;
-            case AUTH_FAILED:
-                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_AUTH_FAILED, request.getTarget().toString()).getContents());
-                break;
-            case OK:
-                // fallthrough
-            case NOOP:
-                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_OK, request.getTarget().toString()).getContents());
-                break;
-            case NOK:
-                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_REFUSED).getContents());
-                break;
-            default:
-                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_UNKNOWN).getContents());
-                break;
-            }
-            responseBarrier.release();
-        }
-        
-    }
-
-    private final BundleContext context;
-
-    public PingCommand() {
-        this(FrameworkUtil.getBundle(PingCommand.class).getBundleContext());
-    }
-
-    public PingCommand(BundleContext context) {
-        this.context = context;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        PrintStream out = ctx.getConsole().getOutput();
-        String agentId = getAgentIDArgument(ctx.getArguments());
-        if (agentId == null) {
-            printCustomMessageWithUsage(out, translator.localize(LocaleResources.COMMAND_PING_ARGUMENT));
-            return;
-        }
-
-        ServiceReference agentInfoDaoRef = context.getServiceReference(AgentInfoDAO.class.getName());
-        requireNonNull(agentInfoDaoRef, translator.localize(LocaleResources.COMMAND_PING_NO_AGENT_INFO_DAO));
-        AgentInfoDAO agentInfoDao = (AgentInfoDAO) context.getService(agentInfoDaoRef);
-
-        AgentId targetId = getAgentId(agentInfoDao, agentId);
-        if (targetId == null) {
-            printCustomMessageWithUsage(out, translator.localize(LocaleResources.COMMAND_PING_INVALID_HOST_ID));
-            return;
-        }
-
-        InetSocketAddress target = agentInfoDao.getAgentInformation(targetId).getRequestQueueAddress();
-        context.ungetService(agentInfoDaoRef);
-        
-        Request ping = new Request(RequestType.RESPONSE_EXPECTED, target);
-        ping.setParameter(Request.ACTION, PING_ACTION_NAME);
-        ping.setReceiver("com.redhat.thermostat.agent.command.internal.PingReceiver");
-        final Semaphore responseBarrier = new Semaphore(0);
-        ping.addListener(new PongListener(out, responseBarrier, translator));
-
-        ServiceReference queueRef = context.getServiceReference(RequestQueue.class.getName());
-        requireNonNull(queueRef, translator.localize(LocaleResources.COMMAND_PING_NO_REQUEST_QUEUE));
-        RequestQueue queue = (RequestQueue) context.getService(queueRef);
-        out.println(translator.localize(LocaleResources.COMMAND_PING_QUEUING_REQUEST, target.toString()).getContents());
-        queue.putRequest(ping);
-        context.ungetService(queueRef);
-        try {
-            responseBarrier.acquire();
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-        }
-    }
-
-    private String getAgentIDArgument(Arguments arguments) {
-        List<String> args = arguments.getNonOptionArguments();
-        if (args.size() != 1) {
-            return null;
-        }
-        return args.get(0);
-    }
-
-    private AgentId getAgentId(AgentInfoDAO dao, String agentId) {
-        AgentId targetId = null;
-        for (AgentId aliveAgent : dao.getAliveAgentIds()) {
-            if (agentId.equals(aliveAgent.get())) {
-                targetId  = aliveAgent;
-                break;
-            }
-        }
-        return targetId;
-    }
-
-    private void printCustomMessageWithUsage(PrintStream out, LocalizedString message) {
-        out.println(message.getContents());
-        // FIXME add usage back out.println(getUsage());
-        return;
-    }
-
-}
-
--- a/client/command/src/main/java/com/redhat/thermostat/client/command/internal/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/internal/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -44,7 +44,6 @@
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
 import com.redhat.thermostat.client.command.RequestQueue;
-import com.redhat.thermostat.client.command.cli.PingCommand;
 import com.redhat.thermostat.common.cli.CommandRegistryImpl;
 import com.redhat.thermostat.shared.config.SSLConfiguration;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/internal/PingCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2012-2016 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.client.command.internal;
+
+import java.io.PrintStream;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+
+import com.redhat.thermostat.client.command.RequestQueue;
+import com.redhat.thermostat.common.cli.AbstractCommand;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Request.RequestType;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+
+/*
+ * FIXME: extract PingCommand out into a ping plugin with its own thermostat-plugin.xml, rather than being a
+ * hardcoded/built-in command
+ */
+public class PingCommand extends AbstractCommand {
+    
+    private static final String PING_ACTION_NAME = "ping";
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    static class PongListener implements RequestResponseListener {
+
+        private PrintStream out;
+        private final Semaphore responseBarrier;
+        private final Translate<LocaleResources> t;
+
+        PongListener(PrintStream out, Semaphore responseBarrier, Translate<LocaleResources> t) {
+            this.out = out;
+            this.responseBarrier = responseBarrier;
+            this.t = t;
+        }
+
+        @Override
+        public void fireComplete(Request request, Response response) {
+            switch (response.getType()) {
+            case ERROR:
+                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_ERROR, request.getTarget().toString()).getContents());
+                break;
+            case AUTH_FAILED:
+                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_AUTH_FAILED, request.getTarget().toString()).getContents());
+                break;
+            case OK:
+                // fallthrough
+            case NOOP:
+                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_OK, request.getTarget().toString()).getContents());
+                break;
+            case NOK:
+                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_REFUSED).getContents());
+                break;
+            default:
+                out.println(t.localize(LocaleResources.COMMAND_PING_RESPONSE_UNKNOWN).getContents());
+                break;
+            }
+            responseBarrier.release();
+        }
+        
+    }
+
+    private final BundleContext context;
+
+    public PingCommand() {
+        this(FrameworkUtil.getBundle(PingCommand.class).getBundleContext());
+    }
+
+    public PingCommand(BundleContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        PrintStream out = ctx.getConsole().getOutput();
+        String agentId = getAgentIDArgument(ctx.getArguments());
+        if (agentId == null) {
+            printCustomMessageWithUsage(out, translator.localize(LocaleResources.COMMAND_PING_ARGUMENT));
+            return;
+        }
+
+        ServiceReference agentInfoDaoRef = context.getServiceReference(AgentInfoDAO.class.getName());
+        requireNonNull(agentInfoDaoRef, translator.localize(LocaleResources.COMMAND_PING_NO_AGENT_INFO_DAO));
+        AgentInfoDAO agentInfoDao = (AgentInfoDAO) context.getService(agentInfoDaoRef);
+
+        AgentId targetId = getAgentId(agentInfoDao, agentId);
+        if (targetId == null) {
+            printCustomMessageWithUsage(out, translator.localize(LocaleResources.COMMAND_PING_INVALID_HOST_ID));
+            return;
+        }
+
+        InetSocketAddress target = agentInfoDao.getAgentInformation(targetId).getRequestQueueAddress();
+        context.ungetService(agentInfoDaoRef);
+        
+        Request ping = new Request(RequestType.RESPONSE_EXPECTED, target);
+        ping.setParameter(Request.ACTION, PING_ACTION_NAME);
+        ping.setReceiver("com.redhat.thermostat.agent.command.internal.PingReceiver");
+        final Semaphore responseBarrier = new Semaphore(0);
+        ping.addListener(new PongListener(out, responseBarrier, translator));
+
+        ServiceReference queueRef = context.getServiceReference(RequestQueue.class.getName());
+        requireNonNull(queueRef, translator.localize(LocaleResources.COMMAND_PING_NO_REQUEST_QUEUE));
+        RequestQueue queue = (RequestQueue) context.getService(queueRef);
+        out.println(translator.localize(LocaleResources.COMMAND_PING_QUEUING_REQUEST, target.toString()).getContents());
+        queue.putRequest(ping);
+        context.ungetService(queueRef);
+        try {
+            responseBarrier.acquire();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+    private String getAgentIDArgument(Arguments arguments) {
+        List<String> args = arguments.getNonOptionArguments();
+        if (args.size() != 1) {
+            return null;
+        }
+        return args.get(0);
+    }
+
+    private AgentId getAgentId(AgentInfoDAO dao, String agentId) {
+        AgentId targetId = null;
+        for (AgentId aliveAgent : dao.getAliveAgentIds()) {
+            if (agentId.equals(aliveAgent.get())) {
+                targetId  = aliveAgent;
+                break;
+            }
+        }
+        return targetId;
+    }
+
+    private void printCustomMessageWithUsage(PrintStream out, LocalizedString message) {
+        out.println(message.getContents());
+        // FIXME add usage back out.println(getUsage());
+        return;
+    }
+
+}
+
--- a/client/command/src/test/java/com/redhat/thermostat/client/command/cli/PingCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.command.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.net.InetSocketAddress;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.concurrent.Semaphore;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.client.command.cli.PingCommand.PongListener;
-import com.redhat.thermostat.client.command.internal.LocaleResources;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.AgentId;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.dao.AgentInfoDAO;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.testutils.StubBundleContext;
-
-public class PingCommandTest {
-
-    private static final String KNOWN_AGENT_ID = "some-agent-id";
-
-    @Test
-    public void testCommandNeedsAgentId() throws CommandException {
-        StubBundleContext context = new StubBundleContext();
-
-        PingCommand command = new PingCommand(context);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-
-        command.run(factory.createContext(args));
-
-        // TODO why doesn't ping throw an exception?
-        assertEquals("Ping command accepts one and only one argument.\n", factory.getOutput());
-    }
-
-    @Test
-    public void testCommandWithoutAgentDao() throws CommandException {
-        HostRef host1 = mock(HostRef.class);
-        when(host1.getAgentId()).thenReturn(KNOWN_AGENT_ID);
-
-        StubBundleContext context = new StubBundleContext();
-
-        PingCommand command = new PingCommand(context);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addNonOptionArgument(KNOWN_AGENT_ID);
-
-        try {
-            command.run(factory.createContext(args));
-            fail("did not throw expected exception");
-        } catch (CommandException agentDaoServiceMissing) {
-            assertEquals("Unable to access agent information: service not available", agentDaoServiceMissing.getMessage());
-        }
-    }
-    
-    @Test
-    public void testCommandWithoutRequestQueue() throws CommandException {
-        AgentId agentId = new AgentId(KNOWN_AGENT_ID);
-
-        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
-        when(agentInfoDao.getAliveAgentIds()).thenReturn(new HashSet<>(Arrays.asList(agentId)));
-        AgentInformation info = mock(AgentInformation.class);
-        when(info.getConfigListenAddress()).thenReturn("myHost:9001");
-        when(agentInfoDao.getAgentInformation(agentId)).thenReturn(info);
-
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
-
-        PingCommand command = new PingCommand(context);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addNonOptionArgument(KNOWN_AGENT_ID);
-
-        try {
-            command.run(factory.createContext(args));
-            fail("did not throw expected exception");
-        } catch (CommandException e) {
-            assertEquals("Unable to access command request queue: service not available", e.getMessage());
-        }
-    }
-    
-    /*
-     * Tests whether getContents() gets called on auth fail responses.
-     */
-    @Test
-    public void testAuthFailStringMessage() {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        PrintStream out = new PrintStream(bout);
-        Semaphore responseBarrier = new Semaphore(1);
-        InetSocketAddress addr = InetSocketAddress.createUnresolved("foo", 1234);
-        @SuppressWarnings("unchecked")
-        Translate<LocaleResources> t = mock(Translate.class);
-        when(t.localize(LocaleResources.COMMAND_PING_RESPONSE_AUTH_FAILED, addr.toString())).thenReturn(new LocalizedString("auth_fail"));
-        PongListener listener = new PongListener(out, responseBarrier, t);
-        responseBarrier.release();
-        Request request = mock(Request.class);
-        when(request.getTarget()).thenReturn(addr);
-        listener.fireComplete(request, new Response(ResponseType.AUTH_FAILED));
-        assertEquals("auth_fail\n", bout.toString());
-    }
-
-    // TODO add more tests that check the actual behaviour under valid input
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/test/java/com/redhat/thermostat/client/command/internal/PingCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2012-2016 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.client.command.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.concurrent.Semaphore;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.command.internal.LocaleResources;
+import com.redhat.thermostat.client.command.internal.PingCommand;
+import com.redhat.thermostat.client.command.internal.PingCommand.PongListener;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.model.AgentInformation;
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+public class PingCommandTest {
+
+    private static final String KNOWN_AGENT_ID = "some-agent-id";
+
+    @Test
+    public void testCommandNeedsAgentId() throws CommandException {
+        StubBundleContext context = new StubBundleContext();
+
+        PingCommand command = new PingCommand(context);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+
+        command.run(factory.createContext(args));
+
+        // TODO why doesn't ping throw an exception?
+        assertEquals("Ping command accepts one and only one argument.\n", factory.getOutput());
+    }
+
+    @Test
+    public void testCommandWithoutAgentDao() throws CommandException {
+        HostRef host1 = mock(HostRef.class);
+        when(host1.getAgentId()).thenReturn(KNOWN_AGENT_ID);
+
+        StubBundleContext context = new StubBundleContext();
+
+        PingCommand command = new PingCommand(context);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addNonOptionArgument(KNOWN_AGENT_ID);
+
+        try {
+            command.run(factory.createContext(args));
+            fail("did not throw expected exception");
+        } catch (CommandException agentDaoServiceMissing) {
+            assertEquals("Unable to access agent information: service not available", agentDaoServiceMissing.getMessage());
+        }
+    }
+    
+    @Test
+    public void testCommandWithoutRequestQueue() throws CommandException {
+        AgentId agentId = new AgentId(KNOWN_AGENT_ID);
+
+        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
+        when(agentInfoDao.getAliveAgentIds()).thenReturn(new HashSet<>(Arrays.asList(agentId)));
+        AgentInformation info = mock(AgentInformation.class);
+        when(info.getConfigListenAddress()).thenReturn("myHost:9001");
+        when(agentInfoDao.getAgentInformation(agentId)).thenReturn(info);
+
+        StubBundleContext context = new StubBundleContext();
+        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
+
+        PingCommand command = new PingCommand(context);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addNonOptionArgument(KNOWN_AGENT_ID);
+
+        try {
+            command.run(factory.createContext(args));
+            fail("did not throw expected exception");
+        } catch (CommandException e) {
+            assertEquals("Unable to access command request queue: service not available", e.getMessage());
+        }
+    }
+    
+    /*
+     * Tests whether getContents() gets called on auth fail responses.
+     */
+    @Test
+    public void testAuthFailStringMessage() {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        PrintStream out = new PrintStream(bout);
+        Semaphore responseBarrier = new Semaphore(1);
+        InetSocketAddress addr = InetSocketAddress.createUnresolved("foo", 1234);
+        @SuppressWarnings("unchecked")
+        Translate<LocaleResources> t = mock(Translate.class);
+        when(t.localize(LocaleResources.COMMAND_PING_RESPONSE_AUTH_FAILED, addr.toString())).thenReturn(new LocalizedString("auth_fail"));
+        PongListener listener = new PongListener(out, responseBarrier, t);
+        responseBarrier.release();
+        Request request = mock(Request.class);
+        when(request.getTarget()).thenReturn(addr);
+        listener.fireComplete(request, new Response(ResponseType.AUTH_FAILED));
+        assertEquals("auth_fail\n", bout.toString());
+    }
+
+    // TODO add more tests that check the actual behaviour under valid input
+}
+
--- a/client/living-vm-filter/core/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -64,7 +64,6 @@
           <instructions>
             <Private-Package>
                 com.redhat.thermostat.client.filter.vm.core.internal,
-                com.redhat.thermostat.client.filter.vm.core
             </Private-Package>
             <Bundle-Activator>com.redhat.thermostat.client.filter.vm.core.internal.VMFilterActivator</Bundle-Activator>
             <Bundle-SymbolicName>com.redhat.thermostat.filter.livingvm.core</Bundle-SymbolicName>
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingHostFilter.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.core;
-
-import com.redhat.thermostat.client.ui.ReferenceFilter;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-
-public class LivingHostFilter extends ReferenceFilter {
-
-    volatile boolean filterActive = true;
-    
-    private HostInfoDAO dao;
-    
-    public LivingHostFilter(HostInfoDAO dao) {
-        this.dao = dao;
-    }
-    
-    @Override
-    public boolean applies(Ref reference) {
-        return (reference instanceof HostRef);
-    }
-    
-    @Override
-    public boolean matches(Ref ref) {
-        if (!filterActive)
-            return true;
-        
-        return applies(ref) && dao.isAlive((HostRef) ref);
-    }
-
-    public void setActive(boolean active) {
-        boolean oldActive = this.filterActive;
-        this.filterActive = active;
-        if (oldActive != filterActive) {
-            notify(FilterEvent.FILTER_CHANGED);
-        }
-    }
-
-    public boolean isActive() {
-        return filterActive;
-    }
-}
-
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingVMFilter.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.core;
-
-import com.redhat.thermostat.client.ui.ReferenceFilter;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class LivingVMFilter extends ReferenceFilter {
-
-    volatile boolean filterActive = true;
-    
-    private VmInfoDAO vmDao;
-    private HostInfoDAO hostDao;
-    
-    public LivingVMFilter(VmInfoDAO vmDao, HostInfoDAO hostDao) {
-        this.hostDao = hostDao;
-        this.vmDao = vmDao;
-    }
-    
-    @Override
-    public boolean applies(Ref reference) {
-        return (reference instanceof VmRef);
-    }
-    
-    @Override
-    public boolean matches(Ref ref) {
-        if (!filterActive) {
-            return true;
-        }
-        
-        if (!applies(ref)) {
-            return false;
-        }
-        
-        // if the parent host if not alive, we don't want to hide this
-        boolean match = true;
-        
-        if (hostDao.isAlive(((VmRef) ref).getHostRef())) {
-            VmInfo vmInfo = vmDao.getVmInfo((VmRef) ref);
-            match = vmInfo.isAlive();
-        }
-
-        return match;
-    }
-
-    public void setActive(boolean active) {
-        boolean oldActive = this.filterActive;
-        this.filterActive = active;
-        if (oldActive != filterActive) {
-            notify(FilterEvent.FILTER_CHANGED);
-        }
-    }
-
-    public boolean isActive() {
-        return filterActive;
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilter.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012-2016 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.client.filter.vm.core.internal;
+
+import com.redhat.thermostat.client.ui.ReferenceFilter;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+public class LivingHostFilter extends ReferenceFilter {
+
+    volatile boolean filterActive = true;
+    
+    private HostInfoDAO dao;
+    
+    public LivingHostFilter(HostInfoDAO dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public boolean applies(Ref reference) {
+        return (reference instanceof HostRef);
+    }
+    
+    @Override
+    public boolean matches(Ref ref) {
+        if (!filterActive)
+            return true;
+        
+        return applies(ref) && dao.isAlive((HostRef) ref);
+    }
+
+    public void setActive(boolean active) {
+        boolean oldActive = this.filterActive;
+        this.filterActive = active;
+        if (oldActive != filterActive) {
+            notify(FilterEvent.FILTER_CHANGED);
+        }
+    }
+
+    public boolean isActive() {
+        return filterActive;
+    }
+}
+
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterMenuAction.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterMenuAction.java	Tue May 03 15:49:54 2016 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.client.filter.vm.core.internal;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilter.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012-2016 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.client.filter.vm.core.internal;
+
+import com.redhat.thermostat.client.ui.ReferenceFilter;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class LivingVMFilter extends ReferenceFilter {
+
+    volatile boolean filterActive = true;
+    
+    private VmInfoDAO vmDao;
+    private HostInfoDAO hostDao;
+    
+    public LivingVMFilter(VmInfoDAO vmDao, HostInfoDAO hostDao) {
+        this.hostDao = hostDao;
+        this.vmDao = vmDao;
+    }
+    
+    @Override
+    public boolean applies(Ref reference) {
+        return (reference instanceof VmRef);
+    }
+    
+    @Override
+    public boolean matches(Ref ref) {
+        if (!filterActive) {
+            return true;
+        }
+        
+        if (!applies(ref)) {
+            return false;
+        }
+        
+        // if the parent host if not alive, we don't want to hide this
+        boolean match = true;
+        
+        if (hostDao.isAlive(((VmRef) ref).getHostRef())) {
+            VmInfo vmInfo = vmDao.getVmInfo((VmRef) ref);
+            match = vmInfo.isAlive();
+        }
+
+        return match;
+    }
+
+    public void setActive(boolean active) {
+        boolean oldActive = this.filterActive;
+        this.filterActive = active;
+        if (oldActive != filterActive) {
+            notify(FilterEvent.FILTER_CHANGED);
+        }
+    }
+
+    public boolean isActive() {
+        return filterActive;
+    }
+}
+
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterMenuAction.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterMenuAction.java	Tue May 03 15:49:54 2016 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.client.filter.vm.core.internal;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java	Tue May 03 15:49:54 2016 +0200
@@ -46,8 +46,6 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
-import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.client.ui.ReferenceFilter;
 import com.redhat.thermostat.common.MultipleServiceTracker;
--- a/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -43,7 +43,6 @@
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 
--- a/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -44,7 +44,6 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.filter.vm.core.internal.LivingVMFilterMenuAction;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
--- a/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -41,8 +41,6 @@
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
-import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.client.ui.ReferenceFilter;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
--- a/client/living-vm-filter/swing/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/client/living-vm-filter/swing/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -64,11 +64,11 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Bundle-Activator>com.redhat.thermostat.client.filter.vm.swing.VMFilterActivator</Bundle-Activator>
+            <Bundle-Activator>com.redhat.thermostat.client.filter.internal.vm.swing.VMFilterActivator</Bundle-Activator>
             <Bundle-SymbolicName>com.redhat.thermostat.filter.livingvm.swing</Bundle-SymbolicName>
             <Private-Package>
-            com.redhat.thermostat.client.filter.vm.swing,
-            com.redhat.thermostat.client.filter.host.swing
+            com.redhat.thermostat.client.filter.internal.vm.swing,
+            com.redhat.thermostat.client.filter.internal.host.swing
             </Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import java.awt.Paint;
-
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
-import com.redhat.thermostat.client.swing.components.Icon;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-
-public class DeadHostIconDecorator implements ReferenceFieldIconDecorator {
-
-    private final Icon UNCONNECTED;
-    private final Icon UNCONNECTED_SELECTED;
-
-    private final ReferenceFieldIconDecorator parent;
-    private final HostInfoDAO dao;
-    
-    public static DeadHostIconDecorator createInstance(HostInfoDAO dao, UIDefaults uiDefaults, HostIconDecorator parent) {
-        return new DeadHostIconDecorator(dao, uiDefaults, parent);
-    }
-    
-    private DeadHostIconDecorator(HostInfoDAO dao, UIDefaults uiDefaults, HostIconDecorator parent) {
-        this.dao = dao;
-
-        int size = uiDefaults.getIconDecorationSize();
-        Paint color = uiDefaults.getDecorationIconColor();
-
-        UNCONNECTED = new FontAwesomeIcon('\uf127', size, color);
-        UNCONNECTED_SELECTED = new FontAwesomeIcon('\uf127', size, color);
-
-        this.parent = parent;
-    }
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST + 100;
-    }
-    
-    @Override
-    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
-        PlatformIcon parentDecoreatedIcon = parent.getIcon(originalIcon, reference);
-        return doOverlay(parentDecoreatedIcon, reference, UNCONNECTED);
-    }
-    
-    @Override
-    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
-        PlatformIcon parentDecoratedIcon = parent.getSelectedIcon(originalIcon, reference);
-        return doOverlay(parentDecoratedIcon, reference, UNCONNECTED_SELECTED);
-    }
-    
-    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
-        
-        if (!(reference instanceof HostRef)) {
-            return originalIcon;
-        }
-        
-        if (dao.isAlive((HostRef) reference)) {
-            return originalIcon;
-        }
-        
-        Icon canvas = (Icon) originalIcon;
-        int y = canvas.getIconHeight() - overlay.getIconHeight();
-        
-        return IconUtils.overlay(canvas, overlay, 0, y);
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import java.awt.Paint;
-
-import com.redhat.thermostat.client.swing.IconResource;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.swing.components.CompositeIcon;
-import com.redhat.thermostat.client.swing.components.Icon;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.Ref;
-
-public class HostIconDecorator implements ReferenceFieldIconDecorator {
-    
-    private static Icon ICON;
-    private static Icon SELECTED;
-
-    public static HostIconDecorator createInstance(UIDefaults uiDefaults) {
-        return new HostIconDecorator(uiDefaults);
-    }
-
-    private HostIconDecorator(UIDefaults uiDefaults) {
-        int size = uiDefaults.getReferenceFieldDefaultIconSize();
-        Paint fg = uiDefaults.getReferenceFieldIconColor();
-        Paint selected = uiDefaults.getReferenceFieldIconSelectedColor();
-        
-        Icon hostIcon = IconUtils.resizeIcon(IconResource.HOST_24.getIcon(), size);
-        
-        ICON = CompositeIcon.createDefaultComposite(hostIcon, fg);
-        SELECTED = CompositeIcon.createDefaultComposite(hostIcon, selected);
-    }
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST;
-    }
-    
-    @Override
-    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
-        if (reference instanceof HostRef) {
-            return ICON;
-        } else {
-            return originalIcon;
-        }
-    }
-    
-    @Override
-    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
-        if (reference instanceof HostRef) {
-            return SELECTED;
-        } else {
-            return originalIcon;
-        }
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class HostNetworkInterfaceLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private NetworkInterfaceInfoDAO dao;
-    private boolean enabled = false;
-    private final Map<HostRef, String> hostNetworkIfaceMap = new HashMap<>();
-
-    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
-
-    public HostNetworkInterfaceLabelDecorator(NetworkInterfaceInfoDAO dao) {
-        this.dao = dao;
-    }
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST;
-    }
-    
-    @Override
-    public String getLabel(String originalLabel, Ref reference) {
-
-        if (!isEnabled()) {
-            return originalLabel;
-        }
-        
-        if (!(reference instanceof HostRef)) {
-            return originalLabel;
-        }
-
-        HostRef ref = (HostRef) reference;
-        String label;
-        if (hostNetworkIfaceMap.containsKey(ref)) {
-            label = hostNetworkIfaceMap.get(ref);
-        } else {
-            label = computeLabel(ref);
-            hostNetworkIfaceMap.put(ref, label);
-        }
-
-        return t.localize(LocaleResources.NET_IFACE_LABEL_DECORATOR, originalLabel, label).getContents();
-    }
-
-    private String computeLabel(HostRef ref) {
-        List<NetworkInterfaceInfo> infos =
-                dao.getNetworkInterfaces(ref);
-        StringBuilder result = new StringBuilder();
-
-        for (NetworkInterfaceInfo info : infos) {
-            // filter out the loopbak
-            if (!info.getInterfaceName().equals("lo")) {
-                if (info.getIp4Addr() != null) {
-                    result.append(info.getIp4Addr()).append("; ");
-                } else if (info.getIp6Addr() != null) {
-                    result.append(info.getIp6Addr()).append("; ");
-                }
-            }
-        }
-        // Avoid IOOBE if there are no network interfaces
-        if (result.length() >= 2) {
-            result.deleteCharAt(result.length() - 2);
-        }
-        return result.toString().trim();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        if (this.enabled != enabled) {
-            this.enabled = enabled;
-            notifier.fireAction(StatusEvent.STATUS_CHANGED);
-        }
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.removeActionListener(listener);
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelMenuAction.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-
-public class HostNetworkInterfaceLabelMenuAction implements MenuAction {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private HostNetworkInterfaceLabelDecorator decorator;
-
-    public HostNetworkInterfaceLabelMenuAction(HostNetworkInterfaceLabelDecorator decorator) {
-        this.decorator = decorator;
-    }
-
-    @Override
-    public LocalizedString getName() {
-        return t.localize(LocaleResources.NET_IFACE_LABEL_MENU_NAME);
-    }
-
-    @Override
-    public LocalizedString getDescription() {
-        return t.localize(LocaleResources.NET_IFACE_LABEL_MENU_DESCRIPTION);
-    }
-
-    @Override
-    public void execute() {
-        decorator.setEnabled(!decorator.isEnabled());
-    }
-
-    @Override
-    public Type getType() {
-        return Type.CHECK;
-    }
-
-    @Override
-    public LocalizedString[] getPath() {
-        return new LocalizedString[] { t.localize(LocaleResources.NET_IFACE_LABEL_MENU_PATH), getName() };
-    }
-
-    @Override
-    public int sortOrder() {
-        return SORT_TOP + 15;
-    }
-
-    @Override
-    public String getPersistenceID() {
-        return MENU_KEY + "host-net-iface-labels";
-    }
-}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/HostVmMainLabelDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.storage.core.Ref;
-
-public class HostVmMainLabelDecorator implements ReferenceFieldLabelDecorator {
-
-    @Override
-    public String getLabel(String originalLabel, Ref reference) {
-        return reference.getName();
-    }
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST;
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/IconUtils.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-
-import com.redhat.thermostat.client.swing.components.EmptyIcon;
-import com.redhat.thermostat.client.swing.components.Icon;
-
-public class IconUtils {
-    public static Icon resizeIcon(Icon source, int size) {
-        Icon canvas = new EmptyIcon(size, size);
-        
-        float v1 = canvas.getIconWidth() / 2;
-        float v0 = source.getIconWidth() / 2; 
-                
-        int x = (int) (v1 - v0 + 0.5);
-                
-        v1 = canvas.getIconHeight() / 2;
-        v0 = source.getIconHeight() / 2; 
-        
-        int y = (int) (v1 - v0 + 0.5);
-
-        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
-                                                canvas.getIconHeight(),
-                                                BufferedImage.TYPE_INT_ARGB);
-        Graphics2D graphics = (Graphics2D) image.getGraphics();
-        graphics.drawImage(source.getImage(), x, y, null);
-        
-        return new Icon(image);
-    }
-
-    public static Icon overlay(Icon canvas, Icon overlay, int x, int y) {
-        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
-                                                canvas.getIconHeight(),
-                                                BufferedImage.TYPE_INT_ARGB);
-        Graphics2D graphics = (Graphics2D) image.getGraphics();
-        canvas.paintIcon(null, graphics, 0, 0);
-        
-        graphics.drawImage(overlay.getImage(), x, y, null);
-        graphics.dispose();
-        
-        return new Icon(image);
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    NET_IFACE_LABEL_MENU_NAME,
-    NET_IFACE_LABEL_MENU_DESCRIPTION,
-    NET_IFACE_LABEL_MENU_PATH,
-    NET_IFACE_LABEL_DECORATOR,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.client.filter.host.swing.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/host/swing/ThermostatVmMainLabelDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.TreeSet;
-
-import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class ThermostatVmMainLabelDecorator implements ReferenceFieldLabelDecorator {
-
-    // duplicated in the startup scripts
-    private static final String MAIN_CLASS =
-            "com.redhat.thermostat.main.Thermostat";
-    // duplicated in the startup scripts
-    private static final String COMMAND_CHANNEL_CLASS =
-            "com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain";
-
-    private static final Set<String> KNOWN_STARTUP_CLASSES;
-
-    static {
-        KNOWN_STARTUP_CLASSES = new TreeSet<>();
-        KNOWN_STARTUP_CLASSES.add(MAIN_CLASS);
-        KNOWN_STARTUP_CLASSES.add(COMMAND_CHANNEL_CLASS);
-    }
-
-    private VmInfoDAO dao;
-
-    public ThermostatVmMainLabelDecorator(VmInfoDAO dao) {
-        this.dao = dao;
-    }
-
-    @Override
-    public String getLabel(String originalLabel, Ref reference) {
-
-        if (!(reference instanceof VmRef) ||
-            !KNOWN_STARTUP_CLASSES.contains(reference.getName())) {
-            return originalLabel;
-        }
-        VmInfo vmInfo = dao.getVmInfo((VmRef) reference);
-        if (!KNOWN_STARTUP_CLASSES.contains(vmInfo.getMainClass())) {
-            return originalLabel;
-        }
-        return createLabel(vmInfo);
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST + 1;
-    }
-
-    /**
-     * This method returns a short version for the VmInfo object command line.
-     * @param info the vm info object from which take information.
-     * @return the resulting string 
-     */
-    private String createLabel(VmInfo info) {
-        if (info.getMainClass().equals(COMMAND_CHANNEL_CLASS)) {
-            return createLabelForCommandChannel(info);
-        }
-
-        return createLabelForRegularCommand(info);
-    }
-
-    private String createLabelForCommandChannel(VmInfo info) {
-        return "Thermostat (command channel)";
-    }
-
-    private String createLabelForRegularCommand(VmInfo info) {
-        String commandLine = info.getJavaCommandLine();
-
-        // heuristic: take the first non-option argument
-
-        // FIXME this doesn't work if --boot-delegation appears before the
-        // subcommand. --boot-delegation requires a separate value.
-        String[] parts = commandLine.split("\\s+");
-        parts = Arrays.copyOfRange(parts, 1, parts.length);
-
-        int argumentCount = 0;
-        StringBuilder result = new StringBuilder();
-        result.append("Thermostat ");
-        for (String part : parts) {
-            if (part.startsWith("--")) {
-                continue;
-            }
-            result.append(part).append(" ");
-            argumentCount++;
-            if (argumentCount == 1) {
-                break;
-            }
-        }
-        return result.toString().trim();
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/DeadHostIconDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import java.awt.Paint;
+
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+public class DeadHostIconDecorator implements ReferenceFieldIconDecorator {
+
+    private final Icon UNCONNECTED;
+    private final Icon UNCONNECTED_SELECTED;
+
+    private final ReferenceFieldIconDecorator parent;
+    private final HostInfoDAO dao;
+    
+    public static DeadHostIconDecorator createInstance(HostInfoDAO dao, UIDefaults uiDefaults, HostIconDecorator parent) {
+        return new DeadHostIconDecorator(dao, uiDefaults, parent);
+    }
+    
+    private DeadHostIconDecorator(HostInfoDAO dao, UIDefaults uiDefaults, HostIconDecorator parent) {
+        this.dao = dao;
+
+        int size = uiDefaults.getIconDecorationSize();
+        Paint color = uiDefaults.getDecorationIconColor();
+
+        UNCONNECTED = new FontAwesomeIcon('\uf127', size, color);
+        UNCONNECTED_SELECTED = new FontAwesomeIcon('\uf127', size, color);
+
+        this.parent = parent;
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST + 100;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        PlatformIcon parentDecoreatedIcon = parent.getIcon(originalIcon, reference);
+        return doOverlay(parentDecoreatedIcon, reference, UNCONNECTED);
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        PlatformIcon parentDecoratedIcon = parent.getSelectedIcon(originalIcon, reference);
+        return doOverlay(parentDecoratedIcon, reference, UNCONNECTED_SELECTED);
+    }
+    
+    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
+        
+        if (!(reference instanceof HostRef)) {
+            return originalIcon;
+        }
+        
+        if (dao.isAlive((HostRef) reference)) {
+            return originalIcon;
+        }
+        
+        Icon canvas = (Icon) originalIcon;
+        int y = canvas.getIconHeight() - overlay.getIconHeight();
+        
+        return IconUtils.overlay(canvas, overlay, 0, y);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostIconDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import java.awt.Paint;
+
+import com.redhat.thermostat.client.swing.IconResource;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.swing.components.CompositeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+
+public class HostIconDecorator implements ReferenceFieldIconDecorator {
+    
+    private static Icon ICON;
+    private static Icon SELECTED;
+
+    public static HostIconDecorator createInstance(UIDefaults uiDefaults) {
+        return new HostIconDecorator(uiDefaults);
+    }
+
+    private HostIconDecorator(UIDefaults uiDefaults) {
+        int size = uiDefaults.getReferenceFieldDefaultIconSize();
+        Paint fg = uiDefaults.getReferenceFieldIconColor();
+        Paint selected = uiDefaults.getReferenceFieldIconSelectedColor();
+        
+        Icon hostIcon = IconUtils.resizeIcon(IconResource.HOST_24.getIcon(), size);
+        
+        ICON = CompositeIcon.createDefaultComposite(hostIcon, fg);
+        SELECTED = CompositeIcon.createDefaultComposite(hostIcon, selected);
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof HostRef) {
+            return ICON;
+        } else {
+            return originalIcon;
+        }
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof HostRef) {
+            return SELECTED;
+        } else {
+            return originalIcon;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class HostNetworkInterfaceLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private NetworkInterfaceInfoDAO dao;
+    private boolean enabled = false;
+    private final Map<HostRef, String> hostNetworkIfaceMap = new HashMap<>();
+
+    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
+
+    public HostNetworkInterfaceLabelDecorator(NetworkInterfaceInfoDAO dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST;
+    }
+    
+    @Override
+    public String getLabel(String originalLabel, Ref reference) {
+
+        if (!isEnabled()) {
+            return originalLabel;
+        }
+        
+        if (!(reference instanceof HostRef)) {
+            return originalLabel;
+        }
+
+        HostRef ref = (HostRef) reference;
+        String label;
+        if (hostNetworkIfaceMap.containsKey(ref)) {
+            label = hostNetworkIfaceMap.get(ref);
+        } else {
+            label = computeLabel(ref);
+            hostNetworkIfaceMap.put(ref, label);
+        }
+
+        return t.localize(LocaleResources.NET_IFACE_LABEL_DECORATOR, originalLabel, label).getContents();
+    }
+
+    private String computeLabel(HostRef ref) {
+        List<NetworkInterfaceInfo> infos =
+                dao.getNetworkInterfaces(ref);
+        StringBuilder result = new StringBuilder();
+
+        for (NetworkInterfaceInfo info : infos) {
+            // filter out the loopbak
+            if (!info.getInterfaceName().equals("lo")) {
+                if (info.getIp4Addr() != null) {
+                    result.append(info.getIp4Addr()).append("; ");
+                } else if (info.getIp6Addr() != null) {
+                    result.append(info.getIp6Addr()).append("; ");
+                }
+            }
+        }
+        // Avoid IOOBE if there are no network interfaces
+        if (result.length() >= 2) {
+            result.deleteCharAt(result.length() - 2);
+        }
+        return result.toString().trim();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (this.enabled != enabled) {
+            this.enabled = enabled;
+            notifier.fireAction(StatusEvent.STATUS_CHANGED);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.removeActionListener(listener);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelMenuAction.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class HostNetworkInterfaceLabelMenuAction implements MenuAction {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private HostNetworkInterfaceLabelDecorator decorator;
+
+    public HostNetworkInterfaceLabelMenuAction(HostNetworkInterfaceLabelDecorator decorator) {
+        this.decorator = decorator;
+    }
+
+    @Override
+    public LocalizedString getName() {
+        return t.localize(LocaleResources.NET_IFACE_LABEL_MENU_NAME);
+    }
+
+    @Override
+    public LocalizedString getDescription() {
+        return t.localize(LocaleResources.NET_IFACE_LABEL_MENU_DESCRIPTION);
+    }
+
+    @Override
+    public void execute() {
+        decorator.setEnabled(!decorator.isEnabled());
+    }
+
+    @Override
+    public Type getType() {
+        return Type.CHECK;
+    }
+
+    @Override
+    public LocalizedString[] getPath() {
+        return new LocalizedString[] { t.localize(LocaleResources.NET_IFACE_LABEL_MENU_PATH), getName() };
+    }
+
+    @Override
+    public int sortOrder() {
+        return SORT_TOP + 15;
+    }
+
+    @Override
+    public String getPersistenceID() {
+        return MENU_KEY + "host-net-iface-labels";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/HostVmMainLabelDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+
+public class HostVmMainLabelDecorator implements ReferenceFieldLabelDecorator {
+
+    @Override
+    public String getLabel(String originalLabel, Ref reference) {
+        return reference.getName();
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/IconUtils.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import com.redhat.thermostat.client.swing.components.EmptyIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+
+public class IconUtils {
+    public static Icon resizeIcon(Icon source, int size) {
+        Icon canvas = new EmptyIcon(size, size);
+        
+        float v1 = canvas.getIconWidth() / 2;
+        float v0 = source.getIconWidth() / 2; 
+                
+        int x = (int) (v1 - v0 + 0.5);
+                
+        v1 = canvas.getIconHeight() / 2;
+        v0 = source.getIconHeight() / 2; 
+        
+        int y = (int) (v1 - v0 + 0.5);
+
+        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
+                                                canvas.getIconHeight(),
+                                                BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = (Graphics2D) image.getGraphics();
+        graphics.drawImage(source.getImage(), x, y, null);
+        
+        return new Icon(image);
+    }
+
+    public static Icon overlay(Icon canvas, Icon overlay, int x, int y) {
+        BufferedImage image = new BufferedImage(canvas.getIconWidth(),
+                                                canvas.getIconHeight(),
+                                                BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = (Graphics2D) image.getGraphics();
+        canvas.paintIcon(null, graphics, 0, 0);
+        
+        graphics.drawImage(overlay.getImage(), x, y, null);
+        graphics.dispose();
+        
+        return new Icon(image);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    NET_IFACE_LABEL_MENU_NAME,
+    NET_IFACE_LABEL_MENU_DESCRIPTION,
+    NET_IFACE_LABEL_MENU_PATH,
+    NET_IFACE_LABEL_DECORATOR,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.client.filter.host.swing.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/host/swing/ThermostatVmMainLabelDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class ThermostatVmMainLabelDecorator implements ReferenceFieldLabelDecorator {
+
+    // duplicated in the startup scripts
+    private static final String MAIN_CLASS =
+            "com.redhat.thermostat.main.Thermostat";
+    // duplicated in the startup scripts
+    private static final String COMMAND_CHANNEL_CLASS =
+            "com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain";
+
+    private static final Set<String> KNOWN_STARTUP_CLASSES;
+
+    static {
+        KNOWN_STARTUP_CLASSES = new TreeSet<>();
+        KNOWN_STARTUP_CLASSES.add(MAIN_CLASS);
+        KNOWN_STARTUP_CLASSES.add(COMMAND_CHANNEL_CLASS);
+    }
+
+    private VmInfoDAO dao;
+
+    public ThermostatVmMainLabelDecorator(VmInfoDAO dao) {
+        this.dao = dao;
+    }
+
+    @Override
+    public String getLabel(String originalLabel, Ref reference) {
+
+        if (!(reference instanceof VmRef) ||
+            !KNOWN_STARTUP_CLASSES.contains(reference.getName())) {
+            return originalLabel;
+        }
+        VmInfo vmInfo = dao.getVmInfo((VmRef) reference);
+        if (!KNOWN_STARTUP_CLASSES.contains(vmInfo.getMainClass())) {
+            return originalLabel;
+        }
+        return createLabel(vmInfo);
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST + 1;
+    }
+
+    /**
+     * This method returns a short version for the VmInfo object command line.
+     * @param info the vm info object from which take information.
+     * @return the resulting string 
+     */
+    private String createLabel(VmInfo info) {
+        if (info.getMainClass().equals(COMMAND_CHANNEL_CLASS)) {
+            return createLabelForCommandChannel(info);
+        }
+
+        return createLabelForRegularCommand(info);
+    }
+
+    private String createLabelForCommandChannel(VmInfo info) {
+        return "Thermostat (command channel)";
+    }
+
+    private String createLabelForRegularCommand(VmInfo info) {
+        String commandLine = info.getJavaCommandLine();
+
+        // heuristic: take the first non-option argument
+
+        // FIXME this doesn't work if --boot-delegation appears before the
+        // subcommand. --boot-delegation requires a separate value.
+        String[] parts = commandLine.split("\\s+");
+        parts = Arrays.copyOfRange(parts, 1, parts.length);
+
+        int argumentCount = 0;
+        StringBuilder result = new StringBuilder();
+        result.append("Thermostat ");
+        for (String part : parts) {
+            if (part.startsWith("--")) {
+                continue;
+            }
+            result.append(part).append(" ");
+            argumentCount++;
+            if (argumentCount == 1) {
+                break;
+            }
+        }
+        return result.toString().trim();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/DeadVMIconDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import java.awt.Paint;
+
+import com.redhat.thermostat.client.filter.internal.host.swing.IconUtils;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class DeadVMIconDecorator implements ReferenceFieldIconDecorator {
+
+    private static VmInfoDAO vmDao;
+    private static HostInfoDAO hostDao;
+    
+    public static Icon DEAD;
+    public static Icon DEAD_SELECTED;
+    
+    private static DeadVMIconDecorator theInstance;
+    
+    public static synchronized DeadVMIconDecorator getInstance(VmInfoDAO vmDao,
+                                                               HostInfoDAO hostDao,
+                                                               UIDefaults uiDefaults)
+    {
+        if (theInstance == null) {
+            DeadVMIconDecorator.vmDao = vmDao;
+            DeadVMIconDecorator.hostDao = hostDao;
+
+            int size = uiDefaults.getIconDecorationSize();
+            Paint color = uiDefaults.getDecorationIconColor();
+
+            DEAD = new FontAwesomeIcon('\uf00d', size, color);
+            DEAD_SELECTED = new FontAwesomeIcon('\uf00d', size, color);
+            
+            theInstance = new DeadVMIconDecorator();
+        }
+        
+        return theInstance;
+    }
+    
+    private DeadVMIconDecorator() {}
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST + 100;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, DEAD);
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        return doOverlay(originalIcon, reference, DEAD_SELECTED);
+    }
+    
+    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
+        
+        if (!(reference instanceof VmRef)) {
+            return originalIcon;
+        }
+        
+        boolean match = true;
+        
+        VmRef vm = (VmRef) reference;
+        if (hostDao.isAlive(vm.getHostRef())) {
+            VmInfo vmInfo = vmDao.getVmInfo(vm);
+            match = !vmInfo.isAlive();
+            
+        } else {
+            match = true;
+        }
+     
+        PlatformIcon result = originalIcon;
+        if (match) {
+            Icon canvas = (Icon) originalIcon;
+            int y = canvas.getIconHeight() - overlay.getIconHeight();
+            result = IconUtils.overlay(canvas, overlay, 0, y);            
+        }
+        
+        return result;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    PID_LABEL_MENU_NAME,
+    PID_LABEL_MENU_DESCRIPTION,
+    PID_LABEL_MENU_PATH,
+    PID_LABEL_DECORATOR,
+
+    STARTTIME_LABEL_MENU_NAME,
+    STARTTIME_LABEL_MENU_DESCRIPTION,
+    STARTTIME_LABEL_MENU_PATH,
+    STARTTIME_LABEL_DECORATOR,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.client.filter.vm.swing.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMFilterActivator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.client.filter.internal.host.swing.DeadHostIconDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostIconDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostNetworkInterfaceLabelDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostNetworkInterfaceLabelMenuAction;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostVmMainLabelDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.ThermostatVmMainLabelDecorator;
+import com.redhat.thermostat.client.swing.ReferenceFieldDecoratorLayout;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+public class VMFilterActivator implements BundleActivator {
+
+    @SuppressWarnings("rawtypes")
+    private final List<ServiceRegistration> registeredServices = Collections.synchronizedList(new ArrayList<ServiceRegistration>());
+
+    private MultipleServiceTracker tracker;
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        
+        Class<?> [] services =  new Class<?> [] {
+                VmInfoDAO.class,
+                HostInfoDAO.class,
+                NetworkInterfaceInfoDAO.class,
+                UIDefaults.class,
+        };
+        
+        tracker = new MultipleServiceTracker(context, services, new MultipleServiceTracker.Action() {
+            
+            @Override
+            public void dependenciesUnavailable() {
+                Iterator<ServiceRegistration> iterator = registeredServices.iterator();
+                while(iterator.hasNext()) {
+                    ServiceRegistration registration = iterator.next();
+                    registration.unregister();
+                    iterator.remove();
+                }
+            }
+            
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                ServiceRegistration registration = null;
+
+                UIDefaults uiDefaults = (UIDefaults) services.get(UIDefaults.class.getName());
+                
+                VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                HostInfoDAO hostDao = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+
+                Dictionary<String, String> decoratorProperties = new Hashtable<>();
+                
+                VMPidLabelDecorator vmPidLabelDecorator = new VMPidLabelDecorator(vmDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
+
+                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
+                        vmPidLabelDecorator, decoratorProperties);
+
+                registeredServices.add(registration);
+
+                VMPidLabelMenuAction vmPidMenuAction = new VMPidLabelMenuAction(vmPidLabelDecorator);
+                registration = context.registerService(MenuAction.class.getName(),
+                        vmPidMenuAction, null);
+
+                registeredServices.add(registration);
+
+                VMStartTimeLabelDecorator vmStartTimeLabelDecorator = new VMStartTimeLabelDecorator(vmDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
+                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
+
+                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
+                        vmStartTimeLabelDecorator, decoratorProperties);
+
+                registeredServices.add(registration);
+
+                VMStartTimeLabelMenuAction vmStartTimeLabelMenuAction = new VMStartTimeLabelMenuAction(vmStartTimeLabelDecorator);
+                registration = context.registerService(MenuAction.class.getName(),
+                        vmStartTimeLabelMenuAction, null);
+
+                registeredServices.add(registration);
+
+                NetworkInterfaceInfoDAO networkDao = (NetworkInterfaceInfoDAO)
+                            services.get(NetworkInterfaceInfoDAO.class.getName());
+
+                HostNetworkInterfaceLabelDecorator hostLabelDecorator =
+                            new HostNetworkInterfaceLabelDecorator(networkDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
+                
+                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
+                                                       hostLabelDecorator, decoratorProperties);
+                registeredServices.add(registration);
+
+                HostNetworkInterfaceLabelMenuAction hostNetworkMenuAction = new HostNetworkInterfaceLabelMenuAction(hostLabelDecorator);
+                registration = context.registerService(MenuAction.class.getName(), hostNetworkMenuAction, null);
+
+                registeredServices.add(registration);
+                
+                HostIconDecorator hostIconDecorator =
+                            HostIconDecorator.createInstance(uiDefaults);
+                DeadHostIconDecorator deadHostIconDecorator =
+                            DeadHostIconDecorator.createInstance(hostDao, uiDefaults, hostIconDecorator);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       deadHostIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                VMIconDecorator livingVMIconDecorator = VMIconDecorator.getInstance(uiDefaults);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       livingVMIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                DeadVMIconDecorator deadVMIconDecorator =
+                            DeadVMIconDecorator.getInstance(vmDao, hostDao, uiDefaults);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
+                                                       deadVMIconDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                HostVmMainLabelDecorator mainDecorator = new HostVmMainLabelDecorator();
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
+                                        ReferenceFieldDecoratorLayout.LABEL_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
+                                                       mainDecorator, decoratorProperties);
+                registeredServices.add(registration);
+                
+                ThermostatVmMainLabelDecorator thermostatDecorator = new ThermostatVmMainLabelDecorator(vmDao);
+                decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
+                        ReferenceFieldDecoratorLayout.LABEL_MAIN.name());
+                
+                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
+                        thermostatDecorator, decoratorProperties);
+                
+                registeredServices.add(registration);
+
+            }
+        });
+        tracker.open();
+    }
+    
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+        for (ServiceRegistration registration : registeredServices) {
+            registration.unregister();
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMIconDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import java.awt.Paint;
+
+import com.redhat.thermostat.client.filter.internal.host.swing.IconUtils;
+import com.redhat.thermostat.client.swing.IconResource;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.swing.components.CompositeIcon;
+import com.redhat.thermostat.client.swing.components.Icon;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+
+public class VMIconDecorator implements ReferenceFieldIconDecorator {
+
+    private static Icon ICON;
+    private static Icon SELECTED;
+
+    private static VMIconDecorator theInstance;
+    public static synchronized VMIconDecorator getInstance(UIDefaults uiDefaults) {
+        
+        if (theInstance == null) {            
+            int size = uiDefaults.getReferenceFieldDefaultIconSize();
+            Paint fg = uiDefaults.getReferenceFieldIconColor();
+            Paint selected = uiDefaults.getReferenceFieldIconSelectedColor();
+            
+            Icon vmIcon = IconUtils.resizeIcon(IconResource.JAVA_APPLICATION_24.getIcon(), size);
+            
+            ICON = CompositeIcon.createDefaultComposite(vmIcon, fg);
+            SELECTED = CompositeIcon.createDefaultComposite(vmIcon, selected);
+            
+            theInstance = new VMIconDecorator();
+        }
+        
+        return theInstance;
+    }
+    
+    private VMIconDecorator() {}
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_FIRST;
+    }
+    
+    @Override
+    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof VmRef) {
+            return ICON;
+        } else {
+            return originalIcon;
+        }
+    }
+    
+    @Override
+    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
+        if (reference instanceof VmRef) {
+            return SELECTED;
+        } else {
+            return originalIcon;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Appends the given ReferenceField label with the PID of the current
+ * {@link VmRef}.
+ */
+public class VMPidLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private VmInfoDAO dao;
+    private boolean enabled = false;
+    private final Map<VmRef, Integer> referencePidMap = new HashMap<>();
+
+    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
+    
+    public VMPidLabelDecorator(VmInfoDAO dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public int getOrderValue() {
+        return ORDER_CPU_GROUP;
+    }
+    
+    @Override
+    public String getLabel(String originalLabel, Ref reference) {
+
+        if (!isEnabled()) {
+            return originalLabel;
+        }
+
+        if (!(reference instanceof VmRef)) {
+            return originalLabel;
+        }
+
+        VmRef vmRef = (VmRef) reference;
+
+        if (!referencePidMap.containsKey(vmRef)) {
+            int pid =  dao.getVmInfo(vmRef).getVmPid();
+            referencePidMap.put(vmRef, pid);
+        }
+
+        String pid = Integer.toString(referencePidMap.get(vmRef));
+        return t.localize(LocaleResources.PID_LABEL_DECORATOR, originalLabel, pid).getContents();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (this.enabled != enabled) {
+            this.enabled = enabled;
+            notifier.fireAction(StatusEvent.STATUS_CHANGED);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.removeActionListener(listener);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelMenuAction.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class VMPidLabelMenuAction implements MenuAction {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private VMPidLabelDecorator decorator;
+
+    public VMPidLabelMenuAction(VMPidLabelDecorator decorator) {
+        this.decorator = decorator;
+    }
+
+    @Override
+    public LocalizedString getName() {
+        return t.localize(LocaleResources.PID_LABEL_MENU_NAME);
+    }
+
+    @Override
+    public LocalizedString getDescription() {
+        return t.localize(LocaleResources.PID_LABEL_MENU_DESCRIPTION);
+    }
+
+    @Override
+    public void execute() {
+        decorator.setEnabled(!decorator.isEnabled());
+    }
+
+    @Override
+    public Type getType() {
+        return MenuAction.Type.CHECK;
+    }
+
+    @Override
+    public LocalizedString[] getPath() {
+        return new LocalizedString[] { t.localize(LocaleResources.PID_LABEL_MENU_PATH), getName() };
+    }
+
+    @Override
+    public int sortOrder() {
+        return SORT_TOP + 10;
+    }
+
+    @Override
+    public String getPersistenceID() {
+        return MENU_KEY + "-pid-labels";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelDecorator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VMStartTimeLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private VmInfoDAO dao;
+    private boolean enabled = false;
+    private final Map<VmRef, Date> referenceTimestampMap = new HashMap<>();
+
+    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
+
+    public VMStartTimeLabelDecorator(VmInfoDAO dao) {
+        this.dao = dao;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (this.enabled != enabled) {
+            this.enabled = enabled;
+            notifier.fireAction(StatusEvent.STATUS_CHANGED);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
+        notifier.removeActionListener(listener);
+    }
+
+    @Override
+    public String getLabel(String originalLabel, Ref reference) {
+        if (!isEnabled()) {
+            return originalLabel;
+        }
+
+        if (!(reference instanceof VmRef)) {
+            return originalLabel;
+        }
+
+        VmRef ref = (VmRef) reference;
+
+        if (!referenceTimestampMap.containsKey(ref)) {
+            long timestamp = dao.getVmInfo(ref).getStartTimeStamp();
+            referenceTimestampMap.put(ref, new Date(timestamp));
+        }
+
+        String timestamp = Clock.DEFAULT_DATE_FORMAT.format(referenceTimestampMap.get(ref));
+        return t.localize(LocaleResources.STARTTIME_LABEL_DECORATOR, originalLabel, timestamp).getContents();
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_CODE_GROUP;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelMenuAction.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class VMStartTimeLabelMenuAction implements MenuAction {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private VMStartTimeLabelDecorator decorator;
+
+    public VMStartTimeLabelMenuAction(VMStartTimeLabelDecorator decorator) {
+        this.decorator = decorator;
+    }
+
+    @Override
+    public LocalizedString getName() {
+        return t.localize(LocaleResources.STARTTIME_LABEL_MENU_NAME);
+    }
+
+    @Override
+    public LocalizedString getDescription() {
+        return t.localize(LocaleResources.STARTTIME_LABEL_MENU_DESCRIPTION);
+    }
+
+    @Override
+    public void execute() {
+        decorator.setEnabled(!decorator.isEnabled());
+    }
+
+    @Override
+    public Type getType() {
+        return Type.CHECK;
+    }
+
+    @Override
+    public LocalizedString[] getPath() {
+        return new LocalizedString[] { t.localize(LocaleResources.STARTTIME_LABEL_MENU_PATH), getName() };
+    }
+
+    @Override
+    public int sortOrder() {
+        return SORT_TOP + 15;
+    }
+
+    @Override
+    public String getPersistenceID() {
+        return MENU_KEY + "-start-time-labels";
+    }
+}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/DeadVMIconDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import java.awt.Paint;
-
-import com.redhat.thermostat.client.filter.host.swing.IconUtils;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
-import com.redhat.thermostat.client.swing.components.Icon;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class DeadVMIconDecorator implements ReferenceFieldIconDecorator {
-
-    private static VmInfoDAO vmDao;
-    private static HostInfoDAO hostDao;
-    
-    public static Icon DEAD;
-    public static Icon DEAD_SELECTED;
-    
-    private static DeadVMIconDecorator theInstance;
-    
-    public static synchronized DeadVMIconDecorator getInstance(VmInfoDAO vmDao,
-                                                               HostInfoDAO hostDao,
-                                                               UIDefaults uiDefaults)
-    {
-        if (theInstance == null) {
-            DeadVMIconDecorator.vmDao = vmDao;
-            DeadVMIconDecorator.hostDao = hostDao;
-
-            int size = uiDefaults.getIconDecorationSize();
-            Paint color = uiDefaults.getDecorationIconColor();
-
-            DEAD = new FontAwesomeIcon('\uf00d', size, color);
-            DEAD_SELECTED = new FontAwesomeIcon('\uf00d', size, color);
-            
-            theInstance = new DeadVMIconDecorator();
-        }
-        
-        return theInstance;
-    }
-    
-    private DeadVMIconDecorator() {}
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST + 100;
-    }
-    
-    @Override
-    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
-        return doOverlay(originalIcon, reference, DEAD);
-    }
-    
-    @Override
-    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
-        return doOverlay(originalIcon, reference, DEAD_SELECTED);
-    }
-    
-    public PlatformIcon doOverlay(PlatformIcon originalIcon, Ref reference, Icon overlay) {
-        
-        if (!(reference instanceof VmRef)) {
-            return originalIcon;
-        }
-        
-        boolean match = true;
-        
-        VmRef vm = (VmRef) reference;
-        if (hostDao.isAlive(vm.getHostRef())) {
-            VmInfo vmInfo = vmDao.getVmInfo(vm);
-            match = !vmInfo.isAlive();
-            
-        } else {
-            match = true;
-        }
-     
-        PlatformIcon result = originalIcon;
-        if (match) {
-            Icon canvas = (Icon) originalIcon;
-            int y = canvas.getIconHeight() - overlay.getIconHeight();
-            result = IconUtils.overlay(canvas, overlay, 0, y);            
-        }
-        
-        return result;
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    PID_LABEL_MENU_NAME,
-    PID_LABEL_MENU_DESCRIPTION,
-    PID_LABEL_MENU_PATH,
-    PID_LABEL_DECORATOR,
-
-    STARTTIME_LABEL_MENU_NAME,
-    STARTTIME_LABEL_MENU_DESCRIPTION,
-    STARTTIME_LABEL_MENU_PATH,
-    STARTTIME_LABEL_DECORATOR,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.client.filter.vm.swing.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.client.filter.host.swing.HostNetworkInterfaceLabelMenuAction;
-import com.redhat.thermostat.client.ui.MenuAction;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.client.filter.host.swing.DeadHostIconDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostIconDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostNetworkInterfaceLabelDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostVmMainLabelDecorator;
-import com.redhat.thermostat.client.filter.host.swing.ThermostatVmMainLabelDecorator;
-import com.redhat.thermostat.client.swing.ReferenceFieldDecoratorLayout;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-public class VMFilterActivator implements BundleActivator {
-
-    @SuppressWarnings("rawtypes")
-    private final List<ServiceRegistration> registeredServices = Collections.synchronizedList(new ArrayList<ServiceRegistration>());
-
-    private MultipleServiceTracker tracker;
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        
-        Class<?> [] services =  new Class<?> [] {
-                VmInfoDAO.class,
-                HostInfoDAO.class,
-                NetworkInterfaceInfoDAO.class,
-                UIDefaults.class,
-        };
-        
-        tracker = new MultipleServiceTracker(context, services, new MultipleServiceTracker.Action() {
-            
-            @Override
-            public void dependenciesUnavailable() {
-                Iterator<ServiceRegistration> iterator = registeredServices.iterator();
-                while(iterator.hasNext()) {
-                    ServiceRegistration registration = iterator.next();
-                    registration.unregister();
-                    iterator.remove();
-                }
-            }
-            
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                ServiceRegistration registration = null;
-
-                UIDefaults uiDefaults = (UIDefaults) services.get(UIDefaults.class.getName());
-                
-                VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
-                HostInfoDAO hostDao = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
-
-                Dictionary<String, String> decoratorProperties = new Hashtable<>();
-                
-                VMPidLabelDecorator vmPidLabelDecorator = new VMPidLabelDecorator(vmDao);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
-
-                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                        vmPidLabelDecorator, decoratorProperties);
-
-                registeredServices.add(registration);
-
-                VMPidLabelMenuAction vmPidMenuAction = new VMPidLabelMenuAction(vmPidLabelDecorator);
-                registration = context.registerService(MenuAction.class.getName(),
-                        vmPidMenuAction, null);
-
-                registeredServices.add(registration);
-
-                VMStartTimeLabelDecorator vmStartTimeLabelDecorator = new VMStartTimeLabelDecorator(vmDao);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
-                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
-
-                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                        vmStartTimeLabelDecorator, decoratorProperties);
-
-                registeredServices.add(registration);
-
-                VMStartTimeLabelMenuAction vmStartTimeLabelMenuAction = new VMStartTimeLabelMenuAction(vmStartTimeLabelDecorator);
-                registration = context.registerService(MenuAction.class.getName(),
-                        vmStartTimeLabelMenuAction, null);
-
-                registeredServices.add(registration);
-
-                NetworkInterfaceInfoDAO networkDao = (NetworkInterfaceInfoDAO)
-                            services.get(NetworkInterfaceInfoDAO.class.getName());
-
-                HostNetworkInterfaceLabelDecorator hostLabelDecorator =
-                            new HostNetworkInterfaceLabelDecorator(networkDao);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.LABEL_INFO.name());
-                
-                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                                                       hostLabelDecorator, decoratorProperties);
-                registeredServices.add(registration);
-
-                HostNetworkInterfaceLabelMenuAction hostNetworkMenuAction = new HostNetworkInterfaceLabelMenuAction(hostLabelDecorator);
-                registration = context.registerService(MenuAction.class.getName(), hostNetworkMenuAction, null);
-
-                registeredServices.add(registration);
-                
-                HostIconDecorator hostIconDecorator =
-                            HostIconDecorator.createInstance(uiDefaults);
-                DeadHostIconDecorator deadHostIconDecorator =
-                            DeadHostIconDecorator.createInstance(hostDao, uiDefaults, hostIconDecorator);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
-                
-                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
-                                                       deadHostIconDecorator, decoratorProperties);
-                registeredServices.add(registration);
-                
-                VMIconDecorator livingVMIconDecorator = VMIconDecorator.getInstance(uiDefaults);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
-                
-                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
-                                                       livingVMIconDecorator, decoratorProperties);
-                registeredServices.add(registration);
-                
-                DeadVMIconDecorator deadVMIconDecorator =
-                            DeadVMIconDecorator.getInstance(vmDao, hostDao, uiDefaults);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldIconDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.ICON_MAIN.name());
-                
-                registration = context.registerService(ReferenceFieldIconDecorator.class.getName(),
-                                                       deadVMIconDecorator, decoratorProperties);
-                registeredServices.add(registration);
-                
-                HostVmMainLabelDecorator mainDecorator = new HostVmMainLabelDecorator();
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
-                                        ReferenceFieldDecoratorLayout.LABEL_MAIN.name());
-                
-                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                                                       mainDecorator, decoratorProperties);
-                registeredServices.add(registration);
-                
-                ThermostatVmMainLabelDecorator thermostatDecorator = new ThermostatVmMainLabelDecorator(vmDao);
-                decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(ReferenceFieldLabelDecorator.ID,
-                        ReferenceFieldDecoratorLayout.LABEL_MAIN.name());
-                
-                registration = context.registerService(ReferenceFieldLabelDecorator.class.getName(),
-                        thermostatDecorator, decoratorProperties);
-                
-                registeredServices.add(registration);
-
-            }
-        });
-        tracker.open();
-    }
-    
-    @SuppressWarnings("rawtypes")
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        tracker.close();
-        for (ServiceRegistration registration : registeredServices) {
-            registration.unregister();
-        }
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMIconDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import java.awt.Paint;
-
-import com.redhat.thermostat.client.filter.host.swing.IconUtils;
-import com.redhat.thermostat.client.swing.IconResource;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.swing.components.CompositeIcon;
-import com.redhat.thermostat.client.swing.components.Icon;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-
-public class VMIconDecorator implements ReferenceFieldIconDecorator {
-
-    private static Icon ICON;
-    private static Icon SELECTED;
-
-    private static VMIconDecorator theInstance;
-    public static synchronized VMIconDecorator getInstance(UIDefaults uiDefaults) {
-        
-        if (theInstance == null) {            
-            int size = uiDefaults.getReferenceFieldDefaultIconSize();
-            Paint fg = uiDefaults.getReferenceFieldIconColor();
-            Paint selected = uiDefaults.getReferenceFieldIconSelectedColor();
-            
-            Icon vmIcon = IconUtils.resizeIcon(IconResource.JAVA_APPLICATION_24.getIcon(), size);
-            
-            ICON = CompositeIcon.createDefaultComposite(vmIcon, fg);
-            SELECTED = CompositeIcon.createDefaultComposite(vmIcon, selected);
-            
-            theInstance = new VMIconDecorator();
-        }
-        
-        return theInstance;
-    }
-    
-    private VMIconDecorator() {}
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_FIRST;
-    }
-    
-    @Override
-    public PlatformIcon getIcon(PlatformIcon originalIcon, Ref reference) {
-        if (reference instanceof VmRef) {
-            return ICON;
-        } else {
-            return originalIcon;
-        }
-    }
-    
-    @Override
-    public PlatformIcon getSelectedIcon(PlatformIcon originalIcon, Ref reference) {
-        if (reference instanceof VmRef) {
-            return SELECTED;
-        } else {
-            return originalIcon;
-        }
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Appends the given ReferenceField label with the PID of the current
- * {@link VmRef}.
- */
-public class VMPidLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private VmInfoDAO dao;
-    private boolean enabled = false;
-    private final Map<VmRef, Integer> referencePidMap = new HashMap<>();
-
-    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
-    
-    public VMPidLabelDecorator(VmInfoDAO dao) {
-        this.dao = dao;
-    }
-    
-    @Override
-    public int getOrderValue() {
-        return ORDER_CPU_GROUP;
-    }
-    
-    @Override
-    public String getLabel(String originalLabel, Ref reference) {
-
-        if (!isEnabled()) {
-            return originalLabel;
-        }
-
-        if (!(reference instanceof VmRef)) {
-            return originalLabel;
-        }
-
-        VmRef vmRef = (VmRef) reference;
-
-        if (!referencePidMap.containsKey(vmRef)) {
-            int pid =  dao.getVmInfo(vmRef).getVmPid();
-            referencePidMap.put(vmRef, pid);
-        }
-
-        String pid = Integer.toString(referencePidMap.get(vmRef));
-        return t.localize(LocaleResources.PID_LABEL_DECORATOR, originalLabel, pid).getContents();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        if (this.enabled != enabled) {
-            this.enabled = enabled;
-            notifier.fireAction(StatusEvent.STATUS_CHANGED);
-        }
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.removeActionListener(listener);
-    }
-}
-
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelMenuAction.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-
-public class VMPidLabelMenuAction implements MenuAction {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private VMPidLabelDecorator decorator;
-
-    public VMPidLabelMenuAction(VMPidLabelDecorator decorator) {
-        this.decorator = decorator;
-    }
-
-    @Override
-    public LocalizedString getName() {
-        return t.localize(LocaleResources.PID_LABEL_MENU_NAME);
-    }
-
-    @Override
-    public LocalizedString getDescription() {
-        return t.localize(LocaleResources.PID_LABEL_MENU_DESCRIPTION);
-    }
-
-    @Override
-    public void execute() {
-        decorator.setEnabled(!decorator.isEnabled());
-    }
-
-    @Override
-    public Type getType() {
-        return MenuAction.Type.CHECK;
-    }
-
-    @Override
-    public LocalizedString[] getPath() {
-        return new LocalizedString[] { t.localize(LocaleResources.PID_LABEL_MENU_PATH), getName() };
-    }
-
-    @Override
-    public int sortOrder() {
-        return SORT_TOP + 10;
-    }
-
-    @Override
-    public String getPersistenceID() {
-        return MENU_KEY + "-pid-labels";
-    }
-}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelDecorator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-public class VMStartTimeLabelDecorator implements ToggleableReferenceFieldLabelDecorator {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private VmInfoDAO dao;
-    private boolean enabled = false;
-    private final Map<VmRef, Date> referenceTimestampMap = new HashMap<>();
-
-    private final ActionNotifier<StatusEvent> notifier = new ActionNotifier<>(this);
-
-    public VMStartTimeLabelDecorator(VmInfoDAO dao) {
-        this.dao = dao;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        if (this.enabled != enabled) {
-            this.enabled = enabled;
-            notifier.fireAction(StatusEvent.STATUS_CHANGED);
-        }
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void addStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeStatusEventListener(ActionListener<StatusEvent> listener) {
-        notifier.removeActionListener(listener);
-    }
-
-    @Override
-    public String getLabel(String originalLabel, Ref reference) {
-        if (!isEnabled()) {
-            return originalLabel;
-        }
-
-        if (!(reference instanceof VmRef)) {
-            return originalLabel;
-        }
-
-        VmRef ref = (VmRef) reference;
-
-        if (!referenceTimestampMap.containsKey(ref)) {
-            long timestamp = dao.getVmInfo(ref).getStartTimeStamp();
-            referenceTimestampMap.put(ref, new Date(timestamp));
-        }
-
-        String timestamp = Clock.DEFAULT_DATE_FORMAT.format(referenceTimestampMap.get(ref));
-        return t.localize(LocaleResources.STARTTIME_LABEL_DECORATOR, originalLabel, timestamp).getContents();
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_CODE_GROUP;
-    }
-}
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelMenuAction.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-
-public class VMStartTimeLabelMenuAction implements MenuAction {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private VMStartTimeLabelDecorator decorator;
-
-    public VMStartTimeLabelMenuAction(VMStartTimeLabelDecorator decorator) {
-        this.decorator = decorator;
-    }
-
-    @Override
-    public LocalizedString getName() {
-        return t.localize(LocaleResources.STARTTIME_LABEL_MENU_NAME);
-    }
-
-    @Override
-    public LocalizedString getDescription() {
-        return t.localize(LocaleResources.STARTTIME_LABEL_MENU_DESCRIPTION);
-    }
-
-    @Override
-    public void execute() {
-        decorator.setEnabled(!decorator.isEnabled());
-    }
-
-    @Override
-    public Type getType() {
-        return Type.CHECK;
-    }
-
-    @Override
-    public LocalizedString[] getPath() {
-        return new LocalizedString[] { t.localize(LocaleResources.STARTTIME_LABEL_MENU_PATH), getName() };
-    }
-
-    @Override
-    public int sortOrder() {
-        return SORT_TOP + 15;
-    }
-
-    @Override
-    public String getPersistenceID() {
-        return MENU_KEY + "-start-time-labels";
-    }
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-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 org.junit.experimental.categories.Category;
-
-import com.redhat.thermostat.annotations.internal.CacioTest;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-
-@Category(CacioTest.class)
-public class DeadHostIconDecoratorTest {
-
-    private DeadHostIconDecorator decorator;
-
-    @Before
-    public void setUp() {
-        final int SOME_SIZE = 10;
-
-        UIDefaults uiDefaults = mock(UIDefaults.class);
-        when(uiDefaults.getIconDecorationSize()).thenReturn(SOME_SIZE);
-        when(uiDefaults.getReferenceFieldDefaultIconSize()).thenReturn(SOME_SIZE);
-
-        HostInfoDAO dao = mock(HostInfoDAO.class);
-
-        HostIconDecorator parent = HostIconDecorator.createInstance(uiDefaults);
-
-        decorator = DeadHostIconDecorator.createInstance(dao, uiDefaults, parent);
-    }
-
-    @Test
-    public void verifyGetIconWithNullProducesValidIcon() {
-        PlatformIcon icon = decorator.getIcon(null, mock(HostRef.class));
-        assertNotNull(icon);
-    }
-
-    @Test
-    public void verifyGetIconWithNotAHostRefProducesOriginalIcon() {
-        PlatformIcon icon = decorator.getIcon(null, mock(VmRef.class));
-        assertNull(icon);
-    }
-
-    @Test
-    public void verifyGetSelectedIconWithNullProducesValidIcon() {
-        PlatformIcon icon = decorator.getSelectedIcon(null, mock(HostRef.class));
-        assertNotNull(icon);
-    }
-
-    @Test
-    public void verifyGetSelectedIconWithNotAHostRefProducesOriginalIcon() {
-        PlatformIcon icon = decorator.getSelectedIcon(null, mock(VmRef.class));
-        assertNull(icon);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-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 java.awt.Color;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.redhat.thermostat.annotations.internal.CacioTest;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.ui.PlatformIcon;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-
-@Category(CacioTest.class)
-public class HostIconDecoratorTest {
-
-    private HostIconDecorator decorator;
-
-    @Before
-    public void setUp() {
-        final int SOME_SIZE = 10;
-        final Color SOME_COLOR = Color.BLACK;
-        UIDefaults ui = mock(UIDefaults.class);
-        when(ui.getReferenceFieldDefaultIconSize()).thenReturn(SOME_SIZE);
-        when(ui.getReferenceFieldIconColor()).thenReturn(SOME_COLOR);
-
-        decorator = HostIconDecorator.createInstance(ui);
-    }
-
-    @Test
-    public void verifyGetIconProducesAnIconForHosts() {
-        HostRef hostRef = mock(HostRef.class);
-        PlatformIcon icon = decorator.getIcon(null, hostRef);
-        assertNotNull(icon);
-    }
-
-    @Test
-    public void testGetIconIgnoresVmRef() {
-        VmRef vmRef = mock(VmRef.class);
-        PlatformIcon icon = decorator.getIcon(null, vmRef);
-        assertNull(icon);
-    }
-
-    @Test
-    public void verifyGetSelectedIconProducesAnIconForHosts() {
-        HostRef hostRef = mock(HostRef.class);
-        PlatformIcon icon = decorator.getSelectedIcon(null, hostRef);
-        assertNotNull(icon);
-    }
-
-    @Test
-    public void testGetSelectedIconIgnoresVmRef() {
-        VmRef vmRef = mock(VmRef.class);
-        PlatformIcon icon = decorator.getSelectedIcon(null, vmRef);
-        assertNull(icon);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostNetworkInterfaceLabelDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.storage.core.VmRef;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-
-public class HostNetworkInterfaceLabelDecoratorTest {
-
-    private NetworkInterfaceInfoDAO dao;
-    private HostNetworkInterfaceLabelDecorator decorator;
-
-    @Before
-    public void setup() {
-        dao = mock(NetworkInterfaceInfoDAO.class);
-        decorator = new HostNetworkInterfaceLabelDecorator(dao);
-    }
-
-    @Test
-    public void testBasicWithNetworkInterfaces() {
-        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
-        String ip = "192.168.0.1";
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
-        assertEquals(ip, info.getInterfaceName());
-        info.setIp4Addr(ip);
-        networkList.add(info);
-        HostRef mockHostRef = mock(HostRef.class);
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
-        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
-        assertEquals("192.168.0.1", decoratedLabel);
-    }
-    
-    @Test
-    public void testBasicTwoIfaces() {
-        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
-        String ip = "192.168.0.1";
-        String ip2 = "10.0.0.1";
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
-        NetworkInterfaceInfo info2 = new NetworkInterfaceInfo("foo-agent", ip2);
-        assertEquals(ip2, info2.getInterfaceName());
-        assertEquals(ip, info.getInterfaceName());
-        info.setIp4Addr(ip);
-        info2.setIp4Addr(ip2);
-        networkList.add(info);
-        networkList.add(info2);
-        HostRef mockHostRef = mock(HostRef.class);
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
-        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
-        assertEquals("192.168.0.1; 10.0.0.1", decoratedLabel);
-    }
-    
-    @Test
-    public void testWithEmptyIp4AddrAndNoIPv6Addr() {
-        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
-        String ip = "192.168.0.1";
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
-        assertEquals(ip, info.getInterfaceName());
-        info.setIp4Addr(""); // empty string
-        networkList.add(info);
-        HostRef mockHostRef = mock(HostRef.class);
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
-        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
-        assertEquals("", decoratedLabel);
-    }
-    
-    /**
-     * This should not throw IndexOutOfBoundsException
-     */
-    @Test
-    public void testWithNoNetworkInterfaces() {
-        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
-        HostRef mockHostRef = mock(HostRef.class);
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
-        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
-        assertEquals("", decoratedLabel);
-    }
-
-    @Test
-    public void verifyGetLabelCaches() {
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(isA(HostRef.class))).thenReturn(new ArrayList<NetworkInterfaceInfo>());
-        HostRef ref = mock(HostRef.class);
-
-        decorator.getLabel("", ref);
-        verify(dao).getNetworkInterfaces(ref);
-
-        decorator.getLabel("", ref);
-        verify(dao).getNetworkInterfaces(ref); // still only once -> cached after first call
-    }
-
-    @Test
-    public void verifyGetLabelAppends() {
-        decorator.setEnabled(true);
-        when(dao.getNetworkInterfaces(isA(HostRef.class))).thenReturn(new ArrayList<NetworkInterfaceInfo>());
-        HostRef ref = mock(HostRef.class);
-
-        String str = decorator.getLabel("Foo", ref).trim();
-        assertThat(str, containsString("Foo"));
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenDisabled() {
-        decorator.setEnabled(false);
-        decorator.getLabel("", mock(HostRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenWrongRefType() {
-        decorator.setEnabled(true);
-        decorator.getLabel("", mock(VmRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void testSetEnabled() {
-        decorator.setEnabled(true);
-        assertThat(decorator.isEnabled(), is(true));
-        decorator.setEnabled(false);
-        assertThat(decorator.isEnabled(), is(false));
-    }
-
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testTogglingEnabledFiresEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(!decorator.isEnabled());
-
-        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
-        verify(listener).actionPerformed(captor.capture());
-
-        ActionEvent event = captor.getValue();
-        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
-                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testSettingSameEnabledValueDoesNotFireEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(decorator.isEnabled());
-
-        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/ThermostatVmMainLabelDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.host.swing;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.Ref;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class ThermostatVmMainLabelDecoratorTest {
-
-    private static final String THERMOSTAT_MAIN_CLASS = "com.redhat.thermostat.main.Thermostat";
-    private static final String THERMOSTAT_COMMAND_CHANNEL_CLASS = "com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain";
-
-    private ThermostatVmMainLabelDecorator decorator;
-    private VmInfoDAO dao;
-    private VmRef vmRef;
-    private VmInfo info;
-
-    @Before
-    public void setUp() {
-        dao = mock(VmInfoDAO.class);
-        vmRef = mock(VmRef.class);        
-        info = mock(VmInfo.class);
-
-        when(dao.getVmInfo(vmRef)).thenReturn(info);
-    }
-    
-    /**
-     * Testing using a Thermostat vm. The getLabel method must return
-     * the shorter version of the vm's command.
-     */
-    @Test
-    public void getLabelTest1() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat service");
-        
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat service", result);
-    }
-
-    @Test
-    public void verifyLabelForIncompleteCommand() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat", result);
-    }
-
-
-    @Test
-    public void verifyLabelForCommandChannel() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_COMMAND_CHANNEL_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_COMMAND_CHANNEL_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain 127.0.0.1 1200");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat (command channel)", result);
-    }
-
-    @Test
-    public void verifyLabelForCliCommand() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat kill-vm --vmId foo");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat kill-vm", result);
-    }
-
-    @Test
-    public void verifyLabelForCliCommand2() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat agent -d http://127.0.0.1:8999/thermostat/storage");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat agent", result);
-    }
-
-    @Test
-    public void verifyLabelWhenGlobalOptionIsUsed() {
-        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
-        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat --print-osgi-info kill-vm");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("Thermostat kill-vm", result);
-    }
-
-    /**
-     * Testing using a non Thermostat vm. The getLabel method must return
-     * the vm's main class.
-     */
-    @Test
-    public void getLabelTest2() {
-        String JAR = "/opt/eclipse//plugin/org.eclipse.equinox.laucher.jar";
-        when(vmRef.getName()).thenReturn(JAR);
-        when(info.getMainClass()).thenReturn(JAR);
-        when(info.getJavaCommandLine()).thenReturn("-os linux");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("originalLabel", result);
-    }
-    
-    
-    /**
-     * Testing using a non VmRef object. The getLabel method must return
-     * the host's reference name.
-     */
-    @Test
-    public void getLabelTest3() {
-        Ref hostRef = mock(HostRef.class);
-        when(hostRef.getName()).thenReturn("localhost.localdomain");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("localhost.localdomain", hostRef);
-        assertEquals("localhost.localdomain", result);
-    }
-
-    @Test
-    public void verifySomeDirectoryIsNotDetectedAsThermostat() {
-        // Just because "thermostat" appears in the path doesn't make it thermostat
-        String JAR = "/home/thermostat/ant/ant.jar";
-        when(vmRef.getName()).thenReturn(JAR);
-        when(info.getMainClass()).thenReturn(JAR);
-        when(info.getJavaCommandLine()).thenReturn("-f bulid.xml");
-
-        decorator = new ThermostatVmMainLabelDecorator(dao);
-        String result = decorator.getLabel("originalLabel", vmRef);
-        assertEquals("originalLabel", result);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/DeadHostIconDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+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 org.junit.experimental.categories.Category;
+
+import com.redhat.thermostat.annotations.internal.CacioTest;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+@Category(CacioTest.class)
+public class DeadHostIconDecoratorTest {
+
+    private DeadHostIconDecorator decorator;
+
+    @Before
+    public void setUp() {
+        final int SOME_SIZE = 10;
+
+        UIDefaults uiDefaults = mock(UIDefaults.class);
+        when(uiDefaults.getIconDecorationSize()).thenReturn(SOME_SIZE);
+        when(uiDefaults.getReferenceFieldDefaultIconSize()).thenReturn(SOME_SIZE);
+
+        HostInfoDAO dao = mock(HostInfoDAO.class);
+
+        HostIconDecorator parent = HostIconDecorator.createInstance(uiDefaults);
+
+        decorator = DeadHostIconDecorator.createInstance(dao, uiDefaults, parent);
+    }
+
+    @Test
+    public void verifyGetIconWithNullProducesValidIcon() {
+        PlatformIcon icon = decorator.getIcon(null, mock(HostRef.class));
+        assertNotNull(icon);
+    }
+
+    @Test
+    public void verifyGetIconWithNotAHostRefProducesOriginalIcon() {
+        PlatformIcon icon = decorator.getIcon(null, mock(VmRef.class));
+        assertNull(icon);
+    }
+
+    @Test
+    public void verifyGetSelectedIconWithNullProducesValidIcon() {
+        PlatformIcon icon = decorator.getSelectedIcon(null, mock(HostRef.class));
+        assertNotNull(icon);
+    }
+
+    @Test
+    public void verifyGetSelectedIconWithNotAHostRefProducesOriginalIcon() {
+        PlatformIcon icon = decorator.getSelectedIcon(null, mock(VmRef.class));
+        assertNull(icon);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/HostIconDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+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 java.awt.Color;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.redhat.thermostat.annotations.internal.CacioTest;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.ui.PlatformIcon;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+
+@Category(CacioTest.class)
+public class HostIconDecoratorTest {
+
+    private HostIconDecorator decorator;
+
+    @Before
+    public void setUp() {
+        final int SOME_SIZE = 10;
+        final Color SOME_COLOR = Color.BLACK;
+        UIDefaults ui = mock(UIDefaults.class);
+        when(ui.getReferenceFieldDefaultIconSize()).thenReturn(SOME_SIZE);
+        when(ui.getReferenceFieldIconColor()).thenReturn(SOME_COLOR);
+
+        decorator = HostIconDecorator.createInstance(ui);
+    }
+
+    @Test
+    public void verifyGetIconProducesAnIconForHosts() {
+        HostRef hostRef = mock(HostRef.class);
+        PlatformIcon icon = decorator.getIcon(null, hostRef);
+        assertNotNull(icon);
+    }
+
+    @Test
+    public void testGetIconIgnoresVmRef() {
+        VmRef vmRef = mock(VmRef.class);
+        PlatformIcon icon = decorator.getIcon(null, vmRef);
+        assertNull(icon);
+    }
+
+    @Test
+    public void verifyGetSelectedIconProducesAnIconForHosts() {
+        HostRef hostRef = mock(HostRef.class);
+        PlatformIcon icon = decorator.getSelectedIcon(null, hostRef);
+        assertNotNull(icon);
+    }
+
+    @Test
+    public void testGetSelectedIconIgnoresVmRef() {
+        VmRef vmRef = mock(VmRef.class);
+        PlatformIcon icon = decorator.getSelectedIcon(null, vmRef);
+        assertNull(icon);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/HostNetworkInterfaceLabelDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class HostNetworkInterfaceLabelDecoratorTest {
+
+    private NetworkInterfaceInfoDAO dao;
+    private HostNetworkInterfaceLabelDecorator decorator;
+
+    @Before
+    public void setup() {
+        dao = mock(NetworkInterfaceInfoDAO.class);
+        decorator = new HostNetworkInterfaceLabelDecorator(dao);
+    }
+
+    @Test
+    public void testBasicWithNetworkInterfaces() {
+        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
+        String ip = "192.168.0.1";
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
+        assertEquals(ip, info.getInterfaceName());
+        info.setIp4Addr(ip);
+        networkList.add(info);
+        HostRef mockHostRef = mock(HostRef.class);
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
+        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
+        assertEquals("192.168.0.1", decoratedLabel);
+    }
+    
+    @Test
+    public void testBasicTwoIfaces() {
+        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
+        String ip = "192.168.0.1";
+        String ip2 = "10.0.0.1";
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
+        NetworkInterfaceInfo info2 = new NetworkInterfaceInfo("foo-agent", ip2);
+        assertEquals(ip2, info2.getInterfaceName());
+        assertEquals(ip, info.getInterfaceName());
+        info.setIp4Addr(ip);
+        info2.setIp4Addr(ip2);
+        networkList.add(info);
+        networkList.add(info2);
+        HostRef mockHostRef = mock(HostRef.class);
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
+        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
+        assertEquals("192.168.0.1; 10.0.0.1", decoratedLabel);
+    }
+    
+    @Test
+    public void testWithEmptyIp4AddrAndNoIPv6Addr() {
+        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
+        String ip = "192.168.0.1";
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo("foo-agent", ip);
+        assertEquals(ip, info.getInterfaceName());
+        info.setIp4Addr(""); // empty string
+        networkList.add(info);
+        HostRef mockHostRef = mock(HostRef.class);
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
+        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
+        assertEquals("", decoratedLabel);
+    }
+    
+    /**
+     * This should not throw IndexOutOfBoundsException
+     */
+    @Test
+    public void testWithNoNetworkInterfaces() {
+        List<NetworkInterfaceInfo> networkList = new ArrayList<>();
+        HostRef mockHostRef = mock(HostRef.class);
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkList);
+        String decoratedLabel = decorator.getLabel("", mockHostRef).trim();
+        assertEquals("", decoratedLabel);
+    }
+
+    @Test
+    public void verifyGetLabelCaches() {
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(isA(HostRef.class))).thenReturn(new ArrayList<NetworkInterfaceInfo>());
+        HostRef ref = mock(HostRef.class);
+
+        decorator.getLabel("", ref);
+        verify(dao).getNetworkInterfaces(ref);
+
+        decorator.getLabel("", ref);
+        verify(dao).getNetworkInterfaces(ref); // still only once -> cached after first call
+    }
+
+    @Test
+    public void verifyGetLabelAppends() {
+        decorator.setEnabled(true);
+        when(dao.getNetworkInterfaces(isA(HostRef.class))).thenReturn(new ArrayList<NetworkInterfaceInfo>());
+        HostRef ref = mock(HostRef.class);
+
+        String str = decorator.getLabel("Foo", ref).trim();
+        assertThat(str, containsString("Foo"));
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenDisabled() {
+        decorator.setEnabled(false);
+        decorator.getLabel("", mock(HostRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenWrongRefType() {
+        decorator.setEnabled(true);
+        decorator.getLabel("", mock(VmRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void testSetEnabled() {
+        decorator.setEnabled(true);
+        assertThat(decorator.isEnabled(), is(true));
+        decorator.setEnabled(false);
+        assertThat(decorator.isEnabled(), is(false));
+    }
+
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testTogglingEnabledFiresEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(!decorator.isEnabled());
+
+        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
+        verify(listener).actionPerformed(captor.capture());
+
+        ActionEvent event = captor.getValue();
+        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
+                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSettingSameEnabledValueDoesNotFireEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(decorator.isEnabled());
+
+        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/host/swing/ThermostatVmMainLabelDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.host.swing;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.Ref;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class ThermostatVmMainLabelDecoratorTest {
+
+    private static final String THERMOSTAT_MAIN_CLASS = "com.redhat.thermostat.main.Thermostat";
+    private static final String THERMOSTAT_COMMAND_CHANNEL_CLASS = "com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain";
+
+    private ThermostatVmMainLabelDecorator decorator;
+    private VmInfoDAO dao;
+    private VmRef vmRef;
+    private VmInfo info;
+
+    @Before
+    public void setUp() {
+        dao = mock(VmInfoDAO.class);
+        vmRef = mock(VmRef.class);        
+        info = mock(VmInfo.class);
+
+        when(dao.getVmInfo(vmRef)).thenReturn(info);
+    }
+    
+    /**
+     * Testing using a Thermostat vm. The getLabel method must return
+     * the shorter version of the vm's command.
+     */
+    @Test
+    public void getLabelTest1() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat service");
+        
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat service", result);
+    }
+
+    @Test
+    public void verifyLabelForIncompleteCommand() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat", result);
+    }
+
+
+    @Test
+    public void verifyLabelForCommandChannel() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_COMMAND_CHANNEL_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_COMMAND_CHANNEL_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.agent.command.server.internal.CommandChannelServerMain 127.0.0.1 1200");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat (command channel)", result);
+    }
+
+    @Test
+    public void verifyLabelForCliCommand() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat kill-vm --vmId foo");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat kill-vm", result);
+    }
+
+    @Test
+    public void verifyLabelForCliCommand2() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat agent -d http://127.0.0.1:8999/thermostat/storage");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat agent", result);
+    }
+
+    @Test
+    public void verifyLabelWhenGlobalOptionIsUsed() {
+        when(vmRef.getName()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getMainClass()).thenReturn(THERMOSTAT_MAIN_CLASS);
+        when(info.getJavaCommandLine()).thenReturn("com.redhat.thermostat.main.Thermostat --print-osgi-info kill-vm");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("Thermostat kill-vm", result);
+    }
+
+    /**
+     * Testing using a non Thermostat vm. The getLabel method must return
+     * the vm's main class.
+     */
+    @Test
+    public void getLabelTest2() {
+        String JAR = "/opt/eclipse//plugin/org.eclipse.equinox.laucher.jar";
+        when(vmRef.getName()).thenReturn(JAR);
+        when(info.getMainClass()).thenReturn(JAR);
+        when(info.getJavaCommandLine()).thenReturn("-os linux");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("originalLabel", result);
+    }
+    
+    
+    /**
+     * Testing using a non VmRef object. The getLabel method must return
+     * the host's reference name.
+     */
+    @Test
+    public void getLabelTest3() {
+        Ref hostRef = mock(HostRef.class);
+        when(hostRef.getName()).thenReturn("localhost.localdomain");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("localhost.localdomain", hostRef);
+        assertEquals("localhost.localdomain", result);
+    }
+
+    @Test
+    public void verifySomeDirectoryIsNotDetectedAsThermostat() {
+        // Just because "thermostat" appears in the path doesn't make it thermostat
+        String JAR = "/home/thermostat/ant/ant.jar";
+        when(vmRef.getName()).thenReturn(JAR);
+        when(info.getMainClass()).thenReturn(JAR);
+        when(info.getJavaCommandLine()).thenReturn("-f bulid.xml");
+
+        decorator = new ThermostatVmMainLabelDecorator(dao);
+        String result = decorator.getLabel("originalLabel", vmRef);
+        assertEquals("originalLabel", result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/AbstractToggleableMenuActionTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.matchers.GreaterOrEqual;
+import org.mockito.internal.matchers.LessOrEqual;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+public abstract class AbstractToggleableMenuActionTest<T extends MenuAction> {
+
+    protected ToggleableReferenceFieldLabelDecorator decorator;
+    protected T action;
+
+    @Before
+    public abstract void setup();
+
+    @Test
+    public void verifyExecuteTogglesDecorator() {
+        when(decorator.isEnabled()).thenReturn(false);
+        action.execute();
+        verify(decorator).setEnabled(true);
+        when(decorator.isEnabled()).thenReturn(true);
+        action.execute();
+        verify(decorator).setEnabled(false);
+    }
+
+    @Test
+    public void assertSortOrderWithinBounds() {
+        int sortOrder = action.sortOrder();
+        assertThat(sortOrder, is(new GreaterOrEqual<>(MenuAction.SORT_TOP)));
+        assertThat(sortOrder, is(new LessOrEqual<>(MenuAction.SORT_BOTTOM)));
+    }
+
+    @Test
+    public void assertPersistenceIdContainsMenuKey() {
+        assertThat(action.getPersistenceID(), containsString(MenuAction.MENU_KEY));
+    }
+
+    @Test
+    public void assertPathContainsName() {
+        assertThat(action.getPath(), containsLocalizedString(action.getName()));
+    }
+
+    private static Matcher<LocalizedString[]> containsLocalizedString(final LocalizedString ls) {
+        return new BaseMatcher<LocalizedString[]>() {
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof LocalizedString[])) {
+                    return false;
+                }
+                boolean contains = false;
+                for (LocalizedString str : ((LocalizedString[]) o)) {
+                    contains = contains || str.getContents().equals(ls.getContents());
+                }
+                return contains;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("LocalizedString[] containing element with contents ")
+                        .appendValue(ls.getContents());
+            }
+        };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/HostNetworkInterfaceLabelMenuActionTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.mockito.Mockito.mock;
+
+import com.redhat.thermostat.client.filter.internal.host.swing.HostNetworkInterfaceLabelDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostNetworkInterfaceLabelMenuAction;
+
+public class HostNetworkInterfaceLabelMenuActionTest extends AbstractToggleableMenuActionTest<HostNetworkInterfaceLabelMenuAction> {
+
+    @Override
+    public void setup() {
+        decorator = mock(HostNetworkInterfaceLabelDecorator.class);
+        action = new HostNetworkInterfaceLabelMenuAction((HostNetworkInterfaceLabelDecorator) decorator);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMFilterActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.redhat.thermostat.annotations.internal.CacioTest;
+import com.redhat.thermostat.client.filter.internal.host.swing.DeadHostIconDecorator;
+import com.redhat.thermostat.client.filter.internal.host.swing.HostNetworkInterfaceLabelDecorator;
+import com.redhat.thermostat.client.swing.UIDefaults;
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
+import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+@Category(CacioTest.class)
+public class VMFilterActivatorTest {
+    
+    @Test
+    public void testServicesRegistered() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        VMFilterActivator activator = new VMFilterActivator();
+        activator.start(ctx);
+        
+        VmInfoDAO vmDao = mock(VmInfoDAO.class);
+        HostInfoDAO hostDao = mock(HostInfoDAO.class);
+        NetworkInterfaceInfoDAO netDao = mock(NetworkInterfaceInfoDAO.class);
+        UIDefaults uiDefaults = mock(UIDefaults.class);
+
+        when(uiDefaults.getReferenceFieldDefaultIconSize()).thenReturn(1);
+        
+        ctx.registerService(VmInfoDAO.class, vmDao, null);
+        ctx.registerService(HostInfoDAO.class, hostDao, null);
+        ctx.registerService(NetworkInterfaceInfoDAO.class, netDao, null);
+        ctx.registerService(UIDefaults.class, uiDefaults, null);
+
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), VMPidLabelDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), VMStartTimeLabelDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), HostNetworkInterfaceLabelDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadHostIconDecorator.class));
+
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), VMIconDecorator.class));
+        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadVMIconDecorator.class));
+
+        assertTrue(ctx.isServiceRegistered(MenuAction.class.getName(), VMPidLabelMenuAction.class));
+        assertTrue(ctx.isServiceRegistered(MenuAction.class.getName(), VMStartTimeLabelMenuAction.class));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class VMPidLabelDecoratorTest {
+
+    private VmInfoDAO dao;
+    private VMPidLabelDecorator decorator;
+
+    @Before
+    public void setup() {
+        dao = mock(VmInfoDAO.class);
+        decorator = new VMPidLabelDecorator(dao);
+    }
+
+    @Test
+    public void testGetLabel() {
+        decorator.setEnabled(true);
+
+        VmInfo vmInfo = mock(VmInfo.class);
+        when(vmInfo.getVmPid()).thenReturn(100);
+        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(vmInfo);
+
+        VmRef ref = mock(VmRef.class);
+        String str = decorator.getLabel("Foo", ref);
+        assertThat(str, containsString("Foo"));
+        assertThat(str, containsString("PID"));
+        assertThat(str, containsString("100"));
+    }
+
+    @Test
+    public void verifyGetLabelCaches() {
+        decorator.setEnabled(true);
+        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(mock(VmInfo.class));
+        VmRef ref = mock(VmRef.class);
+
+        decorator.getLabel("", ref);
+        verify(dao).getVmInfo(ref);
+
+        decorator.getLabel("", ref);
+        verify(dao).getVmInfo(ref); // still only once -> cached after first call
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenDisabled() {
+        decorator.setEnabled(false);
+        decorator.getLabel("", mock(VmRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenWrongRefType() {
+        decorator.setEnabled(true);
+        decorator.getLabel("", mock(HostRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void testSetEnabled() {
+        decorator.setEnabled(true);
+        assertThat(decorator.isEnabled(), is(true));
+        decorator.setEnabled(false);
+        assertThat(decorator.isEnabled(), is(false));
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testTogglingEnabledFiresEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(!decorator.isEnabled());
+
+        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
+        verify(listener).actionPerformed(captor.capture());
+
+        ActionEvent event = captor.getValue();
+        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
+                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSettingSameEnabledValueDoesNotFireEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(decorator.isEnabled());
+
+        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMPidLabelMenuActionTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+
+public class VMPidLabelMenuActionTest extends AbstractToggleableMenuActionTest<VMPidLabelMenuAction> {
+
+    @Before
+    public void setup() {
+        decorator = mock(VMPidLabelDecorator.class);
+        action = new VMPidLabelMenuAction((VMPidLabelDecorator) decorator);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelDecoratorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+
+import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class VMStartTimeLabelDecoratorTest {
+
+    private VmInfoDAO dao;
+    private VMStartTimeLabelDecorator decorator;
+
+    @Before
+    public void setup() {
+        dao = mock(VmInfoDAO.class);
+        decorator = new VMStartTimeLabelDecorator(dao);
+    }
+
+    @Test
+    public void testGetLabel() {
+        decorator.setEnabled(true);
+
+        VmInfo vmInfo = mock(VmInfo.class);
+        when(vmInfo.getStartTimeStamp()).thenReturn(100L);
+        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(vmInfo);
+
+        VmRef ref = mock(VmRef.class);
+        String str = decorator.getLabel("Foo", ref);
+        assertThat(str, containsString("Foo"));
+        assertThat(str, containsString("Start time"));
+        // formatted date/time string is not checked for because this can change depending on locale of test runner, etc.,
+        // and is a UI detail anyway
+    }
+
+    @Test
+    public void verifyGetLabelCaches() {
+        decorator.setEnabled(true);
+        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(mock(VmInfo.class));
+        VmRef ref = mock(VmRef.class);
+
+        decorator.getLabel("", ref);
+        verify(dao).getVmInfo(ref);
+
+        decorator.getLabel("", ref);
+        verify(dao).getVmInfo(ref); // still only once -> cached after first call
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenDisabled() {
+        decorator.setEnabled(false);
+        decorator.getLabel("", mock(VmRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void verifyNoDaoAccessWhenWrongRefType() {
+        decorator.setEnabled(true);
+        decorator.getLabel("", mock(HostRef.class));
+        verifyZeroInteractions(dao);
+    }
+
+    @Test
+    public void testSetEnabled() {
+        decorator.setEnabled(true);
+        assertThat(decorator.isEnabled(), is(true));
+        decorator.setEnabled(false);
+        assertThat(decorator.isEnabled(), is(false));
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testTogglingEnabledFiresEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(!decorator.isEnabled());
+
+        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
+        verify(listener).actionPerformed(captor.capture());
+
+        ActionEvent event = captor.getValue();
+        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
+                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSettingSameEnabledValueDoesNotFireEvent() {
+        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
+                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
+
+        decorator.addStatusEventListener(listener);
+
+        decorator.setEnabled(decorator.isEnabled());
+
+        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/internal/vm/swing/VMStartTimeLabelMenuActionTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-2016 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.client.filter.internal.vm.swing;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.matchers.GreaterOrEqual;
+import org.mockito.internal.matchers.LessOrEqual;
+
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+public class VMStartTimeLabelMenuActionTest {
+
+    private VMStartTimeLabelDecorator decorator;
+    private VMStartTimeLabelMenuAction action;
+
+    @Before
+    public void setup() {
+        decorator = mock(VMStartTimeLabelDecorator.class);
+        action = new VMStartTimeLabelMenuAction(decorator);
+    }
+
+    @Test
+    public void verifyExecuteTogglesDecorator() {
+        when(decorator.isEnabled()).thenReturn(false);
+        action.execute();
+        verify(decorator).setEnabled(true);
+        when(decorator.isEnabled()).thenReturn(true);
+        action.execute();
+        verify(decorator).setEnabled(false);
+    }
+
+    @Test
+    public void assertSortOrderWithinBounds() {
+        int sortOrder = action.sortOrder();
+        assertThat(sortOrder, is(new GreaterOrEqual<>(MenuAction.SORT_TOP)));
+        assertThat(sortOrder, is(new LessOrEqual<>(MenuAction.SORT_BOTTOM)));
+    }
+
+    @Test
+    public void assertPersistenceIdContainsMenuKey() {
+        assertThat(action.getPersistenceID(), containsString(MenuAction.MENU_KEY));
+    }
+
+    @Test
+    public void assertPathContainsName() {
+        assertThat(action.getPath(), containsLocalizedString(action.getName()));
+    }
+
+    private static Matcher<LocalizedString[]> containsLocalizedString(final LocalizedString ls) {
+        return new BaseMatcher<LocalizedString[]>() {
+            @Override
+            public boolean matches(Object o) {
+                if (!(o instanceof LocalizedString[])) {
+                    return false;
+                }
+                boolean contains = false;
+                for (LocalizedString str : ((LocalizedString[]) o)) {
+                    contains = contains || str.getContents().equals(ls.getContents());
+                }
+                return contains;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("LocalizedString[] containing element with contents ")
+                        .appendValue(ls.getContents());
+            }
+        };
+    }
+
+}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/AbstractToggleableMenuActionTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.internal.matchers.GreaterOrEqual;
-import org.mockito.internal.matchers.LessOrEqual;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public abstract class AbstractToggleableMenuActionTest<T extends MenuAction> {
-
-    protected ToggleableReferenceFieldLabelDecorator decorator;
-    protected T action;
-
-    @Before
-    public abstract void setup();
-
-    @Test
-    public void verifyExecuteTogglesDecorator() {
-        when(decorator.isEnabled()).thenReturn(false);
-        action.execute();
-        verify(decorator).setEnabled(true);
-        when(decorator.isEnabled()).thenReturn(true);
-        action.execute();
-        verify(decorator).setEnabled(false);
-    }
-
-    @Test
-    public void assertSortOrderWithinBounds() {
-        int sortOrder = action.sortOrder();
-        assertThat(sortOrder, is(new GreaterOrEqual<>(MenuAction.SORT_TOP)));
-        assertThat(sortOrder, is(new LessOrEqual<>(MenuAction.SORT_BOTTOM)));
-    }
-
-    @Test
-    public void assertPersistenceIdContainsMenuKey() {
-        assertThat(action.getPersistenceID(), containsString(MenuAction.MENU_KEY));
-    }
-
-    @Test
-    public void assertPathContainsName() {
-        assertThat(action.getPath(), containsLocalizedString(action.getName()));
-    }
-
-    private static Matcher<LocalizedString[]> containsLocalizedString(final LocalizedString ls) {
-        return new BaseMatcher<LocalizedString[]>() {
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof LocalizedString[])) {
-                    return false;
-                }
-                boolean contains = false;
-                for (LocalizedString str : ((LocalizedString[]) o)) {
-                    contains = contains || str.getContents().equals(ls.getContents());
-                }
-                return contains;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("LocalizedString[] containing element with contents ")
-                        .appendValue(ls.getContents());
-            }
-        };
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/HostNetworkInterfaceLabelMenuActionTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.filter.host.swing.HostNetworkInterfaceLabelDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostNetworkInterfaceLabelMenuAction;
-
-import static org.mockito.Mockito.mock;
-
-public class HostNetworkInterfaceLabelMenuActionTest extends AbstractToggleableMenuActionTest<HostNetworkInterfaceLabelMenuAction> {
-
-    @Override
-    public void setup() {
-        decorator = mock(HostNetworkInterfaceLabelDecorator.class);
-        action = new HostNetworkInterfaceLabelMenuAction((HostNetworkInterfaceLabelDecorator) decorator);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.redhat.thermostat.annotations.internal.CacioTest;
-import com.redhat.thermostat.client.filter.host.swing.DeadHostIconDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostNetworkInterfaceLabelDecorator;
-import com.redhat.thermostat.client.swing.UIDefaults;
-import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
-import com.redhat.thermostat.client.ui.ReferenceFieldLabelDecorator;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.testutils.StubBundleContext;
-
-@Category(CacioTest.class)
-public class VMFilterActivatorTest {
-    
-    @Test
-    public void testServicesRegistered() throws Exception {
-        StubBundleContext ctx = new StubBundleContext();
-        VMFilterActivator activator = new VMFilterActivator();
-        activator.start(ctx);
-        
-        VmInfoDAO vmDao = mock(VmInfoDAO.class);
-        HostInfoDAO hostDao = mock(HostInfoDAO.class);
-        NetworkInterfaceInfoDAO netDao = mock(NetworkInterfaceInfoDAO.class);
-        UIDefaults uiDefaults = mock(UIDefaults.class);
-
-        when(uiDefaults.getReferenceFieldDefaultIconSize()).thenReturn(1);
-        
-        ctx.registerService(VmInfoDAO.class, vmDao, null);
-        ctx.registerService(HostInfoDAO.class, hostDao, null);
-        ctx.registerService(NetworkInterfaceInfoDAO.class, netDao, null);
-        ctx.registerService(UIDefaults.class, uiDefaults, null);
-
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), VMPidLabelDecorator.class));
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), VMStartTimeLabelDecorator.class));
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldLabelDecorator.class.getName(), HostNetworkInterfaceLabelDecorator.class));
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadHostIconDecorator.class));
-
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), VMIconDecorator.class));
-        assertTrue(ctx.isServiceRegistered(ReferenceFieldIconDecorator.class.getName(), DeadVMIconDecorator.class));
-
-        assertTrue(ctx.isServiceRegistered(MenuAction.class.getName(), VMPidLabelMenuAction.class));
-        assertTrue(ctx.isServiceRegistered(MenuAction.class.getName(), VMStartTimeLabelMenuAction.class));
-    }
-}
-
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class VMPidLabelDecoratorTest {
-
-    private VmInfoDAO dao;
-    private VMPidLabelDecorator decorator;
-
-    @Before
-    public void setup() {
-        dao = mock(VmInfoDAO.class);
-        decorator = new VMPidLabelDecorator(dao);
-    }
-
-    @Test
-    public void testGetLabel() {
-        decorator.setEnabled(true);
-
-        VmInfo vmInfo = mock(VmInfo.class);
-        when(vmInfo.getVmPid()).thenReturn(100);
-        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(vmInfo);
-
-        VmRef ref = mock(VmRef.class);
-        String str = decorator.getLabel("Foo", ref);
-        assertThat(str, containsString("Foo"));
-        assertThat(str, containsString("PID"));
-        assertThat(str, containsString("100"));
-    }
-
-    @Test
-    public void verifyGetLabelCaches() {
-        decorator.setEnabled(true);
-        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(mock(VmInfo.class));
-        VmRef ref = mock(VmRef.class);
-
-        decorator.getLabel("", ref);
-        verify(dao).getVmInfo(ref);
-
-        decorator.getLabel("", ref);
-        verify(dao).getVmInfo(ref); // still only once -> cached after first call
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenDisabled() {
-        decorator.setEnabled(false);
-        decorator.getLabel("", mock(VmRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenWrongRefType() {
-        decorator.setEnabled(true);
-        decorator.getLabel("", mock(HostRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void testSetEnabled() {
-        decorator.setEnabled(true);
-        assertThat(decorator.isEnabled(), is(true));
-        decorator.setEnabled(false);
-        assertThat(decorator.isEnabled(), is(false));
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testTogglingEnabledFiresEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(!decorator.isEnabled());
-
-        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
-        verify(listener).actionPerformed(captor.capture());
-
-        ActionEvent event = captor.getValue();
-        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
-                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testSettingSameEnabledValueDoesNotFireEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(decorator.isEnabled());
-
-        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMPidLabelMenuActionTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import org.junit.Before;
-
-import static org.mockito.Mockito.mock;
-
-public class VMPidLabelMenuActionTest extends AbstractToggleableMenuActionTest<VMPidLabelMenuAction> {
-
-    @Before
-    public void setup() {
-        decorator = mock(VMPidLabelDecorator.class);
-        action = new VMPidLabelMenuAction((VMPidLabelDecorator) decorator);
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelDecoratorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.ToggleableReferenceFieldLabelDecorator;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class VMStartTimeLabelDecoratorTest {
-
-    private VmInfoDAO dao;
-    private VMStartTimeLabelDecorator decorator;
-
-    @Before
-    public void setup() {
-        dao = mock(VmInfoDAO.class);
-        decorator = new VMStartTimeLabelDecorator(dao);
-    }
-
-    @Test
-    public void testGetLabel() {
-        decorator.setEnabled(true);
-
-        VmInfo vmInfo = mock(VmInfo.class);
-        when(vmInfo.getStartTimeStamp()).thenReturn(100L);
-        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(vmInfo);
-
-        VmRef ref = mock(VmRef.class);
-        String str = decorator.getLabel("Foo", ref);
-        assertThat(str, containsString("Foo"));
-        assertThat(str, containsString("Start time"));
-        // formatted date/time string is not checked for because this can change depending on locale of test runner, etc.,
-        // and is a UI detail anyway
-    }
-
-    @Test
-    public void verifyGetLabelCaches() {
-        decorator.setEnabled(true);
-        when(dao.getVmInfo(isA(VmRef.class))).thenReturn(mock(VmInfo.class));
-        VmRef ref = mock(VmRef.class);
-
-        decorator.getLabel("", ref);
-        verify(dao).getVmInfo(ref);
-
-        decorator.getLabel("", ref);
-        verify(dao).getVmInfo(ref); // still only once -> cached after first call
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenDisabled() {
-        decorator.setEnabled(false);
-        decorator.getLabel("", mock(VmRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void verifyNoDaoAccessWhenWrongRefType() {
-        decorator.setEnabled(true);
-        decorator.getLabel("", mock(HostRef.class));
-        verifyZeroInteractions(dao);
-    }
-
-    @Test
-    public void testSetEnabled() {
-        decorator.setEnabled(true);
-        assertThat(decorator.isEnabled(), is(true));
-        decorator.setEnabled(false);
-        assertThat(decorator.isEnabled(), is(false));
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testTogglingEnabledFiresEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(!decorator.isEnabled());
-
-        ArgumentCaptor<ActionEvent> captor = ArgumentCaptor.forClass(ActionEvent.class);
-        verify(listener).actionPerformed(captor.capture());
-
-        ActionEvent event = captor.getValue();
-        assertThat((ToggleableReferenceFieldLabelDecorator.StatusEvent) event.getActionId(),
-                is(ToggleableReferenceFieldLabelDecorator.StatusEvent.STATUS_CHANGED));
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testSettingSameEnabledValueDoesNotFireEvent() {
-        ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent> listener =
-                (ActionListener<ToggleableReferenceFieldLabelDecorator.StatusEvent>) mock(ActionListener.class);
-
-        decorator.addStatusEventListener(listener);
-
-        decorator.setEnabled(decorator.isEnabled());
-
-        verify(listener, never()).actionPerformed(Matchers.<ActionEvent<ToggleableReferenceFieldLabelDecorator.StatusEvent>>any());
-    }
-
-}
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMStartTimeLabelMenuActionTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright 2012-2016 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.client.filter.vm.swing;
-
-import com.redhat.thermostat.client.ui.MenuAction;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.internal.matchers.GreaterOrEqual;
-import org.mockito.internal.matchers.LessOrEqual;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class VMStartTimeLabelMenuActionTest {
-
-    private VMStartTimeLabelDecorator decorator;
-    private VMStartTimeLabelMenuAction action;
-
-    @Before
-    public void setup() {
-        decorator = mock(VMStartTimeLabelDecorator.class);
-        action = new VMStartTimeLabelMenuAction(decorator);
-    }
-
-    @Test
-    public void verifyExecuteTogglesDecorator() {
-        when(decorator.isEnabled()).thenReturn(false);
-        action.execute();
-        verify(decorator).setEnabled(true);
-        when(decorator.isEnabled()).thenReturn(true);
-        action.execute();
-        verify(decorator).setEnabled(false);
-    }
-
-    @Test
-    public void assertSortOrderWithinBounds() {
-        int sortOrder = action.sortOrder();
-        assertThat(sortOrder, is(new GreaterOrEqual<>(MenuAction.SORT_TOP)));
-        assertThat(sortOrder, is(new LessOrEqual<>(MenuAction.SORT_BOTTOM)));
-    }
-
-    @Test
-    public void assertPersistenceIdContainsMenuKey() {
-        assertThat(action.getPersistenceID(), containsString(MenuAction.MENU_KEY));
-    }
-
-    @Test
-    public void assertPathContainsName() {
-        assertThat(action.getPath(), containsLocalizedString(action.getName()));
-    }
-
-    private static Matcher<LocalizedString[]> containsLocalizedString(final LocalizedString ls) {
-        return new BaseMatcher<LocalizedString[]>() {
-            @Override
-            public boolean matches(Object o) {
-                if (!(o instanceof LocalizedString[])) {
-                    return false;
-                }
-                boolean contains = false;
-                for (LocalizedString str : ((LocalizedString[]) o)) {
-                    contains = contains || str.getContents().equals(ls.getContents());
-                }
-                return contains;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("LocalizedString[] containing element with contents ")
-                        .appendValue(ls.getContents());
-            }
-        };
-    }
-
-}
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/UIResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/UIResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -49,7 +49,7 @@
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.redhat.thermostat.test.Bug;
+import com.redhat.thermostat.common.internal.test.Bug;
 
 @Bug(id="976",
      summary="About dialog creashes with GTK look and feel",
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/ClientConfigurationSwingTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/ClientConfigurationSwingTest.java	Tue May 03 15:49:54 2016 +0200
@@ -66,7 +66,7 @@
 import com.redhat.thermostat.client.core.views.ClientConfigurationView;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.test.Bug;
+import com.redhat.thermostat.common.internal.test.Bug;
 
 @Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
--- a/common/core/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -89,8 +89,7 @@
               com.redhat.thermostat.common.model,
             </Export-Package>
             <Private-Package>
-              com.redhat.thermostat.test,
-              com.redhat.thermostat.common.locale,
+              com.redhat.thermostat.common.internal.test,
               com.redhat.thermostat.common.internal,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java	Tue May 03 15:49:54 2016 +0200
@@ -42,7 +42,7 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/common/core/src/main/java/com/redhat/thermostat/common/Size.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Size.java	Tue May 03 15:49:54 2016 +0200
@@ -38,7 +38,7 @@
 
 import java.util.Objects;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 /**
--- a/common/core/src/main/java/com/redhat/thermostat/common/Version.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Version.java	Tue May 03 15:49:54 2016 +0200
@@ -41,7 +41,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.FrameworkUtil;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012-2016 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.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    MISSING_INFO,
+
+    VALUE_AND_UNIT,
+
+    APPLICATION_INFO_LICENSE,
+    APPLICATION_INFO_DESCRIPTION,
+    APPLICATION_VERSION_INFO,
+
+    USERNAME_PROMPT,
+    PASSWORD_PROMPT,
+
+    INVALID_IPPORT,
+    ;
+
+    public static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.common.locale.strings";
+    
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/Bug.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+public @interface Bug {
+
+    String id();
+    String url();
+    String summary();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/ExceptionThrowingInputStream.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+class ExceptionThrowingInputStream extends PipedInputStream {
+
+    private IOException exception;
+
+    ExceptionThrowingInputStream(PipedOutputStream out) throws IOException {
+        super(out);
+    }
+
+    @Override
+    public int read() throws IOException {
+        throwExceptionIfNecessary();
+        return super.read();
+    }
+
+    private void throwExceptionIfNecessary() throws IOException {
+        if (exception != null) {
+            throw exception;
+        }
+    }
+
+    public void setException(IOException ex) {
+        exception = ex;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/FreePortFinder.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import java.net.BindException;
+
+public class FreePortFinder {
+
+
+    public static interface TryPort {
+        void tryPort(int port) throws Exception;
+    }
+
+    private static final int MIN_PORT = 49152;
+    private static final int MAX_PORT = 65535;
+
+    private static volatile int nextPort = MAX_PORT;
+
+    public static int findFreePort(TryPort tryPort) throws Exception {
+        int port;
+        while (true) {
+            try {
+                port = nextPort();
+                tryPort.tryPort(port);
+                break;
+            } catch (BindException ex) {
+                continue;
+            }
+        }
+        return port;
+    }
+
+    private static int nextPort() {
+        nextPort++;
+        if (nextPort > MAX_PORT) {
+            nextPort = MIN_PORT;
+        }
+        return nextPort;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestCommandContextFactory.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandContextFactory;
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.Console;
+
+public class TestCommandContextFactory extends CommandContextFactory {
+
+    private ByteArrayOutputStream out;
+    private ByteArrayOutputStream err;
+    private ExceptionThrowingInputStream in;
+
+    public TestCommandContextFactory() {
+        this(null);
+    }
+
+    public TestCommandContextFactory(BundleContext bCtx) {
+        super(bCtx);
+        reset();
+    }
+
+    private TestConsole console;
+    private PipedOutputStream inOut;
+
+    private class TestConsole implements Console {
+
+        @Override
+        public PrintStream getOutput() {
+            return new PrintStream(out);
+        }
+
+        @Override
+        public PrintStream getError() {
+            return new PrintStream(err);
+        }
+
+        @Override
+        public InputStream getInput() {
+            return in;
+        }
+        
+    }
+
+    @Override
+    public CommandContext createContext(final Arguments args) {
+        return new CommandContext() {
+
+            @Override
+            public Console getConsole() {
+                return new TestConsole();
+            }
+
+            @Override
+            public Arguments getArguments() {
+                return args;
+            }
+
+            @Override
+            public CommandRegistry getCommandRegistry() {
+                return TestCommandContextFactory.this.getCommandRegistry();
+            }
+
+            @Override
+            public CommandContextFactory getCommandContextFactory() {
+                return TestCommandContextFactory.this;
+            }
+            
+        };
+    }
+
+    public String getOutput() {
+        try {
+            out.flush();
+        } catch (IOException e) {
+            // ignore
+        }
+        return new String(out.toByteArray());
+    }
+
+    /**
+     * For simulating user input in tests that require user interaction.
+     * 
+     * @param input the user's input, including any CR characters
+     */
+    public void setInput(String input) {
+        try {
+            inOut.write(input.getBytes());
+            inOut.flush();
+        } catch (IOException e) {
+            RuntimeException ex = new RuntimeException(e);
+            throw ex;
+        }
+    }
+
+    public String getError() {
+        return new String(err.toByteArray());
+    }
+
+    public void reset() {
+        out = new ByteArrayOutputStream();
+        err = new ByteArrayOutputStream();
+        inOut = new PipedOutputStream();
+        try {
+            in = new ExceptionThrowingInputStream(inOut);
+        } catch (IOException e) {
+            RuntimeException ex = new RuntimeException(e);
+            throw ex;
+        }
+        console = new TestConsole();
+    }
+
+    public Console getConsole() {
+        return console;
+    }
+
+    public void setInputThrowsException(IOException ex) {
+        in.setException(ex);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestCommandRegistry.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.Command;
+
+class TestCommandRegistry implements CommandRegistry {
+
+    private Map<String, Command> commands = new HashMap<>();
+
+    public Command getCommand(String name) {
+        return commands.get(name);
+    }
+
+    public Collection<Command> getRegisteredCommands() {
+        return commands.values();
+    }
+
+    public void registerCommand(String name, Command cmd) {
+        commands.put(name, cmd);
+    }
+
+    @Override
+    public void unregisterCommands() {
+        commands.clear();
+    }
+
+    @Override
+    public void unregisterCommand(String name) {
+        commands.remove(name);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/internal/test/TestTimerFactory.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.TimerFactory;
+
+public class TestTimerFactory implements TimerFactory {
+
+    private class TestTimer implements Timer {
+
+        @Override
+        public void start() {
+            isActive = true;
+        }
+
+        @Override
+        public void stop() {
+            isActive = false;
+        }
+
+        @Override
+        public void setAction(Runnable action) {
+            TestTimerFactory.this.action = action;
+        }
+
+        @Override
+        public void setInitialDelay(long initialDelay) {
+            TestTimerFactory.this.initialDelay = initialDelay;
+        }
+
+        @Override
+        public void setDelay(long delay) {
+            TestTimerFactory.this.delay = delay;
+        }
+
+        @Override
+        public void setSchedulingType(SchedulingType schedulingType) {
+            TestTimerFactory.this.schedulingType = schedulingType;
+        }
+
+        @Override
+        public void setTimeUnit(TimeUnit timeUnit) {
+            TestTimerFactory.this.timeUnit = timeUnit;
+        }
+        
+    }
+
+    private Timer timer = new TestTimer();
+
+    private Runnable action;
+
+    private long initialDelay;
+
+    private long delay;
+
+    private Timer.SchedulingType schedulingType;
+
+    private TimeUnit timeUnit;
+
+    private boolean isActive;
+
+    private boolean shutdown;
+
+    public long getInitialDelay() {
+        return initialDelay;
+    }
+
+    public long getDelay() {
+        return delay;
+    }
+
+    public Timer.SchedulingType getSchedulingType() {
+        return schedulingType;
+    }
+
+    public TimeUnit getTimeUnit() {
+        return timeUnit;
+    }
+
+    public Runnable getAction() {
+        return action;
+    }
+
+    @Override
+    public Timer createTimer() {
+        return timer;
+    }
+
+    @Override
+    public void shutdown() {
+        shutdown = true;
+    }
+
+    public boolean isActive() {
+        return isActive;
+    }
+
+    public boolean isShutdown() {
+        return shutdown;
+    }
+
+}
+
--- a/common/core/src/main/java/com/redhat/thermostat/common/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright 2012-2016 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.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    MISSING_INFO,
-
-    VALUE_AND_UNIT,
-
-    APPLICATION_INFO_LICENSE,
-    APPLICATION_INFO_DESCRIPTION,
-    APPLICATION_VERSION_INFO,
-
-    USERNAME_PROMPT,
-    PASSWORD_PROMPT,
-
-    INVALID_IPPORT,
-    ;
-
-    public static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.common.locale.strings";
-    
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java	Tue May 03 15:49:54 2016 +0200
@@ -42,7 +42,7 @@
 import jline.console.ConsoleReader;
 
 import com.redhat.thermostat.common.cli.Console;
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/common/core/src/main/java/com/redhat/thermostat/common/utils/HostPortsParser.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/HostPortsParser.java	Tue May 03 15:49:54 2016 +0200
@@ -39,7 +39,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Tue May 03 15:49:54 2016 +0200
@@ -40,7 +40,7 @@
 import java.util.logging.LogManager;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.Translate;
--- a/common/core/src/main/java/com/redhat/thermostat/test/Bug.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-public @interface Bug {
-
-    String id();
-    String url();
-    String summary();
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import java.io.IOException;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-
-class ExceptionThrowingInputStream extends PipedInputStream {
-
-    private IOException exception;
-
-    ExceptionThrowingInputStream(PipedOutputStream out) throws IOException {
-        super(out);
-    }
-
-    @Override
-    public int read() throws IOException {
-        throwExceptionIfNecessary();
-        return super.read();
-    }
-
-    private void throwExceptionIfNecessary() throws IOException {
-        if (exception != null) {
-            throw exception;
-        }
-    }
-
-    public void setException(IOException ex) {
-        exception = ex;
-    }
-
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/test/FreePortFinder.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import java.net.BindException;
-
-public class FreePortFinder {
-
-
-    public static interface TryPort {
-        void tryPort(int port) throws Exception;
-    }
-
-    private static final int MIN_PORT = 49152;
-    private static final int MAX_PORT = 65535;
-
-    private static volatile int nextPort = MAX_PORT;
-
-    public static int findFreePort(TryPort tryPort) throws Exception {
-        int port;
-        while (true) {
-            try {
-                port = nextPort();
-                tryPort.tryPort(port);
-                break;
-            } catch (BindException ex) {
-                continue;
-            }
-        }
-        return port;
-    }
-
-    private static int nextPort() {
-        nextPort++;
-        if (nextPort > MAX_PORT) {
-            nextPort = MIN_PORT;
-        }
-        return nextPort;
-    }
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PipedOutputStream;
-import java.io.PrintStream;
-
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandContextFactory;
-import com.redhat.thermostat.common.cli.CommandRegistry;
-import com.redhat.thermostat.common.cli.Console;
-
-public class TestCommandContextFactory extends CommandContextFactory {
-
-    private ByteArrayOutputStream out;
-    private ByteArrayOutputStream err;
-    private ExceptionThrowingInputStream in;
-
-    public TestCommandContextFactory() {
-        this(null);
-    }
-
-    public TestCommandContextFactory(BundleContext bCtx) {
-        super(bCtx);
-        reset();
-    }
-
-    private TestConsole console;
-    private PipedOutputStream inOut;
-
-    private class TestConsole implements Console {
-
-        @Override
-        public PrintStream getOutput() {
-            return new PrintStream(out);
-        }
-
-        @Override
-        public PrintStream getError() {
-            return new PrintStream(err);
-        }
-
-        @Override
-        public InputStream getInput() {
-            return in;
-        }
-        
-    }
-
-    @Override
-    public CommandContext createContext(final Arguments args) {
-        return new CommandContext() {
-
-            @Override
-            public Console getConsole() {
-                return new TestConsole();
-            }
-
-            @Override
-            public Arguments getArguments() {
-                return args;
-            }
-
-            @Override
-            public CommandRegistry getCommandRegistry() {
-                return TestCommandContextFactory.this.getCommandRegistry();
-            }
-
-            @Override
-            public CommandContextFactory getCommandContextFactory() {
-                return TestCommandContextFactory.this;
-            }
-            
-        };
-    }
-
-    public String getOutput() {
-        try {
-            out.flush();
-        } catch (IOException e) {
-            // ignore
-        }
-        return new String(out.toByteArray());
-    }
-
-    /**
-     * For simulating user input in tests that require user interaction.
-     * 
-     * @param input the user's input, including any CR characters
-     */
-    public void setInput(String input) {
-        try {
-            inOut.write(input.getBytes());
-            inOut.flush();
-        } catch (IOException e) {
-            RuntimeException ex = new RuntimeException(e);
-            throw ex;
-        }
-    }
-
-    public String getError() {
-        return new String(err.toByteArray());
-    }
-
-    public void reset() {
-        out = new ByteArrayOutputStream();
-        err = new ByteArrayOutputStream();
-        inOut = new PipedOutputStream();
-        try {
-            in = new ExceptionThrowingInputStream(inOut);
-        } catch (IOException e) {
-            RuntimeException ex = new RuntimeException(e);
-            throw ex;
-        }
-        console = new TestConsole();
-    }
-
-    public Console getConsole() {
-        return console;
-    }
-
-    public void setInputThrowsException(IOException ex) {
-        in.setException(ex);
-    }
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/test/TestCommandRegistry.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.redhat.thermostat.common.cli.CommandRegistry;
-import com.redhat.thermostat.common.cli.Command;
-
-class TestCommandRegistry implements CommandRegistry {
-
-    private Map<String, Command> commands = new HashMap<>();
-
-    public Command getCommand(String name) {
-        return commands.get(name);
-    }
-
-    public Collection<Command> getRegisteredCommands() {
-        return commands.values();
-    }
-
-    public void registerCommand(String name, Command cmd) {
-        commands.put(name, cmd);
-    }
-
-    @Override
-    public void unregisterCommands() {
-        commands.clear();
-    }
-
-    @Override
-    public void unregisterCommand(String name) {
-        commands.remove(name);
-    }
-
-}
-
--- a/common/core/src/main/java/com/redhat/thermostat/test/TestTimerFactory.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.TimerFactory;
-
-public class TestTimerFactory implements TimerFactory {
-
-    private class TestTimer implements Timer {
-
-        @Override
-        public void start() {
-            isActive = true;
-        }
-
-        @Override
-        public void stop() {
-            isActive = false;
-        }
-
-        @Override
-        public void setAction(Runnable action) {
-            TestTimerFactory.this.action = action;
-        }
-
-        @Override
-        public void setInitialDelay(long initialDelay) {
-            TestTimerFactory.this.initialDelay = initialDelay;
-        }
-
-        @Override
-        public void setDelay(long delay) {
-            TestTimerFactory.this.delay = delay;
-        }
-
-        @Override
-        public void setSchedulingType(SchedulingType schedulingType) {
-            TestTimerFactory.this.schedulingType = schedulingType;
-        }
-
-        @Override
-        public void setTimeUnit(TimeUnit timeUnit) {
-            TestTimerFactory.this.timeUnit = timeUnit;
-        }
-        
-    }
-
-    private Timer timer = new TestTimer();
-
-    private Runnable action;
-
-    private long initialDelay;
-
-    private long delay;
-
-    private Timer.SchedulingType schedulingType;
-
-    private TimeUnit timeUnit;
-
-    private boolean isActive;
-
-    private boolean shutdown;
-
-    public long getInitialDelay() {
-        return initialDelay;
-    }
-
-    public long getDelay() {
-        return delay;
-    }
-
-    public Timer.SchedulingType getSchedulingType() {
-        return schedulingType;
-    }
-
-    public TimeUnit getTimeUnit() {
-        return timeUnit;
-    }
-
-    public Runnable getAction() {
-        return action;
-    }
-
-    @Override
-    public Timer createTimer() {
-        return timer;
-    }
-
-    @Override
-    public void shutdown() {
-        shutdown = true;
-    }
-
-    public boolean isActive() {
-        return isActive;
-    }
-
-    public boolean isShutdown() {
-        return shutdown;
-    }
-
-}
-
--- a/common/core/src/test/java/com/redhat/thermostat/common/ApplicationInfoTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ApplicationInfoTest.java	Tue May 03 15:49:54 2016 +0200
@@ -46,7 +46,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 
 public class ApplicationInfoTest {
 
--- a/common/core/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,7 +53,7 @@
 import org.mockito.stubbing.Answer;
 
 import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.test.Bug;
+import com.redhat.thermostat.common.internal.test.Bug;
 
 public class ThreadPoolTimerFactoryTest {
 
--- a/common/core/src/test/java/com/redhat/thermostat/common/VersionTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/common/core/src/test/java/com/redhat/thermostat/common/VersionTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,7 +53,7 @@
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
-import com.redhat.thermostat.common.locale.LocaleResources;
+import com.redhat.thermostat.common.internal.LocaleResources;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest(FrameworkUtil.class)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-2016 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.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.internal.LocaleResources;
+
+public class LocaleResourcesTest {
+    @Test
+    public void testLocalizedStringsArePresent() throws IOException {
+        
+        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
+        
+        Properties props = new Properties();
+        try (InputStream in = getClass().getResourceAsStream(stringsResource)) {
+            assertNotNull(in);
+            props.load(in);
+
+            assertEquals(LocaleResources.values().length, props.values().size());
+            for (LocaleResources resource : LocaleResources.values()) {
+                assertTrue("missing property from resource bound file: " + resource,
+                                  props.containsKey(resource.name()));
+            }
+            
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/internal/test/ExceptionThrowingInputStreamTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.PipedOutputStream;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ExceptionThrowingInputStreamTest {
+
+    private ExceptionThrowingInputStream in;
+    
+    private PipedOutputStream out;
+
+    @Before
+    public void setUp() throws IOException {
+        out = new PipedOutputStream();
+        in = new ExceptionThrowingInputStream(out);
+    }
+
+    @After
+    public void tearDown() {
+        in = null;
+        out = null;
+    }
+
+    @Test
+    public void testRead() throws IOException {
+        out.write(2);
+        out.flush();
+
+        int read = in.read();
+
+        assertEquals(2, read);
+    }
+
+    @Test
+    public void testReadException() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.read();
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testReadBytes() throws IOException {
+        
+        String test = "test";
+        out.write(test.getBytes());
+        out.flush();
+
+        byte[] read = new byte[4];
+        int numRead = in.read(read);
+
+        assertEquals(4, numRead);
+        assertEquals("test", new String(read));
+    }
+
+    @Test
+    public void testReadBytesException() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.read(new byte[4]);
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testReadBytes2() throws IOException {
+        
+        String test = "test";
+        out.write(test.getBytes());
+        out.flush();
+
+        byte[] read = new byte[10];
+        int numRead = in.read(read, 3, 4);
+
+        assertEquals(4, numRead);
+        assertEquals("test", new String(read, 3, 4));
+    }
+
+    @Test
+    public void testReadBytesException2() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.read(new byte[10], 3, 4);
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testSkip() throws IOException {
+        
+        String test = "test";
+        out.write(test.getBytes());
+        out.flush();
+
+        byte[] read = new byte[4];
+        in.skip(1);
+        int numRead = in.read(read);
+
+        assertEquals(3, numRead);
+        assertEquals("est", new String(read, 0, 3));
+    }
+
+    @Test
+    public void testSkipException() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.skip(1);
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testAvailable() throws IOException {
+        
+        String test = "test";
+        out.write(test.getBytes());
+        out.flush();
+
+        int available = in.available();
+
+        assertEquals(4, available);
+    }
+
+    @Test
+    public void testAvailableException() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.available();
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testClose() throws IOException {
+        
+        String test = "test";
+        out.write(test.getBytes());
+        out.flush();
+
+        in.close();
+
+        try {
+            in.read();
+        } catch (IOException ex) {
+            assertTrue(true);
+        }
+    }
+
+    @Test
+    public void testCloseException() throws IOException {
+        IOException ex = new IOException();
+        in.setException(ex);
+        try {
+            in.close();
+        } catch (IOException io) {
+            assertSame(ex, io);
+        }
+    }
+
+    @Test
+    public void testMarkSupported() {
+        assertFalse(in.markSupported());
+    }
+
+    @Test(expected=IOException.class)
+    public void testReset() throws IOException {
+        in.reset();
+    }
+
+    @Test
+    public void testMark() throws IOException {
+        // This method should do nothing. We simply check that no exception is thrown,
+        // and otherwise the stream works as normal.
+        in.mark(1);
+
+        out.write(2);
+        out.flush();
+
+        int read = in.read();
+
+        assertEquals(2, read);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/internal/test/TestCommandContextFactoryTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+
+public class TestCommandContextFactoryTest {
+
+    private TestCommandContextFactory cmdCtxFactory;
+    private CommandContext ctx;
+
+    @Before
+    public void setUp() {
+        cmdCtxFactory = new TestCommandContextFactory();
+        ctx = cmdCtxFactory.createContext(new SimpleArguments());
+    }
+
+    @After
+    public void tearDown() {
+        ctx = null;
+        cmdCtxFactory = null;
+    }
+
+    @Test
+    public void testInput() throws IOException {
+        cmdCtxFactory.setInput("test");
+        byte[] readBytes = new byte[5];
+        int numRead = ctx.getConsole().getInput().read(readBytes);
+        assertEquals(4, numRead);
+        assertEquals("test", new String(readBytes, 0, numRead));
+    }
+
+    @Test
+    public void testReset() throws IOException {
+        cmdCtxFactory.setInput("test");
+        cmdCtxFactory.reset();
+        cmdCtxFactory.setInput("foo");
+        byte[] readBytes = new byte[5];
+        int numRead = ctx.getConsole().getInput().read(readBytes);
+        assertEquals(3, numRead);
+        assertEquals("foo", new String(readBytes, 0, numRead));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/internal/test/TestTimerFactoryTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012-2016 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.internal.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Timer;
+
+public class TestTimerFactoryTest {
+
+    private TestTimerFactory timerFactory;
+    private Timer timer;
+
+    @Before
+    public void setUp() {
+        timerFactory = new TestTimerFactory();
+        timer = timerFactory.createTimer();
+    }
+
+    @After
+    public void tearDown() {
+        timer = null;
+        timerFactory = null;
+    }
+
+    @Test
+    public void testStart() {
+        assertFalse(timerFactory.isActive());
+        timer.start();
+        assertTrue(timerFactory.isActive());
+    }
+
+    @Test
+    public void testStop() {
+        assertFalse(timerFactory.isActive());
+        timer.start();
+        assertTrue(timerFactory.isActive());
+        timer.stop();
+        assertFalse(timerFactory.isActive());
+    }
+
+    @Test
+    public void testSetAction() {
+        final boolean[] run = new boolean[1];
+        Runnable action = new Runnable() {
+            @Override
+            public void run() {
+                run[0] = true;
+            }
+        };
+        timer.setAction(action);
+        assertSame(action, timerFactory.getAction());
+        timerFactory.getAction().run();
+        assertTrue(run[0]);
+    }
+
+    @Test
+    public void testSetInitialDelay() {
+        timer.setInitialDelay(123);
+        assertEquals(123l, timerFactory.getInitialDelay());
+    }
+
+    @Test
+    public void testSetDelay() {
+        timer.setDelay(123);
+        assertEquals(123l, timerFactory.getDelay());
+    }
+
+    @Test
+    public void testSetSchedulingType() {
+        timer.setSchedulingType(Timer.SchedulingType.FIXED_RATE);
+        assertEquals(Timer.SchedulingType.FIXED_RATE, timerFactory.getSchedulingType());
+    }
+
+    @Test
+    public void testSetTimeUnit() {
+        timer.setTimeUnit(TimeUnit.HOURS);
+        assertEquals(TimeUnit.HOURS, timerFactory.getTimeUnit());
+    }
+
+    @Test
+    public void testShutdown() {
+        assertFalse(timerFactory.isShutdown());
+        timerFactory.shutdown();
+        assertTrue(timerFactory.isShutdown());
+    }
+}
+
--- a/common/core/src/test/java/com/redhat/thermostat/common/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2012-2016 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.locale;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-import org.junit.Test;
-
-public class LocaleResourcesTest {
-    @Test
-    public void testLocalizedStringsArePresent() throws IOException {
-        
-        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
-        
-        Properties props = new Properties();
-        try (InputStream in = getClass().getResourceAsStream(stringsResource)) {
-            assertNotNull(in);
-            props.load(in);
-
-            assertEquals(LocaleResources.values().length, props.values().size());
-            for (LocaleResources resource : LocaleResources.values()) {
-                assertTrue("missing property from resource bound file: " + resource,
-                                  props.containsKey(resource.name()));
-            }
-            
-        }
-    }
-}
-
--- a/common/core/src/test/java/com/redhat/thermostat/test/ExceptionThrowingInputStreamTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.PipedOutputStream;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ExceptionThrowingInputStreamTest {
-
-    private ExceptionThrowingInputStream in;
-    
-    private PipedOutputStream out;
-
-    @Before
-    public void setUp() throws IOException {
-        out = new PipedOutputStream();
-        in = new ExceptionThrowingInputStream(out);
-    }
-
-    @After
-    public void tearDown() {
-        in = null;
-        out = null;
-    }
-
-    @Test
-    public void testRead() throws IOException {
-        out.write(2);
-        out.flush();
-
-        int read = in.read();
-
-        assertEquals(2, read);
-    }
-
-    @Test
-    public void testReadException() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.read();
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testReadBytes() throws IOException {
-        
-        String test = "test";
-        out.write(test.getBytes());
-        out.flush();
-
-        byte[] read = new byte[4];
-        int numRead = in.read(read);
-
-        assertEquals(4, numRead);
-        assertEquals("test", new String(read));
-    }
-
-    @Test
-    public void testReadBytesException() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.read(new byte[4]);
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testReadBytes2() throws IOException {
-        
-        String test = "test";
-        out.write(test.getBytes());
-        out.flush();
-
-        byte[] read = new byte[10];
-        int numRead = in.read(read, 3, 4);
-
-        assertEquals(4, numRead);
-        assertEquals("test", new String(read, 3, 4));
-    }
-
-    @Test
-    public void testReadBytesException2() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.read(new byte[10], 3, 4);
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testSkip() throws IOException {
-        
-        String test = "test";
-        out.write(test.getBytes());
-        out.flush();
-
-        byte[] read = new byte[4];
-        in.skip(1);
-        int numRead = in.read(read);
-
-        assertEquals(3, numRead);
-        assertEquals("est", new String(read, 0, 3));
-    }
-
-    @Test
-    public void testSkipException() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.skip(1);
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testAvailable() throws IOException {
-        
-        String test = "test";
-        out.write(test.getBytes());
-        out.flush();
-
-        int available = in.available();
-
-        assertEquals(4, available);
-    }
-
-    @Test
-    public void testAvailableException() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.available();
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testClose() throws IOException {
-        
-        String test = "test";
-        out.write(test.getBytes());
-        out.flush();
-
-        in.close();
-
-        try {
-            in.read();
-        } catch (IOException ex) {
-            assertTrue(true);
-        }
-    }
-
-    @Test
-    public void testCloseException() throws IOException {
-        IOException ex = new IOException();
-        in.setException(ex);
-        try {
-            in.close();
-        } catch (IOException io) {
-            assertSame(ex, io);
-        }
-    }
-
-    @Test
-    public void testMarkSupported() {
-        assertFalse(in.markSupported());
-    }
-
-    @Test(expected=IOException.class)
-    public void testReset() throws IOException {
-        in.reset();
-    }
-
-    @Test
-    public void testMark() throws IOException {
-        // This method should do nothing. We simply check that no exception is thrown,
-        // and otherwise the stream works as normal.
-        in.mark(1);
-
-        out.write(2);
-        out.flush();
-
-        int read = in.read();
-
-        assertEquals(2, read);
-    }
-}
-
--- a/common/core/src/test/java/com/redhat/thermostat/test/TestCommandContextFactoryTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-
-public class TestCommandContextFactoryTest {
-
-    private TestCommandContextFactory cmdCtxFactory;
-    private CommandContext ctx;
-
-    @Before
-    public void setUp() {
-        cmdCtxFactory = new TestCommandContextFactory();
-        ctx = cmdCtxFactory.createContext(new SimpleArguments());
-    }
-
-    @After
-    public void tearDown() {
-        ctx = null;
-        cmdCtxFactory = null;
-    }
-
-    @Test
-    public void testInput() throws IOException {
-        cmdCtxFactory.setInput("test");
-        byte[] readBytes = new byte[5];
-        int numRead = ctx.getConsole().getInput().read(readBytes);
-        assertEquals(4, numRead);
-        assertEquals("test", new String(readBytes, 0, numRead));
-    }
-
-    @Test
-    public void testReset() throws IOException {
-        cmdCtxFactory.setInput("test");
-        cmdCtxFactory.reset();
-        cmdCtxFactory.setInput("foo");
-        byte[] readBytes = new byte[5];
-        int numRead = ctx.getConsole().getInput().read(readBytes);
-        assertEquals(3, numRead);
-        assertEquals("foo", new String(readBytes, 0, numRead));
-    }
-}
-
--- a/common/core/src/test/java/com/redhat/thermostat/test/TestTimerFactoryTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright 2012-2016 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.test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.TimeUnit;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.Timer;
-
-public class TestTimerFactoryTest {
-
-    private TestTimerFactory timerFactory;
-    private Timer timer;
-
-    @Before
-    public void setUp() {
-        timerFactory = new TestTimerFactory();
-        timer = timerFactory.createTimer();
-    }
-
-    @After
-    public void tearDown() {
-        timer = null;
-        timerFactory = null;
-    }
-
-    @Test
-    public void testStart() {
-        assertFalse(timerFactory.isActive());
-        timer.start();
-        assertTrue(timerFactory.isActive());
-    }
-
-    @Test
-    public void testStop() {
-        assertFalse(timerFactory.isActive());
-        timer.start();
-        assertTrue(timerFactory.isActive());
-        timer.stop();
-        assertFalse(timerFactory.isActive());
-    }
-
-    @Test
-    public void testSetAction() {
-        final boolean[] run = new boolean[1];
-        Runnable action = new Runnable() {
-            @Override
-            public void run() {
-                run[0] = true;
-            }
-        };
-        timer.setAction(action);
-        assertSame(action, timerFactory.getAction());
-        timerFactory.getAction().run();
-        assertTrue(run[0]);
-    }
-
-    @Test
-    public void testSetInitialDelay() {
-        timer.setInitialDelay(123);
-        assertEquals(123l, timerFactory.getInitialDelay());
-    }
-
-    @Test
-    public void testSetDelay() {
-        timer.setDelay(123);
-        assertEquals(123l, timerFactory.getDelay());
-    }
-
-    @Test
-    public void testSetSchedulingType() {
-        timer.setSchedulingType(Timer.SchedulingType.FIXED_RATE);
-        assertEquals(Timer.SchedulingType.FIXED_RATE, timerFactory.getSchedulingType());
-    }
-
-    @Test
-    public void testSetTimeUnit() {
-        timer.setTimeUnit(TimeUnit.HOURS);
-        assertEquals(TimeUnit.HOURS, timerFactory.getTimeUnit());
-    }
-
-    @Test
-    public void testShutdown() {
-        assertFalse(timerFactory.isShutdown());
-        timerFactory.shutdown();
-        assertTrue(timerFactory.isShutdown());
-    }
-}
-
--- a/dev/archetype-ext/src/main/resources/archetype-resources/src/test/java/ExampleCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/dev/archetype-ext/src/main/resources/archetype-resources/src/test/java/ExampleCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -17,7 +17,7 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.Console;
-import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 
 public class ExampleCommandTest {
 
--- a/dev/schema-info-command/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/dev/schema-info-command/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -61,7 +61,6 @@
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Private-Package>
               com.redhat.thermostat.schemainfo.command.internal,
-              com.redhat.thermostat.schemainfo.command.locale,
             </Private-Package>
             <Bundle-Activator>com.redhat.thermostat.schemainfo.command.internal.Activator</Bundle-Activator>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 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.schemainfo.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+    
+    SCHEMAINFO_SERVICE_UNAVAILABLE,
+    NO_CATEGORIES,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.schemainfo.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- a/dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/internal/SchemaInfoCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/internal/SchemaInfoCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -44,7 +44,6 @@
 import com.redhat.thermostat.common.cli.AbstractCommand;
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.schemainfo.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.dao.SchemaInfoDAO;
 import com.redhat.thermostat.storage.model.SchemaInformation;
--- a/dev/schema-info-command/command/src/main/java/com/redhat/thermostat/schemainfo/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012-2016 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.schemainfo.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-    
-    SCHEMAINFO_SERVICE_UNAVAILABLE,
-    NO_CATEGORIES,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.schemainfo.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- a/dev/schema-info-command/command/src/test/java/com/redhat/thermostat/schemainfo/command/SchemaInfoCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * Copyright 2012-2016 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.schemainfo.command;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.Console;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.dao.SchemaInfoDAO;
-import com.redhat.thermostat.storage.model.SchemaInformation;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.schemainfo.command.internal.SchemaInfoCommand;
-import com.redhat.thermostat.schemainfo.command.locale.LocaleResources;
-
-public class SchemaInfoCommandTest {
-    
-    private static Translate<LocaleResources> translator;
-    private SchemaInfoCommand cmd;
-    private CommandContext ctxt;
-    private Console console;
-    private List<SchemaInformation> list;
-    private PrintStream output;
-    private PrintStream error;
-    private SchemaInfoDAO dao;
-    private SchemaInformation categoryTest1;
-    private SchemaInformation categoryTest2;
-    private StubBundleContext context;
-        
-    @Before
-    public void setUp() {
-        translator = LocaleResources.createLocalizer();
-        categoryTest1 = new SchemaInformation();
-        categoryTest2 = new SchemaInformation();
-        ctxt = mock(CommandContext.class);
-        console = mock(Console.class);
-        list = new ArrayList<>();
-        
-        categoryTest1.setCategoryName("category Test 1");
-        categoryTest1.setTimeStamp(System.currentTimeMillis());
-        categoryTest2.setCategoryName("category Test 2");
-        categoryTest2.setTimeStamp(System.currentTimeMillis());
-        list.add(categoryTest1);
-        list.add(categoryTest2);
-        
-        dao = mock(SchemaInfoDAO.class);
-        context = new StubBundleContext();
-        context.registerService(SchemaInfoDAO.class, dao, null);
-        cmd = new SchemaInfoCommand(context);
-        
-        when(ctxt.getConsole()).thenReturn(console);
-        when(console.getError()).thenReturn(error);
-        when(console.getOutput()).thenReturn(output);
-        
-    }
-    
-    @Test
-    public void testStorageRequired() {
-        assertTrue(cmd.isStorageRequired());
-    }
-    
-    @Test
-    public void verifyGetCategories() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        when(dao.getSchemaInfos()).thenReturn(list);
-        
-        cmd.run(factory.createContext(args));
-        
-        String expected = categoryTest1.getCategoryName() + "\n" +
-                         categoryTest2.getCategoryName() + "\n";
-
-        assertEquals(expected, factory.getOutput());
-    }
-    
-    @Test
-    public void verifyGetNoCategories() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        List<SchemaInformation> emptylist = Collections.emptyList();
-        
-        when(dao.getSchemaInfos()).thenReturn(emptylist);
-        cmd.run(factory.createContext(args));
-        
-        String expected = translator.localize(LocaleResources.NO_CATEGORIES).getContents() + "\n";
-        assertEquals(expected, factory.getOutput());
-    }
-    
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/schema-info-command/command/src/test/java/com/redhat/thermostat/schemainfo/command/internal/SchemaInfoCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012-2016 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.schemainfo.command.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.Console;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.dao.SchemaInfoDAO;
+import com.redhat.thermostat.storage.model.SchemaInformation;
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+public class SchemaInfoCommandTest {
+    
+    private static Translate<LocaleResources> translator;
+    private SchemaInfoCommand cmd;
+    private CommandContext ctxt;
+    private Console console;
+    private List<SchemaInformation> list;
+    private PrintStream output;
+    private PrintStream error;
+    private SchemaInfoDAO dao;
+    private SchemaInformation categoryTest1;
+    private SchemaInformation categoryTest2;
+    private StubBundleContext context;
+        
+    @Before
+    public void setUp() {
+        translator = LocaleResources.createLocalizer();
+        categoryTest1 = new SchemaInformation();
+        categoryTest2 = new SchemaInformation();
+        ctxt = mock(CommandContext.class);
+        console = mock(Console.class);
+        list = new ArrayList<>();
+        
+        categoryTest1.setCategoryName("category Test 1");
+        categoryTest1.setTimeStamp(System.currentTimeMillis());
+        categoryTest2.setCategoryName("category Test 2");
+        categoryTest2.setTimeStamp(System.currentTimeMillis());
+        list.add(categoryTest1);
+        list.add(categoryTest2);
+        
+        dao = mock(SchemaInfoDAO.class);
+        context = new StubBundleContext();
+        context.registerService(SchemaInfoDAO.class, dao, null);
+        cmd = new SchemaInfoCommand(context);
+        
+        when(ctxt.getConsole()).thenReturn(console);
+        when(console.getError()).thenReturn(error);
+        when(console.getOutput()).thenReturn(output);
+        
+    }
+    
+    @Test
+    public void testStorageRequired() {
+        assertTrue(cmd.isStorageRequired());
+    }
+    
+    @Test
+    public void verifyGetCategories() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        when(dao.getSchemaInfos()).thenReturn(list);
+        
+        cmd.run(factory.createContext(args));
+        
+        String expected = categoryTest1.getCategoryName() + "\n" +
+                         categoryTest2.getCategoryName() + "\n";
+
+        assertEquals(expected, factory.getOutput());
+    }
+    
+    @Test
+    public void verifyGetNoCategories() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        List<SchemaInformation> emptylist = Collections.emptyList();
+        
+        when(dao.getSchemaInfos()).thenReturn(emptylist);
+        cmd.run(factory.createContext(args));
+        
+        String expected = translator.localize(LocaleResources.NO_CATEGORIES).getContents() + "\n";
+        assertEquals(expected, factory.getOutput());
+    }
+    
+}
+
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Tue May 03 15:49:54 2016 +0200
@@ -75,6 +75,8 @@
 import org.junit.Test;
 
 import com.redhat.thermostat.common.ApplicationInfo;
+import com.redhat.thermostat.common.internal.test.FreePortFinder;
+import com.redhat.thermostat.common.internal.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.host.cpu.common.CpuStatDAO;
 import com.redhat.thermostat.host.cpu.common.model.CpuStat;
 import com.redhat.thermostat.shared.config.CommonPaths;
@@ -105,8 +107,6 @@
 import com.redhat.thermostat.storage.mongodb.internal.MongoStorage;
 import com.redhat.thermostat.storage.query.Expression;
 import com.redhat.thermostat.storage.query.ExpressionFactory;
-import com.redhat.thermostat.test.FreePortFinder;
-import com.redhat.thermostat.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.vm.classstat.common.VmClassStatDAO;
 import com.redhat.thermostat.vm.classstat.common.model.VmClassStat;
 import com.redhat.thermostat.vm.cpu.common.VmCpuStatDAO;
--- a/killvm/client-swing/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/client-swing/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -59,7 +59,6 @@
             <Bundle-SymbolicName>com.redhat.thermostat.killvm.client</Bundle-SymbolicName>
             <Private-Package>
               com.redhat.thermostat.killvm.client.internal,
-              com.redhat.thermostat.killvm.client.locale,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/KillVMAction.java	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/KillVMAction.java	Tue May 03 15:49:54 2016 +0200
@@ -45,7 +45,6 @@
 import com.redhat.thermostat.common.command.Request;
 import com.redhat.thermostat.common.command.Request.RequestType;
 import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.killvm.client.locale.LocaleResources;
 import com.redhat.thermostat.killvm.common.KillVMRequest;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 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.killvm.client.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    ACTION_NAME,
+    ACTION_DESCRIPTION,
+    KILL_ACTION_ERROR_RESPONSE_MSG,
+    MISSING_INFO;
+
+    public static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.killvm.client.locale.strings";
+    
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
+
--- a/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/SwingVMKilledListener.java	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/internal/SwingVMKilledListener.java	Tue May 03 15:49:54 2016 +0200
@@ -46,7 +46,6 @@
 import com.redhat.thermostat.common.command.RequestResponseListener;
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.killvm.client.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 public class SwingVMKilledListener implements RequestResponseListener {
--- a/killvm/client-swing/src/main/java/com/redhat/thermostat/killvm/client/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.client.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    ACTION_NAME,
-    ACTION_DESCRIPTION,
-    KILL_ACTION_ERROR_RESPONSE_MSG,
-    MISSING_INFO;
-
-    public static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.killvm.client.locale.strings";
-    
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/client-swing/src/test/java/com/redhat/thermostat/killvm/client/internal/TranslateTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-2016 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.killvm.client.internal;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class TranslateTest {
+
+    private Locale lang;
+    private Translate<LocaleResources> t;
+
+    @Before
+    public void setUp() {
+        this.lang = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        t = LocaleResources.createLocalizer();
+    }
+
+    @After
+    public void tearDown() {
+        Locale.setDefault(lang);
+        t = null;
+    }
+    
+    @Test
+    public void testLocalizeWithoutArguments() {
+        String testString = t.localize(LocaleResources.MISSING_INFO).getContents();
+        Assert.assertEquals("Missing Information", testString);
+    }
+    
+    @Test
+    public void testLocalizedStringsArePresent() throws IOException {
+
+        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
+
+        Properties props = new Properties();
+        props.load(getClass().getResourceAsStream(stringsResource));
+
+        Assert.assertEquals(LocaleResources.values().length, props.values().size());
+        for (LocaleResources resource : LocaleResources.values()) {
+            Assert.assertTrue("missing property from resource bound file: " + resource,
+                              props.containsKey(resource.name()));
+        }
+    }
+    
+}
+
--- a/killvm/client-swing/src/test/java/com/redhat/thermostat/killvm/client/locale/TranslateTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.client.locale;
-
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Properties;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.killvm.client.locale.LocaleResources;
-import com.redhat.thermostat.shared.locale.Translate;
-
-public class TranslateTest {
-
-    private Locale lang;
-    private Translate<LocaleResources> t;
-
-    @Before
-    public void setUp() {
-        this.lang = Locale.getDefault();
-        Locale.setDefault(Locale.US);
-        t = LocaleResources.createLocalizer();
-    }
-
-    @After
-    public void tearDown() {
-        Locale.setDefault(lang);
-        t = null;
-    }
-    
-    @Test
-    public void testLocalizeWithoutArguments() {
-        String testString = t.localize(LocaleResources.MISSING_INFO).getContents();
-        Assert.assertEquals("Missing Information", testString);
-    }
-    
-    @Test
-    public void testLocalizedStringsArePresent() throws IOException {
-
-        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
-
-        Properties props = new Properties();
-        props.load(getClass().getResourceAsStream(stringsResource));
-
-        Assert.assertEquals(LocaleResources.values().length, props.values().size());
-        for (LocaleResources resource : LocaleResources.values()) {
-            Assert.assertTrue("missing property from resource bound file: " + resource,
-                              props.containsKey(resource.name()));
-        }
-    }
-    
-}
-
--- a/killvm/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -60,12 +60,8 @@
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-Activator>com.redhat.thermostat.killvm.command.internal.Activator</Bundle-Activator>
             <Bundle-SymbolicName>com.redhat.thermostat.killvm.command</Bundle-SymbolicName>
-            <Export-Package>
-              com.redhat.thermostat.killvm.command,
-            </Export-Package>
             <Private-Package>
               com.redhat.thermostat.killvm.command.internal,
-              com.redhat.thermostat.killvm.command.locale,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/KillVMCommand.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.command;
-
-import com.redhat.thermostat.client.cli.VmArgument;
-import com.redhat.thermostat.common.cli.AbstractCommand;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.killvm.command.internal.ShellVMKilledListener;
-import com.redhat.thermostat.killvm.command.locale.LocaleResources;
-import com.redhat.thermostat.killvm.common.KillVMRequest;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.AgentId;
-import com.redhat.thermostat.storage.core.VmId;
-import com.redhat.thermostat.storage.dao.AgentInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class KillVMCommand extends AbstractCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final ShellVMKilledListener listener;
-
-    private VmInfoDAO vmInfoDAO;
-    private AgentInfoDAO agentInfoDAO;
-    private KillVMRequest request;
-
-    public KillVMCommand(ShellVMKilledListener listener) {
-        this.listener = listener;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        requireNonNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
-        requireNonNull(agentInfoDAO, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE));
-        requireNonNull(request, translator.localize(LocaleResources.REQUEST_SERVICE_UNAVAILABLE));
-
-        listener.setOut(ctx.getConsole().getOutput());
-        listener.setErr(ctx.getConsole().getError());
-
-        VmArgument vmArgument = VmArgument.required(ctx.getArguments());
-        attemptToKillVM(vmArgument.getVmId());
-    }
-
-    private void attemptToKillVM(VmId vmId) throws CommandException {
-        VmInfo result = vmInfoDAO.getVmInfo(vmId);
-        if (result == null) {
-            throw new CommandException(translator.localize(LocaleResources.VM_NOT_FOUND, vmId.get()));
-        }
-        sendKillRequest(new AgentId(result.getAgentId()), result.getVmPid());
-    }
-
-    private void sendKillRequest(AgentId agentId, int pid) throws CommandException {
-        request.sendKillVMRequestToAgent(agentId, pid, agentInfoDAO, listener);
-
-        waitForListenerResponse();
-    }
-
-    private void waitForListenerResponse() throws CommandException {
-        try {
-            listener.await(1000l);
-        } catch (InterruptedException e) {
-            throw new CommandException(translator.localize(LocaleResources.KILL_INTERRUPTED));
-        }
-    }
-
-    public void setVmInfoDAO(VmInfoDAO vmInfoDAO) {
-        this.vmInfoDAO = vmInfoDAO;
-    }
-
-    public void setAgentInfoDAO(AgentInfoDAO agentInfoDAO) {
-        this.agentInfoDAO = agentInfoDAO;
-    }
-
-    public void setKillVMRequest(KillVMRequest request) {
-        this.request = request;
-    }
-}
--- a/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -46,7 +46,6 @@
 import com.redhat.thermostat.client.command.RequestQueue;
 import com.redhat.thermostat.common.MultipleServiceTracker;
 import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.killvm.command.KillVMCommand;
 import com.redhat.thermostat.killvm.common.KillVMRequest;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/KillVMCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012-2016 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.killvm.command.internal;
+
+import com.redhat.thermostat.client.cli.VmArgument;
+import com.redhat.thermostat.common.cli.AbstractCommand;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.killvm.common.KillVMRequest;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class KillVMCommand extends AbstractCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final ShellVMKilledListener listener;
+
+    private VmInfoDAO vmInfoDAO;
+    private AgentInfoDAO agentInfoDAO;
+    private KillVMRequest request;
+
+    public KillVMCommand(ShellVMKilledListener listener) {
+        this.listener = listener;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        requireNonNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
+        requireNonNull(agentInfoDAO, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE));
+        requireNonNull(request, translator.localize(LocaleResources.REQUEST_SERVICE_UNAVAILABLE));
+
+        listener.setOut(ctx.getConsole().getOutput());
+        listener.setErr(ctx.getConsole().getError());
+
+        VmArgument vmArgument = VmArgument.required(ctx.getArguments());
+        attemptToKillVM(vmArgument.getVmId());
+    }
+
+    private void attemptToKillVM(VmId vmId) throws CommandException {
+        VmInfo result = vmInfoDAO.getVmInfo(vmId);
+        if (result == null) {
+            throw new CommandException(translator.localize(LocaleResources.VM_NOT_FOUND, vmId.get()));
+        }
+        sendKillRequest(new AgentId(result.getAgentId()), result.getVmPid());
+    }
+
+    private void sendKillRequest(AgentId agentId, int pid) throws CommandException {
+        request.sendKillVMRequestToAgent(agentId, pid, agentInfoDAO, listener);
+
+        waitForListenerResponse();
+    }
+
+    private void waitForListenerResponse() throws CommandException {
+        try {
+            listener.await(1000l);
+        } catch (InterruptedException e) {
+            throw new CommandException(translator.localize(LocaleResources.KILL_INTERRUPTED));
+        }
+    }
+
+    public void setVmInfoDAO(VmInfoDAO vmInfoDAO) {
+        this.vmInfoDAO = vmInfoDAO;
+    }
+
+    public void setAgentInfoDAO(AgentInfoDAO agentInfoDAO) {
+        this.agentInfoDAO = agentInfoDAO;
+    }
+
+    public void setKillVMRequest(KillVMRequest request) {
+        this.request = request;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2016 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.killvm.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    HOST_SERVICE_UNAVAILABLE,
+    VM_SERVICE_UNAVAILABLE,
+    AGENT_SERVICE_UNAVAILABLE,
+    REQUEST_SERVICE_UNAVAILABLE,
+    KILL_INTERRUPTED,
+    VM_NOT_FOUND;
+
+    public static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.killvm.command.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
--- a/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    HOST_SERVICE_UNAVAILABLE,
-    VM_SERVICE_UNAVAILABLE,
-    AGENT_SERVICE_UNAVAILABLE,
-    REQUEST_SERVICE_UNAVAILABLE,
-    KILL_INTERRUPTED,
-    VM_NOT_FOUND;
-
-    public static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.killvm.command.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
--- a/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/KillVmCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.command;
-
-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 org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.client.cli.VmArgument;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.killvm.command.internal.ShellVMKilledListener;
-import com.redhat.thermostat.killvm.common.KillVMRequest;
-import com.redhat.thermostat.storage.core.AgentId;
-import com.redhat.thermostat.storage.core.VmId;
-import com.redhat.thermostat.storage.dao.AgentInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class KillVmCommandTest {
-
-    private TestCommandContextFactory cmdCtxFactory;
-    private KillVMCommand cmd;
-
-    private VmInfoDAO vmInfoDAO;
-    private AgentInfoDAO agentInfoDAO;
-
-    private ShellVMKilledListener listener;
-    private KillVMRequest request;
-
-    @Before
-    public void setup() {
-        cmdCtxFactory = new TestCommandContextFactory();
-
-        vmInfoDAO = mock(VmInfoDAO.class);
-        agentInfoDAO = mock(AgentInfoDAO.class);
-
-        listener = mock(ShellVMKilledListener.class);
-        request = mock(KillVMRequest.class);
-
-        cmd = new KillVMCommand(listener);
-    }
-
-    @Test
-    public void testKillLiveVM() throws CommandException, InterruptedException {
-        String vmId = "liveVM";
-
-        VmInfo vmInfo = new VmInfo("myAgent", vmId, 123, 0, 0, null, null, null, null, null, null, null, null, null,
-                null, null,0, "myUsername");
-        when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(vmInfo);
-
-        CommandContext ctx = createContext(vmId);
-
-        setServices();
-        cmd.run(ctx);
-
-        verify(request).sendKillVMRequestToAgent(any(AgentId.class), any(int.class), any(AgentInfoDAO.class), any(RequestResponseListener.class));
-    }
-
-    @Test(expected = CommandException.class)
-    public void testKillNonexistentVM() throws CommandException {
-        String vmId = "nonexistentVM";
-
-        when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(null);
-
-        CommandContext ctx = createContext(vmId);
-        setServices();
-
-        cmd.run(ctx);
-    }
-
-    @Test(expected = CommandException.class)
-    public void testNoVMArgument() throws CommandException {
-        SimpleArguments args = new SimpleArguments();
-        CommandContext ctx = cmdCtxFactory.createContext(args);
-        setServices();
-        cmd.run(ctx);
-    }
-
-    public CommandContext createContext(String vmId) {
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument(VmArgument.ARGUMENT_NAME, vmId);
-        return cmdCtxFactory.createContext(args);
-    }
-
-    private void setServices() {
-        cmd.setVmInfoDAO(vmInfoDAO);
-        cmd.setAgentInfoDAO(agentInfoDAO);
-        cmd.setKillVMRequest(request);
-
-    }
-}
--- a/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/ActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/ActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -41,7 +41,6 @@
 
 import org.junit.Test;
 
-import com.redhat.thermostat.killvm.command.KillVMCommand;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
 public class ActivatorTest {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/KillVmCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-2016 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.killvm.command.internal;
+
+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 org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.client.cli.VmArgument;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
+import com.redhat.thermostat.killvm.command.internal.KillVMCommand;
+import com.redhat.thermostat.killvm.command.internal.ShellVMKilledListener;
+import com.redhat.thermostat.killvm.common.KillVMRequest;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class KillVmCommandTest {
+
+    private TestCommandContextFactory cmdCtxFactory;
+    private KillVMCommand cmd;
+
+    private VmInfoDAO vmInfoDAO;
+    private AgentInfoDAO agentInfoDAO;
+
+    private ShellVMKilledListener listener;
+    private KillVMRequest request;
+
+    @Before
+    public void setup() {
+        cmdCtxFactory = new TestCommandContextFactory();
+
+        vmInfoDAO = mock(VmInfoDAO.class);
+        agentInfoDAO = mock(AgentInfoDAO.class);
+
+        listener = mock(ShellVMKilledListener.class);
+        request = mock(KillVMRequest.class);
+
+        cmd = new KillVMCommand(listener);
+    }
+
+    @Test
+    public void testKillLiveVM() throws CommandException, InterruptedException {
+        String vmId = "liveVM";
+
+        VmInfo vmInfo = new VmInfo("myAgent", vmId, 123, 0, 0, null, null, null, null, null, null, null, null, null,
+                null, null,0, "myUsername");
+        when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(vmInfo);
+
+        CommandContext ctx = createContext(vmId);
+
+        setServices();
+        cmd.run(ctx);
+
+        verify(request).sendKillVMRequestToAgent(any(AgentId.class), any(int.class), any(AgentInfoDAO.class), any(RequestResponseListener.class));
+    }
+
+    @Test(expected = CommandException.class)
+    public void testKillNonexistentVM() throws CommandException {
+        String vmId = "nonexistentVM";
+
+        when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(null);
+
+        CommandContext ctx = createContext(vmId);
+        setServices();
+
+        cmd.run(ctx);
+    }
+
+    @Test(expected = CommandException.class)
+    public void testNoVMArgument() throws CommandException {
+        SimpleArguments args = new SimpleArguments();
+        CommandContext ctx = cmdCtxFactory.createContext(args);
+        setServices();
+        cmd.run(ctx);
+    }
+
+    public CommandContext createContext(String vmId) {
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument(VmArgument.ARGUMENT_NAME, vmId);
+        return cmdCtxFactory.createContext(args);
+    }
+
+    private void setServices() {
+        cmd.setVmInfoDAO(vmInfoDAO);
+        cmd.setAgentInfoDAO(agentInfoDAO);
+        cmd.setKillVMRequest(request);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-2016 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.killvm.command.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+}
--- a/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012-2016 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.killvm.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleLoaderTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleLoaderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,8 +53,8 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.launch.Framework;
 
+import com.redhat.thermostat.common.internal.test.Bug;
 import com.redhat.thermostat.launcher.internal.BundleLoader;
-import com.redhat.thermostat.test.Bug;
 
 public class BundleLoaderTest {
 
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/HelpCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/HelpCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -52,7 +52,7 @@
 
 import com.redhat.thermostat.common.cli.Arguments;
 import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 
 public class HelpCommandTest {
 
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherImplTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/LauncherImplTest.java	Tue May 03 15:49:54 2016 +0200
@@ -82,6 +82,8 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.CommandRegistry;
 import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestTimerFactory;
 import com.redhat.thermostat.common.tools.ApplicationState;
 import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.BundleManager;
@@ -92,8 +94,6 @@
 import com.redhat.thermostat.storage.core.DbService;
 import com.redhat.thermostat.storage.core.DbServiceFactory;
 import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.test.TestTimerFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.utils.keyring.Keyring;
 
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -66,10 +66,10 @@
 import com.redhat.thermostat.common.cli.SimpleArguments;
 import com.redhat.thermostat.common.config.ClientPreferences;
 import com.redhat.thermostat.common.config.experimental.ConfigurationInfoSource;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.common.utils.StringUtils;
 import com.redhat.thermostat.launcher.Launcher;
 import com.redhat.thermostat.launcher.internal.ShellCommand.HistoryProvider;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 
 import jline.TerminalFactory;
 import jline.TerminalFactory.Flavor;
--- a/local/command/src/main/java/com/redhat/thermostat/local/command/internal/LocalCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/local/command/src/main/java/com/redhat/thermostat/local/command/internal/LocalCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -40,7 +40,6 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.DependencyServices;
-import com.redhat.thermostat.local.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.launcher.Launcher;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/local/command/src/main/java/com/redhat/thermostat/local/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012-2016 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.local.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+
+public enum LocaleResources {
+
+    SERVICE_UNAVAILABLE_MESSAGE,
+    ERROR_STARTING_SERVICE,
+    STOPPING_SERVICE_INTERRUPTED,
+    SERVICE_WAIT_INTERRUPTED,
+    ERROR_STARTING_GUI,
+    ERROR_RUNNING_GUI,
+    RUNNING_GUI_INTERRUPTED,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.config.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- a/local/command/src/main/java/com/redhat/thermostat/local/command/internal/ServiceLauncher.java	Mon May 02 18:43:01 2016 +0200
+++ b/local/command/src/main/java/com/redhat/thermostat/local/command/internal/ServiceLauncher.java	Tue May 03 15:49:54 2016 +0200
@@ -43,7 +43,6 @@
 import com.redhat.thermostat.common.tools.ApplicationState;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.launcher.Launcher;
-import com.redhat.thermostat.local.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/local/command/src/main/java/com/redhat/thermostat/local/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012-2016 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.local.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-
-public enum LocaleResources {
-
-    SERVICE_UNAVAILABLE_MESSAGE,
-    ERROR_STARTING_SERVICE,
-    STOPPING_SERVICE_INTERRUPTED,
-    SERVICE_WAIT_INTERRUPTED,
-    ERROR_STARTING_GUI,
-    ERROR_RUNNING_GUI,
-    RUNNING_GUI_INTERRUPTED,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.config.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/local/command/src/test/java/com/redhat/thermostat/local/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 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.local.command.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- a/local/command/src/test/java/com/redhat/thermostat/local/command/internal/ServiceLauncherTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/local/command/src/test/java/com/redhat/thermostat/local/command/internal/ServiceLauncherTest.java	Tue May 03 15:49:54 2016 +0200
@@ -42,7 +42,6 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.tools.ApplicationState;
 import com.redhat.thermostat.launcher.Launcher;
-import com.redhat.thermostat.local.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 import org.junit.Before;
 import org.junit.Test;
--- a/local/command/src/test/java/com/redhat/thermostat/local/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.local.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/notes/client-cli/src/test/java/com/redhat/thermostat/notes/client/cli/internal/AbstractNotesCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/notes/client-cli/src/test/java/com/redhat/thermostat/notes/client/cli/internal/AbstractNotesCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -41,6 +41,7 @@
 import com.redhat.thermostat.common.cli.Arguments;
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.notes.client.cli.locale.LocaleResources;
 import com.redhat.thermostat.notes.common.HostNoteDAO;
 import com.redhat.thermostat.notes.common.VmNoteDAO;
@@ -55,7 +56,7 @@
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.HostInfo;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
+
 import org.junit.Before;
 import org.junit.Test;
 
--- a/platform/core/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/platform/core/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -140,15 +140,15 @@
                             com.redhat.thermostat.platform.event,
                         </Export-Package>
                         <Private-Package>
-                            com.redhat.thermostat.platform.command,
                             com.redhat.thermostat.platform.internal,
+                            com.redhat.thermostat.platform.internal.annotations.processor,
                             com.redhat.thermostat.platform.internal.application,
                             com.redhat.thermostat.platform.internal.application.lifecycle,
+                            com.redhat.thermostat.platform.internal.command,
                             com.redhat.thermostat.platform.internal.mvc,
                             com.redhat.thermostat.platform.internal.mvc.lifecycle,
                             com.redhat.thermostat.platform.internal.mvc.lifecycle.handlers,
                             com.redhat.thermostat.platform.internal.locale,
-                            com.redhat.thermostat.platform.annotations.processor,
                         </Private-Package>
                         <!--Do not autogenerate uses clauses in Manifests -->
                         <_nouses>true</_nouses>
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/annotations/processor/PlatformConfigurationProcessor.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright 2012-2016 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.platform.annotations.processor;
-
-import com.google.gson.FieldNamingPolicy;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.platform.ApplicationProvider;
-import com.redhat.thermostat.platform.annotations.ApplicationDescriptor;
-import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
-
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Messager;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedSourceVersion;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
-import javax.tools.Diagnostic;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-/**
- */
-@SupportedAnnotationTypes("com.redhat.thermostat.platform.annotations.ApplicationDescriptor")
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
-public class PlatformConfigurationProcessor extends AbstractProcessor {
-
-    @Override
-    public boolean process(Set<? extends TypeElement> annotations,
-                           RoundEnvironment roundEnv)
-    {
-        if(roundEnv.processingOver()) {
-            return false;
-        }
-
-        ApplicationInfo info = new ApplicationInfo();
-        info.applications = new ArrayList<>();
-
-        Types types = processingEnv.getTypeUtils();
-        Elements elements = processingEnv.getElementUtils();
-        String applicationProvider =
-                ApplicationProvider.class.getCanonicalName();
-        
-        TypeMirror providerInterface =
-                elements.getTypeElement(applicationProvider).asType();
-        
-        Messager messager = processingEnv.getMessager();
-        for (Element element :
-             roundEnv.getElementsAnnotatedWith(ApplicationDescriptor.class))
-        {
-            messager.printMessage(Diagnostic.Kind.NOTE,
-                                  "for element: " + element);
-            
-            boolean isSame = types.isSubtype(element.asType(), providerInterface);
-
-            if (!isSame) {
-                messager.printMessage(Diagnostic.Kind.ERROR,
-                                      "Cannot process element " + element +
-                                      " - must be of type: " +
-                                      ApplicationProvider.class);
-                continue;
-            }
-            
-            ApplicationDescriptor descriptor =
-                    element.getAnnotation(ApplicationDescriptor.class);
-            ApplicationInfo.Application data =
-                    new ApplicationInfo.Application();
-
-            data.name = descriptor.name();
-            data.provider = element.asType().toString() + ".class";
-
-            messager.printMessage(Diagnostic.Kind.NOTE,
-                                  "application provider class: " +
-                                  data.provider);
-            messager.printMessage(Diagnostic.Kind.NOTE,
-                                  "application name: " + data.name);
-            
-            info.applications.add(data);
-        }
-
-        if (!info.applications.isEmpty()) {
-            writeConfigurations(messager, info);
-        }
-
-        return false;
-    }
-
-    private void writeConfigurations(Messager messager, ApplicationInfo info) {
-        Map<String, String> options = processingEnv.getOptions();
-        String jsonFileName = options.get("name");
-        if (jsonFileName == null) {
-            jsonFileName = info.applications.get(0).name;
-        }
-
-        Gson gson = new GsonBuilder().
-                setPrettyPrinting().
-                setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).
-                create();
-        String json = gson.toJson(info) + "\n";
-
-        messager.printMessage(Diagnostic.Kind.NOTE,
-                              "writing json configuration...");
-
-        try {
-            Filer filer = processingEnv.getFiler();
-            FileObject output =
-                    filer.createResource(StandardLocation.SOURCE_OUTPUT,
-                                         "",
-                                         jsonFileName  + ".json");
-
-            Writer writer = output.openWriter();
-            writer.append(json);
-            writer.flush();
-
-            messager.printMessage(Diagnostic.Kind.NOTE, "done!");
-
-        } catch (IOException e) {
-            messager.printMessage(Diagnostic.Kind.ERROR,
-                                  "cannot write json configuration file");
-
-        }
-    }
-}
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/command/PlatformCommand.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright 2012-2016 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.platform.command;
-
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.cli.AbstractCommand;
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
-import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
-import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
-import com.redhat.thermostat.platform.internal.application.lifecycle.ShutdownHook;
-import com.redhat.thermostat.shared.config.CommonPaths;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Service;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-import java.util.concurrent.CountDownLatch;
-
-@Component
-@Service(Command.class)
-@Property(name = Command.NAME, value = PlatformCommand.NAME)
-public class PlatformCommand extends AbstractCommand {
-    
-    static final String NAME = "platform";
-
-    @Reference(bind = "bindCommonPaths", unbind = "unbindCommonPaths")
-    private CommonPaths paths;
-
-    @Reference(bind = "bindApplicationService", unbind = "unbindApplicationService")
-    private ApplicationService appService;
-    
-    private ConfigurationManager manager;
-    private ApplicationLifeCycleManager lifeCycleManager;
-
-    private ApplicationRegistry platformRegistry;
-    
-    public PlatformCommand() {}
-
-    protected void bindCommonPaths(CommonPaths paths) {
-        this.paths = paths;
-    }
-    
-    protected void unbindCommonPaths(CommonPaths paths) {
-        this.paths = null;
-    }
-
-    protected void bindApplicationService(ApplicationService service) {
-        this.appService = service;
-    }
-    
-    protected void unbindApplicationService(ApplicationService service) {
-        this.appService = null;
-    }
-    
-    @Activate
-    protected void activate() throws CommandException {
-
-        CountDownLatch latch = new CountDownLatch(1);
-        lifeCycleManager = new ApplicationLifeCycleManager(latch);
-        
-        ShutdownHook.register(lifeCycleManager);
-        
-        BundleContext context =
-                FrameworkUtil.getBundle(getClass()).getBundleContext();
-        
-        manager = new ConfigurationManager(paths);
-        
-        platformRegistry = new ApplicationRegistry(context);
-    }
-
-    @Override
-    public boolean isStorageRequired() {
-        return false;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        if (ctx.getArguments().hasArgument("list")) {
-            PlatformCommandDelegate.listApplications(ctx, manager);
-            return;
-        }
-        
-        String argument = ctx.getArguments().getArgument("launch");
-        if (argument != null) {
-
-            PlatformCommandDelegate.executePlatform(ctx, argument, manager,
-                                                    platformRegistry,
-                                                    lifeCycleManager);
-            return;
-        }
-    }
-}
--- a/platform/core/src/main/java/com/redhat/thermostat/platform/command/PlatformCommandDelegate.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012-2016 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.platform.command;
-
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.TableRenderer;
-import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
-import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
-import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
-import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
-
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.COLUMN_SEPARATOR;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.COMMAND_H_SEPARATOR;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.HEADER_COMMAND;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.HEADER_PROVIDER;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.INVALID_PLATFORM;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.PROVIDER_H_SEPARATOR;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.V_SEPARATOR;
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.translate;
-
-class PlatformCommandDelegate {
-
-    static void listApplications(CommandContext ctx, ConfigurationManager manager) {
-        ApplicationInfo infos = manager.getApplicationConfigs();
-        TableRenderer renderer = new TableRenderer(3, 2);
-        renderer.printLine(translate(HEADER_COMMAND),
-                           translate(COLUMN_SEPARATOR),
-                           translate(HEADER_PROVIDER));
-        renderer.printLine(translate(COMMAND_H_SEPARATOR),
-                           translate(V_SEPARATOR),
-                           translate(PROVIDER_H_SEPARATOR));
-        for (ApplicationInfo.Application info : infos.applications) {
-            renderer.printLine(info.name, translate(COLUMN_SEPARATOR), info.provider);
-        }
-        renderer.render(ctx.getConsole().getOutput());
-    }
-
-    static void startPlatform(CommandContext ctx, String id,
-                              ConfigurationManager manager,
-                              ApplicationRegistry registry,
-                              ApplicationLifeCycleManager lifeCycleManager)
-    {
-        ApplicationInfo.Application info = manager.getApplicationConfig(id);
-        if (info == null) {
-            ctx.getConsole().getOutput().println(translate(INVALID_PLATFORM, id));
-            return;
-        }
-
-        lifeCycleManager.setTarget(info);
-        lifeCycleManager.registerShutdownService();
-        lifeCycleManager.registerMDIService();
-        registry.addRegistryEventListener(lifeCycleManager);
-        registry.start();
-    }
-
-    static void stopPlatform(ApplicationRegistry registry) {
-        registry.stop();
-    }
-
-    public static void executePlatform(CommandContext ctx, String id,
-                                       ConfigurationManager manager,
-                                       ApplicationRegistry registry,
-                                       ApplicationLifeCycleManager lifeCycleManager)
-    {
-        startPlatform(ctx, id, manager, registry, lifeCycleManager);
-
-        lifeCycleManager.execute();
-
-        stopPlatform(registry);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/annotations/processor/PlatformConfigurationProcessor.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2012-2016 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.platform.internal.annotations.processor;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.redhat.thermostat.platform.ApplicationProvider;
+import com.redhat.thermostat.platform.annotations.ApplicationDescriptor;
+import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ */
+@SupportedAnnotationTypes("com.redhat.thermostat.platform.annotations.ApplicationDescriptor")
+@SupportedSourceVersion(SourceVersion.RELEASE_7)
+public class PlatformConfigurationProcessor extends AbstractProcessor {
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations,
+                           RoundEnvironment roundEnv)
+    {
+        if(roundEnv.processingOver()) {
+            return false;
+        }
+
+        ApplicationInfo info = new ApplicationInfo();
+        info.applications = new ArrayList<>();
+
+        Types types = processingEnv.getTypeUtils();
+        Elements elements = processingEnv.getElementUtils();
+        String applicationProvider =
+                ApplicationProvider.class.getCanonicalName();
+        
+        TypeMirror providerInterface =
+                elements.getTypeElement(applicationProvider).asType();
+        
+        Messager messager = processingEnv.getMessager();
+        for (Element element :
+             roundEnv.getElementsAnnotatedWith(ApplicationDescriptor.class))
+        {
+            messager.printMessage(Diagnostic.Kind.NOTE,
+                                  "for element: " + element);
+            
+            boolean isSame = types.isSubtype(element.asType(), providerInterface);
+
+            if (!isSame) {
+                messager.printMessage(Diagnostic.Kind.ERROR,
+                                      "Cannot process element " + element +
+                                      " - must be of type: " +
+                                      ApplicationProvider.class);
+                continue;
+            }
+            
+            ApplicationDescriptor descriptor =
+                    element.getAnnotation(ApplicationDescriptor.class);
+            ApplicationInfo.Application data =
+                    new ApplicationInfo.Application();
+
+            data.name = descriptor.name();
+            data.provider = element.asType().toString() + ".class";
+
+            messager.printMessage(Diagnostic.Kind.NOTE,
+                                  "application provider class: " +
+                                  data.provider);
+            messager.printMessage(Diagnostic.Kind.NOTE,
+                                  "application name: " + data.name);
+            
+            info.applications.add(data);
+        }
+
+        if (!info.applications.isEmpty()) {
+            writeConfigurations(messager, info);
+        }
+
+        return false;
+    }
+
+    private void writeConfigurations(Messager messager, ApplicationInfo info) {
+        Map<String, String> options = processingEnv.getOptions();
+        String jsonFileName = options.get("name");
+        if (jsonFileName == null) {
+            jsonFileName = info.applications.get(0).name;
+        }
+
+        Gson gson = new GsonBuilder().
+                setPrettyPrinting().
+                setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).
+                create();
+        String json = gson.toJson(info) + "\n";
+
+        messager.printMessage(Diagnostic.Kind.NOTE,
+                              "writing json configuration...");
+
+        try {
+            Filer filer = processingEnv.getFiler();
+            FileObject output =
+                    filer.createResource(StandardLocation.SOURCE_OUTPUT,
+                                         "",
+                                         jsonFileName  + ".json");
+
+            Writer writer = output.openWriter();
+            writer.append(json);
+            writer.flush();
+
+            messager.printMessage(Diagnostic.Kind.NOTE, "done!");
+
+        } catch (IOException e) {
+            messager.printMessage(Diagnostic.Kind.ERROR,
+                                  "cannot write json configuration file");
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012-2016 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.platform.internal.command;
+
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.cli.AbstractCommand;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
+import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
+import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
+import com.redhat.thermostat.platform.internal.application.lifecycle.ShutdownHook;
+import com.redhat.thermostat.shared.config.CommonPaths;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+import java.util.concurrent.CountDownLatch;
+
+@Component
+@Service(Command.class)
+@Property(name = Command.NAME, value = PlatformCommand.NAME)
+public class PlatformCommand extends AbstractCommand {
+    
+    static final String NAME = "platform";
+
+    @Reference(bind = "bindCommonPaths", unbind = "unbindCommonPaths")
+    private CommonPaths paths;
+
+    @Reference(bind = "bindApplicationService", unbind = "unbindApplicationService")
+    private ApplicationService appService;
+    
+    private ConfigurationManager manager;
+    private ApplicationLifeCycleManager lifeCycleManager;
+
+    private ApplicationRegistry platformRegistry;
+    
+    public PlatformCommand() {}
+
+    protected void bindCommonPaths(CommonPaths paths) {
+        this.paths = paths;
+    }
+    
+    protected void unbindCommonPaths(CommonPaths paths) {
+        this.paths = null;
+    }
+
+    protected void bindApplicationService(ApplicationService service) {
+        this.appService = service;
+    }
+    
+    protected void unbindApplicationService(ApplicationService service) {
+        this.appService = null;
+    }
+    
+    @Activate
+    protected void activate() throws CommandException {
+
+        CountDownLatch latch = new CountDownLatch(1);
+        lifeCycleManager = new ApplicationLifeCycleManager(latch);
+        
+        ShutdownHook.register(lifeCycleManager);
+        
+        BundleContext context =
+                FrameworkUtil.getBundle(getClass()).getBundleContext();
+        
+        manager = new ConfigurationManager(paths);
+        
+        platformRegistry = new ApplicationRegistry(context);
+    }
+
+    @Override
+    public boolean isStorageRequired() {
+        return false;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        if (ctx.getArguments().hasArgument("list")) {
+            PlatformCommandDelegate.listApplications(ctx, manager);
+            return;
+        }
+        
+        String argument = ctx.getArguments().getArgument("launch");
+        if (argument != null) {
+
+            PlatformCommandDelegate.executePlatform(ctx, argument, manager,
+                                                    platformRegistry,
+                                                    lifeCycleManager);
+            return;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/main/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegate.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012-2016 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.platform.internal.command;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.TableRenderer;
+import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
+import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
+import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
+import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
+
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.COLUMN_SEPARATOR;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.COMMAND_H_SEPARATOR;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.HEADER_COMMAND;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.HEADER_PROVIDER;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.INVALID_PLATFORM;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.PROVIDER_H_SEPARATOR;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.V_SEPARATOR;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.translate;
+
+class PlatformCommandDelegate {
+
+    static void listApplications(CommandContext ctx, ConfigurationManager manager) {
+        ApplicationInfo infos = manager.getApplicationConfigs();
+        TableRenderer renderer = new TableRenderer(3, 2);
+        renderer.printLine(translate(HEADER_COMMAND),
+                           translate(COLUMN_SEPARATOR),
+                           translate(HEADER_PROVIDER));
+        renderer.printLine(translate(COMMAND_H_SEPARATOR),
+                           translate(V_SEPARATOR),
+                           translate(PROVIDER_H_SEPARATOR));
+        for (ApplicationInfo.Application info : infos.applications) {
+            renderer.printLine(info.name, translate(COLUMN_SEPARATOR), info.provider);
+        }
+        renderer.render(ctx.getConsole().getOutput());
+    }
+
+    static void startPlatform(CommandContext ctx, String id,
+                              ConfigurationManager manager,
+                              ApplicationRegistry registry,
+                              ApplicationLifeCycleManager lifeCycleManager)
+    {
+        ApplicationInfo.Application info = manager.getApplicationConfig(id);
+        if (info == null) {
+            ctx.getConsole().getOutput().println(translate(INVALID_PLATFORM, id));
+            return;
+        }
+
+        lifeCycleManager.setTarget(info);
+        lifeCycleManager.registerShutdownService();
+        lifeCycleManager.registerMDIService();
+        registry.addRegistryEventListener(lifeCycleManager);
+        registry.start();
+    }
+
+    static void stopPlatform(ApplicationRegistry registry) {
+        registry.stop();
+    }
+
+    public static void executePlatform(CommandContext ctx, String id,
+                                       ConfigurationManager manager,
+                                       ApplicationRegistry registry,
+                                       ApplicationLifeCycleManager lifeCycleManager)
+    {
+        startPlatform(ctx, id, manager, registry, lifeCycleManager);
+
+        lifeCycleManager.execute();
+
+        stopPlatform(registry);
+    }
+}
--- a/platform/core/src/main/resources/META-INF/services/javax.annotation.processing.Processor	Mon May 02 18:43:01 2016 +0200
+++ b/platform/core/src/main/resources/META-INF/services/javax.annotation.processing.Processor	Tue May 03 15:49:54 2016 +0200
@@ -1,1 +1,1 @@
-com.redhat.thermostat.platform.annotations.processor.PlatformConfigurationProcessor
+com.redhat.thermostat.platform.internal.annotations.processor.PlatformConfigurationProcessor
--- a/platform/core/src/test/java/com/redhat/thermostat/platform/command/PlatformCommandDelegateTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright 2012-2016 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.platform.command;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Locale;
-import java.util.concurrent.CountDownLatch;
-
-import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
-
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-import static org.junit.Assert.assertTrue;
-
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.Console;
-import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
-import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
-import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
-
-import static com.redhat.thermostat.platform.internal.locale.LocaleResources.*;
-
-public class PlatformCommandDelegateTest {
-
-    private CommandContext ctx;
-    private ConfigurationManager manager;
-    private Console console;
-    private ByteArrayOutputStream stream;
-    private PrintStream out;
-    private CountDownLatch latch;
-
-    private ApplicationRegistry registry;
-    private ApplicationLifeCycleManager lifeCycleManager;
-
-    private static Locale locale;
-    
-    @BeforeClass
-    public static void init() {
-        locale = Locale.getDefault();
-        Locale.setDefault(Locale.US);
-    }
-    
-    @AfterClass
-    public static void cleanup() {
-        Locale.setDefault(locale);
-    }
-    
-    @Before
-    public void setUp() {
-        ctx = mock(CommandContext.class);
-        manager = mock(ConfigurationManager.class);
-        console = mock(Console.class);        
-        registry = mock(ApplicationRegistry.class);
-        latch = mock(CountDownLatch.class);
-        lifeCycleManager = mock(ApplicationLifeCycleManager.class);
-
-        stream = new ByteArrayOutputStream();
-        out = new PrintStream(stream);
-        
-        when(ctx.getConsole()).thenReturn(console);
-        when(console.getOutput()).thenReturn(out);
-    }
-    
-    @Test
-    public void testListCommands() {
-        
-        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
-        info0.name = "0";
-        info0.provider = "provider0";
-        
-        ApplicationInfo.Application info1 = new ApplicationInfo.Application();
-        info1.name = "1";
-        info1.provider = "provider1";
-        
-        ApplicationInfo infos = new ApplicationInfo();
-        infos.applications = new ArrayList<>();
-        infos.applications.add(info0);
-        infos.applications.add(info1);
-        
-        when(manager.getApplicationConfigs()).thenReturn(infos);
-
-        PlatformCommandDelegate.listApplications(ctx, manager);
-        
-        String content = stream.toString();
-
-        // the number of spaces is dependent on the
-        // header length, so also changes based on the locale
-        assertTrue(content.contains("0       |  provider0"));
-        assertTrue(content.contains("1       |  provider1"));
-    }
-    
-    @Test
-    public void testStartInvalidPlatform() {
-        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
-        info0.name = "0";
-        info0.provider = "provider0";
-        
-        ApplicationInfo infos = new ApplicationInfo();
-        infos.applications = new ArrayList<>();
-        infos.applications.add(info0);
-        
-        when(manager.getApplicationConfigs()).thenReturn(infos);
-        when(ctx.getConsole()).thenReturn(console);
-        when(console.getOutput()).thenReturn(out);
-
-        PlatformCommandDelegate.startPlatform(ctx, "1", manager, registry,
-                                              lifeCycleManager);
-        
-        String content = stream.toString();
-
-        // this is also dependent on the locale
-        assertTrue(content.contains(translate(INVALID_PLATFORM, "1")));
-    }
-    
-    @Test
-    public void testStartPlatform() {
-        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
-        info0.name = "0";
-        info0.provider = "provider0";
-        
-        // this also implicitly tests that name '0' is correctly passed
-        // as an argument to getApplicationConfig inside the startPlatform
-        // method
-        when(manager.getApplicationConfig("0")).thenReturn(info0);
-
-        PlatformCommandDelegate.startPlatform(ctx, "0", manager, registry,
-                                              lifeCycleManager);
-        
-        verify(registry).start();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/core/src/test/java/com/redhat/thermostat/platform/internal/command/PlatformCommandDelegateTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012-2016 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.platform.internal.command;
+
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.INVALID_PLATFORM;
+import static com.redhat.thermostat.platform.internal.locale.LocaleResources.translate;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.Console;
+import com.redhat.thermostat.platform.internal.application.ApplicationInfo;
+import com.redhat.thermostat.platform.internal.application.ApplicationRegistry;
+import com.redhat.thermostat.platform.internal.application.ConfigurationManager;
+import com.redhat.thermostat.platform.internal.application.lifecycle.ApplicationLifeCycleManager;
+
+public class PlatformCommandDelegateTest {
+
+    private CommandContext ctx;
+    private ConfigurationManager manager;
+    private Console console;
+    private ByteArrayOutputStream stream;
+    private PrintStream out;
+    private CountDownLatch latch;
+
+    private ApplicationRegistry registry;
+    private ApplicationLifeCycleManager lifeCycleManager;
+
+    private static Locale locale;
+    
+    @BeforeClass
+    public static void init() {
+        locale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+    }
+    
+    @AfterClass
+    public static void cleanup() {
+        Locale.setDefault(locale);
+    }
+    
+    @Before
+    public void setUp() {
+        ctx = mock(CommandContext.class);
+        manager = mock(ConfigurationManager.class);
+        console = mock(Console.class);        
+        registry = mock(ApplicationRegistry.class);
+        latch = mock(CountDownLatch.class);
+        lifeCycleManager = mock(ApplicationLifeCycleManager.class);
+
+        stream = new ByteArrayOutputStream();
+        out = new PrintStream(stream);
+        
+        when(ctx.getConsole()).thenReturn(console);
+        when(console.getOutput()).thenReturn(out);
+    }
+    
+    @Test
+    public void testListCommands() {
+        
+        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
+        info0.name = "0";
+        info0.provider = "provider0";
+        
+        ApplicationInfo.Application info1 = new ApplicationInfo.Application();
+        info1.name = "1";
+        info1.provider = "provider1";
+        
+        ApplicationInfo infos = new ApplicationInfo();
+        infos.applications = new ArrayList<>();
+        infos.applications.add(info0);
+        infos.applications.add(info1);
+        
+        when(manager.getApplicationConfigs()).thenReturn(infos);
+
+        PlatformCommandDelegate.listApplications(ctx, manager);
+        
+        String content = stream.toString();
+
+        // the number of spaces is dependent on the
+        // header length, so also changes based on the locale
+        assertTrue(content.contains("0       |  provider0"));
+        assertTrue(content.contains("1       |  provider1"));
+    }
+    
+    @Test
+    public void testStartInvalidPlatform() {
+        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
+        info0.name = "0";
+        info0.provider = "provider0";
+        
+        ApplicationInfo infos = new ApplicationInfo();
+        infos.applications = new ArrayList<>();
+        infos.applications.add(info0);
+        
+        when(manager.getApplicationConfigs()).thenReturn(infos);
+        when(ctx.getConsole()).thenReturn(console);
+        when(console.getOutput()).thenReturn(out);
+
+        PlatformCommandDelegate.startPlatform(ctx, "1", manager, registry,
+                                              lifeCycleManager);
+        
+        String content = stream.toString();
+
+        // this is also dependent on the locale
+        assertTrue(content.contains(translate(INVALID_PLATFORM, "1")));
+    }
+    
+    @Test
+    public void testStartPlatform() {
+        ApplicationInfo.Application info0 = new ApplicationInfo.Application();
+        info0.name = "0";
+        info0.provider = "provider0";
+        
+        // this also implicitly tests that name '0' is correctly passed
+        // as an argument to getApplicationConfig inside the startPlatform
+        // method
+        when(manager.getApplicationConfig("0")).thenReturn(info0);
+
+        PlatformCommandDelegate.startPlatform(ctx, "0", manager, registry,
+                                              lifeCycleManager);
+        
+        verify(registry).start();
+    }
+}
--- a/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -343,7 +343,7 @@
           <artifactId>maven-javadoc-plugin</artifactId>
           <version>2.9.1</version>
           <configuration>
-            <excludePackageNames>*.impl*;*.internal.*;*.dev.*;*.experimental;com.redhat.thermostat.agent.locale;com.redhat.thermostat.agent.proxy;com.redhat.thermostat.backend.system;com.redhat.thermostat.client.command.cli;com.redhat.thermostat.client.filter.host.swing;com.redhat.thermostat.client.filter.vm.core;com.redhat.thermostat.client.filter.vm.swing;com.redhat.thermostat.client.locale;com.redhat.thermostat.common.locale;com.redhat.thermostat.main;com.redhat.thermostat.numa;com.redhat.thermostat.plugin.validator.locale;com.redhat.thermostat.storage.mongodb;com.redhat.thermostat.test;com.redhat.thermostat.testutils;com.redhat.thermostat.utils.keyring.activator;com.redhat.thermostat.vm;com.redhat.thermostat.host;com.redhat.thermostat.gc;com.redhat.thermostat.thread;com.redhat.thermostat.validate;com.redhat.thermostat.service.activator;com.redhat.thermostat.web;com.redhat.thermostat.killvm;com.redhat.thermostat.notes;com.redhat.thermostat.shared.perflog</excludePackageNames>
+            <excludePackageNames>*.internal*;*.dev.*;*.experimental;com.redhat.thermostat.agent.proxy;com.redhat.thermostat.main;com.redhat.thermostat.numa;com.redhat.thermostat.storage.mongodb;com.redhat.thermostat.testutils;com.redhat.thermostat.vm;com.redhat.thermostat.host;com.redhat.thermostat.gc;com.redhat.thermostat.thread;com.redhat.thermostat.validate;com.redhat.thermostat.service.activator;com.redhat.thermostat.web;com.redhat.thermostat.killvm;com.redhat.thermostat.notes;com.redhat.thermostat.shared.perflog</excludePackageNames>
           </configuration>
         </plugin>
         <plugin>
--- a/setup/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -64,7 +64,6 @@
               com.redhat.thermostat.setup.command.internal,
               com.redhat.thermostat.setup.command.internal.model,
               com.redhat.thermostat.setup.command.internal.cli,
-              com.redhat.thermostat.setup.command.locale,
             </Private-Package>
             <Bundle-Activator>com.redhat.thermostat.setup.command.internal.Activator</Bundle-Activator>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/CredentialPanel.java	Tue May 03 15:49:54 2016 +0200
@@ -40,7 +40,6 @@
 import com.redhat.thermostat.client.swing.components.Icon;
 import com.redhat.thermostat.client.swing.components.ThermostatPasswordField;
 import com.redhat.thermostat.client.swing.components.ThermostatTextField;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 import javax.swing.BorderFactory;
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/InputCredentialPanel.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/InputCredentialPanel.java	Tue May 03 15:49:54 2016 +0200
@@ -39,7 +39,6 @@
 import com.redhat.thermostat.client.swing.components.ThermostatPasswordField;
 import com.redhat.thermostat.setup.command.internal.model.CredentialGenerator;
 import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 import javax.swing.JButton;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-2016 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.setup.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+
+public enum LocaleResources {
+
+    WINDOW_TITLE,
+    WELCOME_SCREEN_TITLE,
+    MONGO_SETUP_TITLE,
+    USERS_SETUP_TITLE,
+    SETUP_COMPLETE_TITLE,
+    MONGO_CRED_TITLE,
+    CLIENT_CRED_TITLE,
+    AGENT_CRED_TITLE,
+    NEXT,
+    BACK,
+    CANCEL,
+    FINISH,
+    SHOW_MORE,
+    SHOW_LESS,
+    STEP_X_OF_Y,
+    AGENT_HELP_INFO,
+    CLIENT_HELP_INFO,
+    STORAGE_HELP_INFO,
+    PASSWORD_MISMATCH,
+    DETAILS_MISSING,
+    USERNAMES_IDENTICAL,
+    SHOW_PASSWORDS,
+    USE_DEFAULTS,
+    THERMOSTAT_BRIEF,
+    THERMOSTAT_BLURB,
+    STORAGE_FAILED,
+    STORAGE_RUNNING,
+    SERVICE_UNAVAILABLE_MESSAGE,
+    SETUP_FAILED,
+    SETUP_INTERRUPTED,
+    SETUP_CANCELLED,
+    USERNAME,
+    PASSWORD,
+    VERIFY_PASSWORD,
+    QUICK_SETUP,
+    CUSTOM_SETUP,
+    QUICK_SETUP_INFO,
+    CUSTOM_SETUP_INFO,
+    USER_PREFIX,
+    MONGO_USER_PREFIX,
+    CLIENT_USER_PREFIX,
+    AGENT_USER_PREFIX,
+    CLI_SETUP_INTRO,
+    CLI_SETUP_PROCEED_QUESTION,
+    CLI_SETUP_UNKNOWN_RESPONSE,
+    CLI_SETUP_PROCEED_WORD,
+    CLI_SETUP_CANCEL_WORD,
+    CLI_SETUP_YES,
+    CLI_SETUP_NO,
+    CLI_SETUP_PASSWORD_INVALID,
+    CLI_SETUP_PASSWORD_MISMATCH,
+    CLI_SETUP_USERNAME_INVALID,
+    CLI_SETUP_USERNAMES_IDENTICAL,
+    CLI_SETUP_MONGODB_USER_CREDS_INTRO,
+    CLI_SETUP_MONGODB_USERNAME_PROMPT,
+    CLI_SETUP_PASSWORD_PROMPT,
+    CLI_SETUP_USERNAME_REPEAT,
+    CLI_SETUP_PASSWORD_REPEAT_PROMPT,
+    CLI_SETUP_THERMOSTAT_USER_CREDS_INTRO,
+    CLI_SETUP_THERMOSTAT_CLIENT_USERNAME_PROMPT, 
+    CLI_SETUP_THERMOSTAT_AGENT_USERNAME_PROMPT,
+    CLI_SETUP_FINISH_SUCCESS,
+    SETUP_FAILED_DIALOG_TITLE,
+    SETUP_FAILED_DIALOG_MESSAGE,
+    SHOW_MORE_ERROR_INFO,
+    SHOW_LESS_ERROR_INFO,
+    STEPS_TO_RESOLVE_ERROR_LABEL_TEXT,
+    SETUP_COMPLETE_NOTE_CREDENTIALS_TEXT,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.setup.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/MongoUserSetupView.java	Tue May 03 15:49:54 2016 +0200
@@ -37,7 +37,6 @@
 package com.redhat.thermostat.setup.command.internal;
 
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -60,7 +60,6 @@
 import com.redhat.thermostat.service.process.UNIXProcessHandler;
 import com.redhat.thermostat.setup.command.internal.cli.CLISetup;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.utils.keyring.Keyring;
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCompleteView.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupCompleteView.java	Tue May 03 15:49:54 2016 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.setup.command.internal;
 
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 import javax.swing.BorderFactory;
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/SetupWindow.java	Tue May 03 15:49:54 2016 +0200
@@ -84,7 +84,6 @@
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.setup.command.internal.model.CredentialGenerator;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 public class SetupWindow {
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/StartView.java	Tue May 03 15:49:54 2016 +0200
@@ -63,7 +63,6 @@
 import com.redhat.thermostat.client.swing.components.ThermostatScrollPane;
 import com.redhat.thermostat.common.ApplicationInfo;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 public class StartView extends JPanel implements SetupView {
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/UserPropertiesView.java	Tue May 03 15:49:54 2016 +0200
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.setup.command.internal;
 
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 import javax.swing.BorderFactory;
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/CLISetup.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/CLISetup.java	Tue May 03 15:49:54 2016 +0200
@@ -47,8 +47,8 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.Console;
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.setup.command.internal.LocaleResources;
 import com.redhat.thermostat.setup.command.internal.model.ThermostatSetup;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/PasswordCredentialsReader.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/PasswordCredentialsReader.java	Tue May 03 15:49:54 2016 +0200
@@ -43,8 +43,8 @@
 
 import com.redhat.thermostat.common.cli.Console;
 import com.redhat.thermostat.common.tools.StorageAuthInfoGetter;
+import com.redhat.thermostat.setup.command.internal.LocaleResources;
 import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/UsernameCredentialsReader.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/cli/UsernameCredentialsReader.java	Tue May 03 15:49:54 2016 +0200
@@ -41,8 +41,8 @@
 
 import com.redhat.thermostat.common.cli.Console;
 import com.redhat.thermostat.common.tools.StorageAuthInfoGetter;
+import com.redhat.thermostat.setup.command.internal.LocaleResources;
 import com.redhat.thermostat.setup.command.internal.model.UserCredsValidator;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java	Mon May 02 18:43:01 2016 +0200
+++ b/setup/command/src/main/java/com/redhat/thermostat/setup/command/internal/model/ThermostatSetup.java	Tue May 03 15:49:54 2016 +0200
@@ -43,7 +43,7 @@
 import com.redhat.thermostat.common.config.ClientPreferences;
 import com.redhat.thermostat.launcher.Launcher;
 import com.redhat.thermostat.service.process.UNIXProcessHandler;
-import com.redhat.thermostat.setup.command.locale.LocaleResources;
+import com.redhat.thermostat.setup.command.internal.LocaleResources;
 import com.redhat.thermostat.shared.config.CommonPaths;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.utils.keyring.Keyring;
--- a/setup/command/src/main/java/com/redhat/thermostat/setup/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012-2016 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.setup.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-
-public enum LocaleResources {
-
-    WINDOW_TITLE,
-    WELCOME_SCREEN_TITLE,
-    MONGO_SETUP_TITLE,
-    USERS_SETUP_TITLE,
-    SETUP_COMPLETE_TITLE,
-    MONGO_CRED_TITLE,
-    CLIENT_CRED_TITLE,
-    AGENT_CRED_TITLE,
-    NEXT,
-    BACK,
-    CANCEL,
-    FINISH,
-    SHOW_MORE,
-    SHOW_LESS,
-    STEP_X_OF_Y,
-    AGENT_HELP_INFO,
-    CLIENT_HELP_INFO,
-    STORAGE_HELP_INFO,
-    PASSWORD_MISMATCH,
-    DETAILS_MISSING,
-    USERNAMES_IDENTICAL,
-    SHOW_PASSWORDS,
-    USE_DEFAULTS,
-    THERMOSTAT_BRIEF,
-    THERMOSTAT_BLURB,
-    STORAGE_FAILED,
-    STORAGE_RUNNING,
-    SERVICE_UNAVAILABLE_MESSAGE,
-    SETUP_FAILED,
-    SETUP_INTERRUPTED,
-    SETUP_CANCELLED,
-    USERNAME,
-    PASSWORD,
-    VERIFY_PASSWORD,
-    QUICK_SETUP,
-    CUSTOM_SETUP,
-    QUICK_SETUP_INFO,
-    CUSTOM_SETUP_INFO,
-    USER_PREFIX,
-    MONGO_USER_PREFIX,
-    CLIENT_USER_PREFIX,
-    AGENT_USER_PREFIX,
-    CLI_SETUP_INTRO,
-    CLI_SETUP_PROCEED_QUESTION,
-    CLI_SETUP_UNKNOWN_RESPONSE,
-    CLI_SETUP_PROCEED_WORD,
-    CLI_SETUP_CANCEL_WORD,
-    CLI_SETUP_YES,
-    CLI_SETUP_NO,
-    CLI_SETUP_PASSWORD_INVALID,
-    CLI_SETUP_PASSWORD_MISMATCH,
-    CLI_SETUP_USERNAME_INVALID,
-    CLI_SETUP_USERNAMES_IDENTICAL,
-    CLI_SETUP_MONGODB_USER_CREDS_INTRO,
-    CLI_SETUP_MONGODB_USERNAME_PROMPT,
-    CLI_SETUP_PASSWORD_PROMPT,
-    CLI_SETUP_USERNAME_REPEAT,
-    CLI_SETUP_PASSWORD_REPEAT_PROMPT,
-    CLI_SETUP_THERMOSTAT_USER_CREDS_INTRO,
-    CLI_SETUP_THERMOSTAT_CLIENT_USERNAME_PROMPT, 
-    CLI_SETUP_THERMOSTAT_AGENT_USERNAME_PROMPT,
-    CLI_SETUP_FINISH_SUCCESS,
-    SETUP_FAILED_DIALOG_TITLE,
-    SETUP_FAILED_DIALOG_MESSAGE,
-    SHOW_MORE_ERROR_INFO,
-    SHOW_LESS_ERROR_INFO,
-    STEPS_TO_RESOLVE_ERROR_LABEL_TEXT,
-    SETUP_COMPLETE_NOTE_CREDENTIALS_TEXT,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.setup.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup/command/src/test/java/com/redhat/thermostat/setup/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 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.setup.command.internal;
+
+import com.redhat.thermostat.setup.command.internal.LocaleResources;
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- a/setup/command/src/test/java/com/redhat/thermostat/setup/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.setup.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/storage/core/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/storage/core/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -85,7 +85,6 @@
             <Private-Package>
               com.redhat.thermostat.storage.internal,
               com.redhat.thermostat.storage.internal.dao,
-              com.redhat.thermostat.storage.locale,
               com.redhat.thermostat.storage.internal.statement,
               com.redhat.thermostat.storage.monitor.internal,
             </Private-Package>
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/config/FileStorageCredentials.java	Mon May 02 18:43:01 2016 +0200
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/config/FileStorageCredentials.java	Tue May 03 15:49:54 2016 +0200
@@ -44,10 +44,10 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
-import com.redhat.thermostat.storage.locale.LocaleResources;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.StorageCredentials;
+import com.redhat.thermostat.storage.internal.LocaleResources;
 
 public class FileStorageCredentials implements StorageCredentials {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-2016 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.storage.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    FILE_NOT_VALID,
+    BAD_AUTH_CONTENTS,
+    ;
+    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.storage.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012-2016 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.storage.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    FILE_NOT_VALID,
-    BAD_AUTH_CONTENTS,
-    ;
-    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.storage.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 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.storage.internal;
+
+import com.redhat.thermostat.storage.internal.LocaleResources;
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest  extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012-2016 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.storage.locale;
-
-import com.redhat.thermostat.storage.locale.LocaleResources;
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest  extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/system-backend/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/system-backend/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -108,10 +108,10 @@
         <configuration>
           <instructions>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.backend.system.SystemBackendActivator</Bundle-Activator>
+            <Bundle-Activator>com.redhat.thermostat.backend.system.internal.SystemBackendActivator</Bundle-Activator>
             <Bundle-SymbolicName>com.redhat.thermostat.backend.system</Bundle-SymbolicName>
             <Private-Package>
-                com.redhat.thermostat.backend.system,
+                com.redhat.thermostat.backend.system.internal,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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/DistributionInformationSource.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.io.IOException;
-
-public interface DistributionInformationSource {
-
-    public DistributionInformation getDistributionInformation() throws IOException;
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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/HostInfoBuilder.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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.agent.utils.ProcDataSource;
-import com.redhat.thermostat.agent.utils.hostname.HostName;
-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 HostInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class);
-
-    public static final String FALLBACK_LOCAL_HOSTNAME = "localhost";
-
-    static class HostCpuInfo {
-        public final String model;
-        public final int count;
-
-        public HostCpuInfo(String model, int count) {
-            this.count = count;
-            this.model = model;
-        }
-    }
-
-    static class HostOsInfo {
-        public final String kernel;
-        public final String distribution;
-
-        public HostOsInfo(String kernel, String distribution) {
-            this.kernel = kernel;
-            this.distribution = distribution;
-        }
-    }
-
-    static class HostMemoryInfo {
-        public final Size totalMemory;
-
-        public HostMemoryInfo(Size totalMemory) {
-            this.totalMemory = totalMemory;
-        }
-    }
-
-    private final ProcDataSource dataSource;
-    private final WriterID writerId;
-
-    public HostInfoBuilder(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.toString());
-        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/JvmStatDataExtractor.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.MonitoredVmUtil;
-
-/**
- * A helper class to provide type-safe access to commonly used jvmstat monitors
- * <p>
- * Implementation details: For local vms, jvmstat uses a ByteBuffer
- * corresponding to mmap()ed hsperfdata file. The hsperfdata file is updated
- * asynchronously by the vm that created the file. The polling that jvmstat api
- * provides is merely an abstraction over this (possibly always up-to-date)
- * ByteBuffer. So the data this class extracts is as current as possible, and
- * does not correspond to when the jvmstat update events fired.
- */
-public class JvmStatDataExtractor {
-
-    /*
-     * Note, there may be a performance issue to consider here. We have a lot of
-     * string constants. When we start adding some of the more heavyweight
-     * features, and running into CPU issues this may need to be reconsidered in
-     * order to avoid the String pool overhead. See also:
-     * http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern()
-     */
-
-    private final MonitoredVm vm;
-
-    public JvmStatDataExtractor(MonitoredVm vm) {
-        this.vm = vm;
-    }
-
-    public String getCommandLine() throws MonitorException {
-        return MonitoredVmUtil.commandLine(vm);
-    }
-
-    public String getMainClass() throws MonitorException {
-        return MonitoredVmUtil.mainClass(vm, true);
-    }
-
-    public String getJavaVersion() throws MonitorException {
-        return (String) vm.findByName("java.property.java.version").getValue();
-    }
-
-    public String getJavaHome() throws MonitorException {
-        return (String) vm.findByName("java.property.java.home").getValue();
-    }
-
-    public String getVmName() throws MonitorException {
-        return (String) vm.findByName("java.property.java.vm.name").getValue();
-    }
-
-    public String getVmInfo() throws MonitorException {
-        return (String) vm.findByName("java.property.java.vm.info").getValue();
-    }
-
-    public String getVmVersion() throws MonitorException {
-        return (String) vm.findByName("java.property.java.vm.version").getValue();
-    }
-
-    public String getVmArguments() throws MonitorException {
-        return MonitoredVmUtil.jvmArgs(vm);
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.VmIdentifier;
-import sun.jvmstat.monitor.event.HostEvent;
-import sun.jvmstat.monitor.event.HostListener;
-import sun.jvmstat.monitor.event.VmStatusChangeEvent;
-
-import com.redhat.thermostat.agent.VmBlacklist;
-import com.redhat.thermostat.agent.VmStatusListener.Status;
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.backend.system.ProcessUserInfoBuilder.ProcessUserInfo;
-import com.redhat.thermostat.common.Pair;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class JvmStatHostListener implements HostListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class);
-
-    private final VmInfoDAO vmInfoDAO;
-    private final VmStatusChangeNotifier notifier;
-    private final ProcessUserInfoBuilder userInfoBuilder;
-    private final WriterID writerId;
-    private Map<Integer, Pair<String, MonitoredVm>> monitoredVms  = new HashMap<>();
-    private final HostRef hostRef;
-    private final VmBlacklist blacklist;
-
-    JvmStatHostListener(VmInfoDAO vmInfoDAO, VmStatusChangeNotifier notifier, 
-            ProcessUserInfoBuilder userInfoBuilder, WriterID writerId, HostRef hostRef,
-            VmBlacklist blacklist) {
-        this.vmInfoDAO = vmInfoDAO;
-        this.notifier = notifier;
-        this.userInfoBuilder = userInfoBuilder;
-        this.writerId = writerId;
-        this.hostRef = hostRef;
-        this.blacklist = blacklist;
-    }
-
-    @Override
-    public void disconnected(HostEvent event) {
-        logger.warning("Disconnected from host");
-    }
-
-    @SuppressWarnings("unchecked") // Unchecked casts to (Set<Integer>).
-    @Override
-    public void vmStatusChanged(VmStatusChangeEvent event) {
-        MonitoredHost host = event.getMonitoredHost();
-
-        for (Integer newVm : (Set<Integer>) event.getStarted()) {
-            try {
-                logger.fine("New vm: " + newVm);
-                sendNewVM(newVm, host);
-            } catch (MonitorException e) {
-                logger.log(Level.WARNING, "error getting info for new vm " + newVm, e);
-            } catch (URISyntaxException e) {
-                logger.log(Level.WARNING, "error getting info for new vm " + newVm, e);
-            }
-        }
-
-        for (Integer stoppedVm : (Set<Integer>) event.getTerminated()) {
-            try {
-                logger.fine("stopped vm: " + stoppedVm);
-                sendStoppedVM(stoppedVm, host);
-            } catch (URISyntaxException e) {
-                logger.log(Level.WARNING, "error getting info for stopped vm " + stoppedVm, e);
-            } catch (MonitorException e) {
-                logger.log(Level.WARNING, "error getting info for stopped vm " + stoppedVm, e);
-            }
-        }
-    }
-
-    private void sendNewVM(Integer vmPid, MonitoredHost host)
-            throws MonitorException, URISyntaxException {
-        // Propagate any MonitorException, and do not notify Backends or remember
-        // VMs when we fail to extract the necessary information.
-        // http://icedtea.classpath.org/pipermail/thermostat/2013-November/008702.html
-        MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve(
-                new VmIdentifier(vmPid.toString())));
-        if (vm != null) {
-            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-            String vmId = UUID.randomUUID().toString();
-            long startTime = System.currentTimeMillis();
-            long stopTime = Long.MIN_VALUE;
-            VmInfo info = createVmInfo(vmId, vmPid, startTime, stopTime, extractor);
-
-            // Check blacklist
-            VmRef vmRef = new VmRef(hostRef, vmId, vmPid, info.getMainClass());
-            if (!blacklist.isBlacklisted(vmRef)) {
-                vmInfoDAO.putVmInfo(info);
-
-                notifier.notifyVmStatusChange(Status.VM_STARTED, vmId, vmPid);
-                logger.finer("Sent VM_STARTED messsage");
-
-                monitoredVms.put(vmPid, new Pair<>(vmId, vm));
-            }
-            else {
-                logger.info("Skipping VM: " + vmPid);
-            }
-        }
-    }
-
-    VmInfo createVmInfo(String vmId, Integer vmPid, long startTime, long stopTime,
-            JvmStatDataExtractor extractor) throws MonitorException {
-        Map<String, String> properties = new HashMap<String, String>();
-        ProcDataSource dataSource = new ProcDataSource();
-        Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmPid);
-        // TODO actually figure out the loaded libraries.
-        String[] loadedNativeLibraries = new String[0];
-        ProcessUserInfo userInfo = userInfoBuilder.build(vmPid);
-        VmInfo info = new VmInfo(writerId.getWriterID(), vmId, vmPid, startTime, stopTime,
-                extractor.getJavaVersion(), extractor.getJavaHome(),
-                extractor.getMainClass(), extractor.getCommandLine(),
-                extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(),
-                properties, environment, loadedNativeLibraries, userInfo.getUid(), userInfo.getUsername());
-        return info;
-    }
-
-    private void sendStoppedVM(Integer vmPid, MonitoredHost host) throws URISyntaxException, MonitorException {
-        
-        VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(new VmIdentifier(vmPid.toString()));
-        if (resolvedVmID != null && monitoredVms.containsKey(vmPid)) {
-            Pair<String, MonitoredVm> vmData = monitoredVms.remove(vmPid);
-            
-            String vmId = vmData.getFirst();
-            notifier.notifyVmStatusChange(Status.VM_STOPPED, vmId, vmPid);
-
-            long stopTime = System.currentTimeMillis();
-            vmInfoDAO.putVmStoppedTime(vmId, stopTime);
-
-            MonitoredVm vm = vmData.getSecond();
-            vm.detach();
-        }
-    }
-
-    /*
-     * For testing purposes only.
-     */
-    Map<Integer, Pair<String, MonitoredVm>> getMonitoredVms() {
-        return monitoredVms;
-    }
-    
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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;
-
-public 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;
-    
-    public LsbRelease() {
-        this.lsbRelaseBin = LSB_RELEASE_SCRIPT;
-    }
-    
-    // package-private for testing
-    LsbRelease(String lsbReleaseBin) {
-        this.lsbRelaseBin = lsbReleaseBin;
-    }
-
-    @Override
-    public DistributionInformation getDistributionInformation()
-            throws IOException {
-        return getFromLsbRelease();
-    }
-
-    public 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");
-                }
-            }
-        }
-
-    }
-
-    public 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/NetworkInfoBuilder.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class NetworkInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class);
-
-    private final WriterID writerId;
-    
-    public NetworkInfoBuilder(WriterID writerId) {
-        this.writerId = writerId;
-    }
-    
-    public List<NetworkInterfaceInfo> build() {
-        List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>();
-        String wId = writerId.getWriterID();
-        try {
-            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
-            for (NetworkInterface iface : Collections.list(ifaces)) {
-                NetworkInterfaceInfo info = new NetworkInterfaceInfo(wId, iface.getName());
-                for (InetAddress addr : Collections.list(iface.getInetAddresses())) {
-                    if (addr instanceof Inet4Address) {
-                        info.setIp4Addr(addr.getHostAddress());
-                    } else if (addr instanceof Inet6Address) {
-                        info.setIp6Addr(addr.getHostAddress());
-                    }
-                }
-                infos.add(info);
-            }
-        } catch (SocketException e) {
-            logger.log(Level.WARNING, "error enumerating network interfaces");
-        }
-        return infos;
-    }
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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.agent.utils.ProcDataSource;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class ProcessEnvironmentBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(ProcessEnvironmentBuilder.class);
-
-    private final ProcDataSource dataSource;
-
-    public ProcessEnvironmentBuilder(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/ProcessUserInfoBuilder.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.agent.utils.username.UserNameLookupException;
-import com.redhat.thermostat.agent.utils.username.UserNameUtil;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-class ProcessUserInfoBuilder {
-    
-    private static final ProcessUserInfo NON_EXISTENT_USER = new ProcessUserInfo();
-    private static final String PROC_STATUS_UID = "Uid:";
-    private static final Logger logger = LoggingUtils.getLogger(ProcessUserInfoBuilder.class);
-    private ProcDataSource source;
-    private UserNameUtil userNameUtil;
-    
-    ProcessUserInfoBuilder(ProcDataSource source, UserNameUtil userNameUtil) {
-        this.source = source;
-        this.userNameUtil = userNameUtil;
-    }
-    
-    static class ProcessUserInfo {
-        
-        private long uid;
-        private String username;
-        
-        ProcessUserInfo(long uid, String username) {
-            this.uid = uid;
-            this.username = username;
-        }
-        
-        ProcessUserInfo() {
-            this.uid = -1;
-            this.username = null;
-        }
-        
-        public long getUid() {
-            return uid;
-        }
-        
-        public String getUsername() {
-            return username;
-        }
-    }
-    
-    ProcessUserInfo build(int pid) {
-        ProcessUserInfo info = NON_EXISTENT_USER;
-        try {
-            Reader reader = source.getStatusReader(pid);
-            long uid = getUidFromProcfs(new BufferedReader(reader));
-            String name = null;
-            try {
-                name = userNameUtil.getUserName(uid);
-            } catch (UserNameLookupException e) {
-                logger.log(Level.WARNING, "Unable to retrieve username for uid: " + uid, e);
-            }
-            info = new ProcessUserInfo(uid, name);
-        } catch (IOException e) {
-            logger.log(Level.WARNING, "Unable to read user info for " + pid, e);
-        }
-        
-        return info;
-    }
-
-    /*
-     * Look for the following line:
-     * Uid:  <RealUid>   <EffectiveUid>   <SavedUid>   <FSUid>
-     */
-    private long getUidFromProcfs(BufferedReader br) throws IOException {
-        long uid = -1;
-        String line;
-        while ((line = br.readLine()) != null) {
-            line = line.trim();
-            if (line.startsWith(PROC_STATUS_UID)) {
-                String[] parts = line.split("\\s+");
-                if (parts.length == 5) {
-                    try {
-                        // Use Real UID
-                        uid = Long.parseLong(parts[1]);
-                    } catch (NumberFormatException e) {
-                        throw new IOException("Unexpected output from ps command", e);
-                    }
-                }
-                else {
-                    throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length);
-                }
-            }
-        }
-        if (uid < 0) {
-            throw new IOException("Unable to determine UID from /proc/${pid}/status");
-        }
-        return uid;
-    }
-
-
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.net.URISyntaxException;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import sun.jvmstat.monitor.HostIdentifier;
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-
-import com.redhat.thermostat.agent.VmBlacklist;
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.agent.utils.username.UserNameUtil;
-import com.redhat.thermostat.backend.BaseBackend;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.HostInfo;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class SystemBackend extends BaseBackend {
-
-    private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class);
-
-    private HostInfoDAO hostInfos;
-    private NetworkInterfaceInfoDAO networkInterfaces;
-    private VmInfoDAO vmInfoDAO;
-
-    private long procCheckInterval = 1000; // TODO make this configurable.
-
-    private Timer timer = null;
-
-    private HostIdentifier hostId = null;
-    private MonitoredHost host = null;
-    private JvmStatHostListener hostListener = null;
-
-    private final NetworkInfoBuilder networkInfoBuilder;
-    private final HostInfoBuilder hostInfoBuilder;
-    private final ProcessUserInfoBuilder userInfoBuilder;
-    private final VmStatusChangeNotifier notifier;
-    private final WriterID writerId;
-    private final VmBlacklist blacklist;
-
-    public SystemBackend(HostInfoDAO hostInfoDAO, NetworkInterfaceInfoDAO netInfoDAO, VmInfoDAO vmInfoDAO,
-            Version version, VmStatusChangeNotifier notifier, UserNameUtil userNameUtil, WriterID writerId,
-            VmBlacklist blacklist) {
-        super("System Backend",
-                "Gathers basic information from the system",
-                "Red Hat, Inc.",
-                version.getVersionNumber(), true);
-        this.hostInfos = hostInfoDAO;
-        this.networkInterfaces = netInfoDAO;
-        this.vmInfoDAO = vmInfoDAO;
-        this.notifier = notifier;
-        this.writerId = writerId;
-        this.blacklist = blacklist;
-
-        ProcDataSource source = new ProcDataSource();
-        hostInfoBuilder = new HostInfoBuilder(source, writerId);
-        networkInfoBuilder = new NetworkInfoBuilder(writerId);
-        userInfoBuilder = new ProcessUserInfoBuilder(source, userNameUtil);
-    }
-
-    @Override
-    public synchronized boolean activate() {
-        if (timer != null) {
-            return true;
-        }
-
-        if (!getObserveNewJvm()) {
-            logger.fine("not monitoring new vms");
-        }
-        HostInfo hostInfo = hostInfoBuilder.build();
-        hostInfos.putHostInfo(hostInfo);
-
-        timer = new Timer();
-        timer.scheduleAtFixedRate(new TimerTask() {
-            @Override
-            public void run() {
-                for (NetworkInterfaceInfo info: networkInfoBuilder.build()) {
-                    networkInterfaces.putNetworkInterfaceInfo(info);
-                }
-            }
-        }, 0, procCheckInterval);
-
-        try {
-            hostId = new HostIdentifier((String) null);
-            HostRef hostRef = new HostRef(hostInfo.getAgentId(), hostInfo.getHostname());
-            hostListener = new JvmStatHostListener(vmInfoDAO, notifier, 
-                    userInfoBuilder, writerId, hostRef, blacklist);
-            host = MonitoredHost.getMonitoredHost(hostId);
-            host.addHostListener(hostListener);
-        } catch (MonitorException me) {
-            logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", me);
-        } catch (URISyntaxException use) {
-            logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", use);
-        }
-
-        return true;
-    }
-
-    @Override
-    public synchronized boolean deactivate() {
-        if (timer == null) {
-            return true;
-        }
-
-        timer.cancel();
-        timer = null;
-
-        try {
-            host.removeHostListener(hostListener);
-        } catch (MonitorException me) {
-            logger.log(Level.INFO, "something went wrong in jvmstat's listening to this host");
-        }
-        host = null;
-        hostId = null;
-
-        return true;
-    }
-
-    @Override
-    public synchronized boolean isActive() {
-        return (timer != null);
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_DEFAULT_GROUP;
-    }
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackendActivator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.util.Map;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.agent.VmBlacklist;
-import com.redhat.thermostat.agent.utils.username.UserNameUtil;
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.backend.BackendService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-@SuppressWarnings("rawtypes")
-public class SystemBackendActivator implements BundleActivator {
-
-    private MultipleServiceTracker tracker;
-    private SystemBackend backend;
-    private ServiceRegistration reg;
-    private VmStatusChangeNotifier notifier;
-    
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        
-        notifier = new VmStatusChangeNotifier(context);
-        notifier.start();
-        
-        Class<?>[] deps = new Class<?>[] {
-                BackendService.class,
-                HostInfoDAO.class,
-                NetworkInterfaceInfoDAO.class,
-                VmInfoDAO.class,
-                UserNameUtil.class,
-                WriterID.class, // system backend uses it
-                VmBlacklist.class,
-        };
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
-                NetworkInterfaceInfoDAO netInfoDAO = (NetworkInterfaceInfoDAO) services
-                        .get(NetworkInterfaceInfoDAO.class.getName());
-                VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
-                UserNameUtil userNameUtil = (UserNameUtil) services.get(UserNameUtil.class.getName());
-                Version version = new Version(context.getBundle());
-                WriterID id = (WriterID) services.get(WriterID.class.getName());
-                VmBlacklist blacklist = (VmBlacklist) services.get(VmBlacklist.class.getName());
-                backend = new SystemBackend(hostInfoDAO, netInfoDAO, vmInfoDAO, version, notifier, 
-                        userNameUtil, id, blacklist);
-                reg = context.registerService(Backend.class, backend, null);
-            }
-            
-            @Override
-            public void dependenciesUnavailable() {
-                if (backend.isActive()) {
-                    backend.deactivate();
-                }
-                reg.unregister();
-            }
-            
-        });
-                
-        tracker.open();
-    }
-    
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        if (backend != null && backend.isActive()) {
-            backend.deactivate();
-        }
-        tracker.close();
-        notifier.stop();
-    }
-}
-
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/VmStatusChangeNotifier.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-import com.redhat.thermostat.agent.VmStatusListener;
-import com.redhat.thermostat.agent.VmStatusListener.Status;
-
-/**
- * Notifies any and all {@link VmStatusListener} registered as OSGi Services
- * about VM status changes: {@link VmStatusListener.Status#VM_STARTED} and
- * {@link VmStatusListener.Status#VM_STOPPED}.
- * <p>
- * Any listeners registered after a {@link VmStatusListener.Status#VM_STARTED}
- * was delivered receive a {@link VmStatusListener.Status#VM_ACTIVE} event
- * instead as an indication that a VM was started at some unknown point
- * previously.
- */
-public class VmStatusChangeNotifier {
-
-    private final Object listenerLock = new Object();
-    private final Map<Integer, String> activePids;
-    private final Map<VmStatusListener, Set<Integer>> listeners = new ConcurrentHashMap<>();
-
-    private final ServiceTracker tracker;
-
-    public VmStatusChangeNotifier(BundleContext bundleContext) {
-        this.activePids = new HashMap<>();
-
-        tracker = new ServiceTracker(bundleContext, VmStatusListener.class, null) {
-            @Override
-            public VmStatusListener addingService(ServiceReference reference) {
-                VmStatusListener listener = (VmStatusListener) super.addingService(reference);
-
-                synchronized (listenerLock) {
-                    Set<Integer> notifiedAbout = new TreeSet<>();
-                    for (Entry<Integer, String> entry : activePids.entrySet()) {
-                        Integer pid = entry.getKey();
-                        listener.vmStatusChanged(Status.VM_ACTIVE, entry.getValue(), pid);
-                        notifiedAbout.add(pid);
-                    }
-
-                    listeners.put(listener, notifiedAbout);
-                }
-
-                return listener;
-            }
-
-            @Override
-            public void removedService(ServiceReference reference,
-                    Object service) {
-                VmStatusListener listener = (VmStatusListener) service;
-                listeners.remove(listener);
-                super.removedService(reference, service);
-            }
-        };
-    }
-
-    public void start() {
-        tracker.open();
-    }
-
-    public void stop() {
-        tracker.close();
-    }
-
-    /**
-     * Notify all registered listeners about a Vm status change.
-     *
-     * @param newStatus either {@link VmStatusListener.Status#VM_STARTED} or
-     * {@link VmStatusListener.Status#VM_STOPPED}
-     * @param vmId unique identifier for the VM
-     * @param pid process ID for the VM
-     */
-    public void notifyVmStatusChange(VmStatusListener.Status newStatus, String vmId, int pid) {
-        if (newStatus == Status.VM_ACTIVE) {
-            throw new IllegalArgumentException("Dont pass in " + Status.VM_ACTIVE + ", that will be handled automatically");
-        }
-
-        synchronized (listenerLock) {
-            for (Entry<VmStatusListener, Set<Integer>> entry : listeners.entrySet()) {
-                entry.getKey().vmStatusChanged(newStatus, vmId, pid);
-                entry.getValue().add(pid);
-            }
-
-            if (newStatus == Status.VM_STARTED) {
-                activePids.put(pid, vmId);
-            } else {
-                activePids.remove(pid);
-            }
-        }
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/DistributionInformation.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012-2016 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 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;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/DistributionInformationSource.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-2016 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 java.io.IOException;
+
+public interface DistributionInformationSource {
+
+    public DistributionInformation getDistributionInformation() throws IOException;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/EtcOsRelease.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-2016 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 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;
+    }
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilder.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2012-2016 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 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.agent.utils.ProcDataSource;
+import com.redhat.thermostat.agent.utils.hostname.HostName;
+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 HostInfoBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class);
+
+    public static final String FALLBACK_LOCAL_HOSTNAME = "localhost";
+
+    static class HostCpuInfo {
+        public final String model;
+        public final int count;
+
+        public HostCpuInfo(String model, int count) {
+            this.count = count;
+            this.model = model;
+        }
+    }
+
+    static class HostOsInfo {
+        public final String kernel;
+        public final String distribution;
+
+        public HostOsInfo(String kernel, String distribution) {
+            this.kernel = kernel;
+            this.distribution = distribution;
+        }
+    }
+
+    static class HostMemoryInfo {
+        public final Size totalMemory;
+
+        public HostMemoryInfo(Size totalMemory) {
+            this.totalMemory = totalMemory;
+        }
+    }
+
+    private final ProcDataSource dataSource;
+    private final WriterID writerId;
+
+    public HostInfoBuilder(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.toString());
+        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;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatDataExtractor.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012-2016 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 sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.MonitoredVmUtil;
+
+/**
+ * A helper class to provide type-safe access to commonly used jvmstat monitors
+ * <p>
+ * Implementation details: For local vms, jvmstat uses a ByteBuffer
+ * corresponding to mmap()ed hsperfdata file. The hsperfdata file is updated
+ * asynchronously by the vm that created the file. The polling that jvmstat api
+ * provides is merely an abstraction over this (possibly always up-to-date)
+ * ByteBuffer. So the data this class extracts is as current as possible, and
+ * does not correspond to when the jvmstat update events fired.
+ */
+public class JvmStatDataExtractor {
+
+    /*
+     * Note, there may be a performance issue to consider here. We have a lot of
+     * string constants. When we start adding some of the more heavyweight
+     * features, and running into CPU issues this may need to be reconsidered in
+     * order to avoid the String pool overhead. See also:
+     * http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern()
+     */
+
+    private final MonitoredVm vm;
+
+    public JvmStatDataExtractor(MonitoredVm vm) {
+        this.vm = vm;
+    }
+
+    public String getCommandLine() throws MonitorException {
+        return MonitoredVmUtil.commandLine(vm);
+    }
+
+    public String getMainClass() throws MonitorException {
+        return MonitoredVmUtil.mainClass(vm, true);
+    }
+
+    public String getJavaVersion() throws MonitorException {
+        return (String) vm.findByName("java.property.java.version").getValue();
+    }
+
+    public String getJavaHome() throws MonitorException {
+        return (String) vm.findByName("java.property.java.home").getValue();
+    }
+
+    public String getVmName() throws MonitorException {
+        return (String) vm.findByName("java.property.java.vm.name").getValue();
+    }
+
+    public String getVmInfo() throws MonitorException {
+        return (String) vm.findByName("java.property.java.vm.info").getValue();
+    }
+
+    public String getVmVersion() throws MonitorException {
+        return (String) vm.findByName("java.property.java.vm.version").getValue();
+    }
+
+    public String getVmArguments() throws MonitorException {
+        return MonitoredVmUtil.jvmArgs(vm);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListener.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2012-2016 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 java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.VmIdentifier;
+import sun.jvmstat.monitor.event.HostEvent;
+import sun.jvmstat.monitor.event.HostListener;
+import sun.jvmstat.monitor.event.VmStatusChangeEvent;
+
+import com.redhat.thermostat.agent.VmBlacklist;
+import com.redhat.thermostat.agent.VmStatusListener.Status;
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.backend.system.internal.ProcessUserInfoBuilder.ProcessUserInfo;
+import com.redhat.thermostat.common.Pair;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+public class JvmStatHostListener implements HostListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class);
+
+    private final VmInfoDAO vmInfoDAO;
+    private final VmStatusChangeNotifier notifier;
+    private final ProcessUserInfoBuilder userInfoBuilder;
+    private final WriterID writerId;
+    private Map<Integer, Pair<String, MonitoredVm>> monitoredVms  = new HashMap<>();
+    private final HostRef hostRef;
+    private final VmBlacklist blacklist;
+
+    JvmStatHostListener(VmInfoDAO vmInfoDAO, VmStatusChangeNotifier notifier, 
+            ProcessUserInfoBuilder userInfoBuilder, WriterID writerId, HostRef hostRef,
+            VmBlacklist blacklist) {
+        this.vmInfoDAO = vmInfoDAO;
+        this.notifier = notifier;
+        this.userInfoBuilder = userInfoBuilder;
+        this.writerId = writerId;
+        this.hostRef = hostRef;
+        this.blacklist = blacklist;
+    }
+
+    @Override
+    public void disconnected(HostEvent event) {
+        logger.warning("Disconnected from host");
+    }
+
+    @SuppressWarnings("unchecked") // Unchecked casts to (Set<Integer>).
+    @Override
+    public void vmStatusChanged(VmStatusChangeEvent event) {
+        MonitoredHost host = event.getMonitoredHost();
+
+        for (Integer newVm : (Set<Integer>) event.getStarted()) {
+            try {
+                logger.fine("New vm: " + newVm);
+                sendNewVM(newVm, host);
+            } catch (MonitorException e) {
+                logger.log(Level.WARNING, "error getting info for new vm " + newVm, e);
+            } catch (URISyntaxException e) {
+                logger.log(Level.WARNING, "error getting info for new vm " + newVm, e);
+            }
+        }
+
+        for (Integer stoppedVm : (Set<Integer>) event.getTerminated()) {
+            try {
+                logger.fine("stopped vm: " + stoppedVm);
+                sendStoppedVM(stoppedVm, host);
+            } catch (URISyntaxException e) {
+                logger.log(Level.WARNING, "error getting info for stopped vm " + stoppedVm, e);
+            } catch (MonitorException e) {
+                logger.log(Level.WARNING, "error getting info for stopped vm " + stoppedVm, e);
+            }
+        }
+    }
+
+    private void sendNewVM(Integer vmPid, MonitoredHost host)
+            throws MonitorException, URISyntaxException {
+        // Propagate any MonitorException, and do not notify Backends or remember
+        // VMs when we fail to extract the necessary information.
+        // http://icedtea.classpath.org/pipermail/thermostat/2013-November/008702.html
+        MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve(
+                new VmIdentifier(vmPid.toString())));
+        if (vm != null) {
+            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+            String vmId = UUID.randomUUID().toString();
+            long startTime = System.currentTimeMillis();
+            long stopTime = Long.MIN_VALUE;
+            VmInfo info = createVmInfo(vmId, vmPid, startTime, stopTime, extractor);
+
+            // Check blacklist
+            VmRef vmRef = new VmRef(hostRef, vmId, vmPid, info.getMainClass());
+            if (!blacklist.isBlacklisted(vmRef)) {
+                vmInfoDAO.putVmInfo(info);
+
+                notifier.notifyVmStatusChange(Status.VM_STARTED, vmId, vmPid);
+                logger.finer("Sent VM_STARTED messsage");
+
+                monitoredVms.put(vmPid, new Pair<>(vmId, vm));
+            }
+            else {
+                logger.info("Skipping VM: " + vmPid);
+            }
+        }
+    }
+
+    VmInfo createVmInfo(String vmId, Integer vmPid, long startTime, long stopTime,
+            JvmStatDataExtractor extractor) throws MonitorException {
+        Map<String, String> properties = new HashMap<String, String>();
+        ProcDataSource dataSource = new ProcDataSource();
+        Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmPid);
+        // TODO actually figure out the loaded libraries.
+        String[] loadedNativeLibraries = new String[0];
+        ProcessUserInfo userInfo = userInfoBuilder.build(vmPid);
+        VmInfo info = new VmInfo(writerId.getWriterID(), vmId, vmPid, startTime, stopTime,
+                extractor.getJavaVersion(), extractor.getJavaHome(),
+                extractor.getMainClass(), extractor.getCommandLine(),
+                extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(),
+                properties, environment, loadedNativeLibraries, userInfo.getUid(), userInfo.getUsername());
+        return info;
+    }
+
+    private void sendStoppedVM(Integer vmPid, MonitoredHost host) throws URISyntaxException, MonitorException {
+        
+        VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(new VmIdentifier(vmPid.toString()));
+        if (resolvedVmID != null && monitoredVms.containsKey(vmPid)) {
+            Pair<String, MonitoredVm> vmData = monitoredVms.remove(vmPid);
+            
+            String vmId = vmData.getFirst();
+            notifier.notifyVmStatusChange(Status.VM_STOPPED, vmId, vmPid);
+
+            long stopTime = System.currentTimeMillis();
+            vmInfoDAO.putVmStoppedTime(vmId, stopTime);
+
+            MonitoredVm vm = vmData.getSecond();
+            vm.detach();
+        }
+    }
+
+    /*
+     * For testing purposes only.
+     */
+    Map<Integer, Pair<String, MonitoredVm>> getMonitoredVms() {
+        return monitoredVms;
+    }
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/LsbRelease.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012-2016 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 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;
+
+public 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;
+    
+    public LsbRelease() {
+        this.lsbRelaseBin = LSB_RELEASE_SCRIPT;
+    }
+    
+    // package-private for testing
+    LsbRelease(String lsbReleaseBin) {
+        this.lsbRelaseBin = lsbReleaseBin;
+    }
+
+    @Override
+    public DistributionInformation getDistributionInformation()
+            throws IOException {
+        return getFromLsbRelease();
+    }
+
+    public 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");
+                }
+            }
+        }
+
+    }
+
+    public 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/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/NetworkInfoBuilder.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012-2016 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 java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class NetworkInfoBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class);
+
+    private final WriterID writerId;
+    
+    public NetworkInfoBuilder(WriterID writerId) {
+        this.writerId = writerId;
+    }
+    
+    public List<NetworkInterfaceInfo> build() {
+        List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>();
+        String wId = writerId.getWriterID();
+        try {
+            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+            for (NetworkInterface iface : Collections.list(ifaces)) {
+                NetworkInterfaceInfo info = new NetworkInterfaceInfo(wId, iface.getName());
+                for (InetAddress addr : Collections.list(iface.getInetAddresses())) {
+                    if (addr instanceof Inet4Address) {
+                        info.setIp4Addr(addr.getHostAddress());
+                    } else if (addr instanceof Inet6Address) {
+                        info.setIp6Addr(addr.getHostAddress());
+                    }
+                }
+                infos.add(info);
+            }
+        } catch (SocketException e) {
+            logger.log(Level.WARNING, "error enumerating network interfaces");
+        }
+        return infos;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilder.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2012-2016 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 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.agent.utils.ProcDataSource;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class ProcessEnvironmentBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(ProcessEnvironmentBuilder.class);
+
+    private final ProcDataSource dataSource;
+
+    public ProcessEnvironmentBuilder(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;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/ProcessUserInfoBuilder.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2012-2016 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.agent.utils.username.UserNameLookupException;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+class ProcessUserInfoBuilder {
+    
+    private static final ProcessUserInfo NON_EXISTENT_USER = new ProcessUserInfo();
+    private static final String PROC_STATUS_UID = "Uid:";
+    private static final Logger logger = LoggingUtils.getLogger(ProcessUserInfoBuilder.class);
+    private ProcDataSource source;
+    private UserNameUtil userNameUtil;
+    
+    ProcessUserInfoBuilder(ProcDataSource source, UserNameUtil userNameUtil) {
+        this.source = source;
+        this.userNameUtil = userNameUtil;
+    }
+    
+    static class ProcessUserInfo {
+        
+        private long uid;
+        private String username;
+        
+        ProcessUserInfo(long uid, String username) {
+            this.uid = uid;
+            this.username = username;
+        }
+        
+        ProcessUserInfo() {
+            this.uid = -1;
+            this.username = null;
+        }
+        
+        public long getUid() {
+            return uid;
+        }
+        
+        public String getUsername() {
+            return username;
+        }
+    }
+    
+    ProcessUserInfo build(int pid) {
+        ProcessUserInfo info = NON_EXISTENT_USER;
+        try {
+            Reader reader = source.getStatusReader(pid);
+            long uid = getUidFromProcfs(new BufferedReader(reader));
+            String name = null;
+            try {
+                name = userNameUtil.getUserName(uid);
+            } catch (UserNameLookupException e) {
+                logger.log(Level.WARNING, "Unable to retrieve username for uid: " + uid, e);
+            }
+            info = new ProcessUserInfo(uid, name);
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "Unable to read user info for " + pid, e);
+        }
+        
+        return info;
+    }
+
+    /*
+     * Look for the following line:
+     * Uid:  <RealUid>   <EffectiveUid>   <SavedUid>   <FSUid>
+     */
+    private long getUidFromProcfs(BufferedReader br) throws IOException {
+        long uid = -1;
+        String line;
+        while ((line = br.readLine()) != null) {
+            line = line.trim();
+            if (line.startsWith(PROC_STATUS_UID)) {
+                String[] parts = line.split("\\s+");
+                if (parts.length == 5) {
+                    try {
+                        // Use Real UID
+                        uid = Long.parseLong(parts[1]);
+                    } catch (NumberFormatException e) {
+                        throw new IOException("Unexpected output from ps command", e);
+                    }
+                }
+                else {
+                    throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length);
+                }
+            }
+        }
+        if (uid < 0) {
+            throw new IOException("Unable to determine UID from /proc/${pid}/status");
+        }
+        return uid;
+    }
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/SystemBackend.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012-2016 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 java.net.URISyntaxException;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import sun.jvmstat.monitor.HostIdentifier;
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+
+import com.redhat.thermostat.agent.VmBlacklist;
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.backend.BaseBackend;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.HostInfo;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class SystemBackend extends BaseBackend {
+
+    private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class);
+
+    private HostInfoDAO hostInfos;
+    private NetworkInterfaceInfoDAO networkInterfaces;
+    private VmInfoDAO vmInfoDAO;
+
+    private long procCheckInterval = 1000; // TODO make this configurable.
+
+    private Timer timer = null;
+
+    private HostIdentifier hostId = null;
+    private MonitoredHost host = null;
+    private JvmStatHostListener hostListener = null;
+
+    private final NetworkInfoBuilder networkInfoBuilder;
+    private final HostInfoBuilder hostInfoBuilder;
+    private final ProcessUserInfoBuilder userInfoBuilder;
+    private final VmStatusChangeNotifier notifier;
+    private final WriterID writerId;
+    private final VmBlacklist blacklist;
+
+    public SystemBackend(HostInfoDAO hostInfoDAO, NetworkInterfaceInfoDAO netInfoDAO, VmInfoDAO vmInfoDAO,
+            Version version, VmStatusChangeNotifier notifier, UserNameUtil userNameUtil, WriterID writerId,
+            VmBlacklist blacklist) {
+        super("System Backend",
+                "Gathers basic information from the system",
+                "Red Hat, Inc.",
+                version.getVersionNumber(), true);
+        this.hostInfos = hostInfoDAO;
+        this.networkInterfaces = netInfoDAO;
+        this.vmInfoDAO = vmInfoDAO;
+        this.notifier = notifier;
+        this.writerId = writerId;
+        this.blacklist = blacklist;
+
+        ProcDataSource source = new ProcDataSource();
+        hostInfoBuilder = new HostInfoBuilder(source, writerId);
+        networkInfoBuilder = new NetworkInfoBuilder(writerId);
+        userInfoBuilder = new ProcessUserInfoBuilder(source, userNameUtil);
+    }
+
+    @Override
+    public synchronized boolean activate() {
+        if (timer != null) {
+            return true;
+        }
+
+        if (!getObserveNewJvm()) {
+            logger.fine("not monitoring new vms");
+        }
+        HostInfo hostInfo = hostInfoBuilder.build();
+        hostInfos.putHostInfo(hostInfo);
+
+        timer = new Timer();
+        timer.scheduleAtFixedRate(new TimerTask() {
+            @Override
+            public void run() {
+                for (NetworkInterfaceInfo info: networkInfoBuilder.build()) {
+                    networkInterfaces.putNetworkInterfaceInfo(info);
+                }
+            }
+        }, 0, procCheckInterval);
+
+        try {
+            hostId = new HostIdentifier((String) null);
+            HostRef hostRef = new HostRef(hostInfo.getAgentId(), hostInfo.getHostname());
+            hostListener = new JvmStatHostListener(vmInfoDAO, notifier, 
+                    userInfoBuilder, writerId, hostRef, blacklist);
+            host = MonitoredHost.getMonitoredHost(hostId);
+            host.addHostListener(hostListener);
+        } catch (MonitorException me) {
+            logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", me);
+        } catch (URISyntaxException use) {
+            logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", use);
+        }
+
+        return true;
+    }
+
+    @Override
+    public synchronized boolean deactivate() {
+        if (timer == null) {
+            return true;
+        }
+
+        timer.cancel();
+        timer = null;
+
+        try {
+            host.removeHostListener(hostListener);
+        } catch (MonitorException me) {
+            logger.log(Level.INFO, "something went wrong in jvmstat's listening to this host");
+        }
+        host = null;
+        hostId = null;
+
+        return true;
+    }
+
+    @Override
+    public synchronized boolean isActive() {
+        return (timer != null);
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_DEFAULT_GROUP;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/SystemBackendActivator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012-2016 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 java.util.Map;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.agent.VmBlacklist;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+@SuppressWarnings("rawtypes")
+public class SystemBackendActivator implements BundleActivator {
+
+    private MultipleServiceTracker tracker;
+    private SystemBackend backend;
+    private ServiceRegistration reg;
+    private VmStatusChangeNotifier notifier;
+    
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        
+        notifier = new VmStatusChangeNotifier(context);
+        notifier.start();
+        
+        Class<?>[] deps = new Class<?>[] {
+                BackendService.class,
+                HostInfoDAO.class,
+                NetworkInterfaceInfoDAO.class,
+                VmInfoDAO.class,
+                UserNameUtil.class,
+                WriterID.class, // system backend uses it
+                VmBlacklist.class,
+        };
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+                NetworkInterfaceInfoDAO netInfoDAO = (NetworkInterfaceInfoDAO) services
+                        .get(NetworkInterfaceInfoDAO.class.getName());
+                VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                UserNameUtil userNameUtil = (UserNameUtil) services.get(UserNameUtil.class.getName());
+                Version version = new Version(context.getBundle());
+                WriterID id = (WriterID) services.get(WriterID.class.getName());
+                VmBlacklist blacklist = (VmBlacklist) services.get(VmBlacklist.class.getName());
+                backend = new SystemBackend(hostInfoDAO, netInfoDAO, vmInfoDAO, version, notifier, 
+                        userNameUtil, id, blacklist);
+                reg = context.registerService(Backend.class, backend, null);
+            }
+            
+            @Override
+            public void dependenciesUnavailable() {
+                if (backend.isActive()) {
+                    backend.deactivate();
+                }
+                reg.unregister();
+            }
+            
+        });
+                
+        tracker.open();
+    }
+    
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if (backend != null && backend.isActive()) {
+            backend.deactivate();
+        }
+        tracker.close();
+        notifier.stop();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/internal/VmStatusChangeNotifier.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012-2016 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 java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.redhat.thermostat.agent.VmStatusListener;
+import com.redhat.thermostat.agent.VmStatusListener.Status;
+
+/**
+ * Notifies any and all {@link VmStatusListener} registered as OSGi Services
+ * about VM status changes: {@link VmStatusListener.Status#VM_STARTED} and
+ * {@link VmStatusListener.Status#VM_STOPPED}.
+ * <p>
+ * Any listeners registered after a {@link VmStatusListener.Status#VM_STARTED}
+ * was delivered receive a {@link VmStatusListener.Status#VM_ACTIVE} event
+ * instead as an indication that a VM was started at some unknown point
+ * previously.
+ */
+public class VmStatusChangeNotifier {
+
+    private final Object listenerLock = new Object();
+    private final Map<Integer, String> activePids;
+    private final Map<VmStatusListener, Set<Integer>> listeners = new ConcurrentHashMap<>();
+
+    private final ServiceTracker tracker;
+
+    public VmStatusChangeNotifier(BundleContext bundleContext) {
+        this.activePids = new HashMap<>();
+
+        tracker = new ServiceTracker(bundleContext, VmStatusListener.class, null) {
+            @Override
+            public VmStatusListener addingService(ServiceReference reference) {
+                VmStatusListener listener = (VmStatusListener) super.addingService(reference);
+
+                synchronized (listenerLock) {
+                    Set<Integer> notifiedAbout = new TreeSet<>();
+                    for (Entry<Integer, String> entry : activePids.entrySet()) {
+                        Integer pid = entry.getKey();
+                        listener.vmStatusChanged(Status.VM_ACTIVE, entry.getValue(), pid);
+                        notifiedAbout.add(pid);
+                    }
+
+                    listeners.put(listener, notifiedAbout);
+                }
+
+                return listener;
+            }
+
+            @Override
+            public void removedService(ServiceReference reference,
+                    Object service) {
+                VmStatusListener listener = (VmStatusListener) service;
+                listeners.remove(listener);
+                super.removedService(reference, service);
+            }
+        };
+    }
+
+    public void start() {
+        tracker.open();
+    }
+
+    public void stop() {
+        tracker.close();
+    }
+
+    /**
+     * Notify all registered listeners about a Vm status change.
+     *
+     * @param newStatus either {@link VmStatusListener.Status#VM_STARTED} or
+     * {@link VmStatusListener.Status#VM_STOPPED}
+     * @param vmId unique identifier for the VM
+     * @param pid process ID for the VM
+     */
+    public void notifyVmStatusChange(VmStatusListener.Status newStatus, String vmId, int pid) {
+        if (newStatus == Status.VM_ACTIVE) {
+            throw new IllegalArgumentException("Dont pass in " + Status.VM_ACTIVE + ", that will be handled automatically");
+        }
+
+        synchronized (listenerLock) {
+            for (Entry<VmStatusListener, Set<Integer>> entry : listeners.entrySet()) {
+                entry.getKey().vmStatusChanged(newStatus, vmId, pid);
+                entry.getValue().add(pid);
+            }
+
+            if (newStatus == Status.VM_STARTED) {
+                activePids.put(pid, vmId);
+            } else {
+                activePids.remove(pid);
+            }
+        }
+    }
+
+}
+
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import static org.junit.Assert.*;
-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 org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.testutils.TestUtils;
-
-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 (TestUtils.isLinux()) {
-            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 (TestUtils.isLinux()) {
-            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/EtcOsReleaseTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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 org.junit.Test;
-
-import com.redhat.thermostat.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() {
-        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/HostInfoBuilderTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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 org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.backend.system.HostInfoBuilder.HostCpuInfo;
-import com.redhat.thermostat.backend.system.HostInfoBuilder.HostMemoryInfo;
-import com.redhat.thermostat.backend.system.HostInfoBuilder.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() {
-        HostInfo info = new HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(dataSource, writerId).getHostName(address);
-        assertEquals("test-hostname", name);
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import static org.junit.Assert.assertEquals;
-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 org.junit.Test;
-
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.StringMonitor;
-
-public class JvmStatDataExtractorTest {
-
-    private MonitoredVm buildStringMonitoredVm(String monitorName, String monitorReturn) throws MonitorException {
-        final StringMonitor monitor = mock(StringMonitor.class);
-        when(monitor.stringValue()).thenReturn(monitorReturn);
-        when(monitor.getValue()).thenReturn(monitorReturn);
-        MonitoredVm vm = mock(MonitoredVm.class);
-        when(vm.findByName(monitorName)).thenReturn(monitor);
-        return vm;
-    }
-
-    @Test
-    public void testCommandLine() throws MonitorException {
-        final String MONITOR_NAME = "sun.rt.javaCommand";
-        final String MONITOR_VALUE = "command line java";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getCommandLine();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testMainClass() throws MonitorException {
-        final String MONITOR_NAME = "sun.rt.javaCommand";
-        final String MONITOR_VALUE = "some.package.Main";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getMainClass();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testJavaVersion() throws MonitorException {
-        final String MONITOR_NAME = "java.property.java.version";
-        final String MONITOR_VALUE = "some java version";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getJavaVersion();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testJavaHome() throws MonitorException {
-        final String MONITOR_NAME = "java.property.java.home";
-        final String MONITOR_VALUE = "${java.home}";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getJavaHome();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testVmName() throws MonitorException {
-        final String MONITOR_NAME = "java.property.java.vm.name";
-        final String MONITOR_VALUE = "${vm.name}";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getVmName();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testVmInfo() throws MonitorException {
-        final String MONITOR_NAME = "java.property.java.vm.info";
-        final String MONITOR_VALUE = "${vm.info}";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getVmInfo();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testVmVersion() throws MonitorException {
-        final String MONITOR_NAME = "java.property.java.vm.version";
-        final String MONITOR_VALUE = "${vm.version}";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getVmVersion();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testVmArguments() throws MonitorException {
-        final String MONITOR_NAME = "java.rt.vmArgs";
-        final String MONITOR_VALUE = "${vm.arguments}";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getVmArguments();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.net.URISyntaxException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import sun.jvmstat.monitor.HostIdentifier;
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.StringMonitor;
-import sun.jvmstat.monitor.VmIdentifier;
-import sun.jvmstat.monitor.event.VmStatusChangeEvent;
-
-import com.redhat.thermostat.agent.VmBlacklist;
-import com.redhat.thermostat.agent.VmStatusListener.Status;
-import com.redhat.thermostat.backend.system.ProcessUserInfoBuilder.ProcessUserInfo;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-public class JvmStatHostListenerTest {
-    
-    private static String INFO_CMDLINE = "/path/to/executable command line args";
-    private static String INFO_JAVAHOME = "/path/to/java";
-    private static String INFO_JAVAVER = "1.9001";
-    private static String INFO_MAINCLASS = "MyMainClass";
-    private static String INFO_VMARGS = "-Xarg1 -Xarg2";
-    private static String INFO_VMINFO = "Info";
-    private static String INFO_VMNAME = "MyJVM";
-    private static String INFO_VMVER = "90.01";
-    private static long INFO_VMUSERID = 2000;
-    private static String INFO_VMUSERNAME = "User";
-
-    private JvmStatHostListener hostListener;
-    private MonitoredHost host;
-    private MonitoredVm monitoredVm1;
-    private MonitoredVm monitoredVm2;
-    private JvmStatDataExtractor extractor;
-    private VmInfoDAO vmInfoDAO;
-    private VmStatusChangeNotifier notifier;
-    private VmBlacklist blacklist;
-
-    @Before
-    public void setup() throws MonitorException, URISyntaxException {
-        vmInfoDAO = mock(VmInfoDAO.class);
-        notifier = mock(VmStatusChangeNotifier.class);
-        
-        ProcessUserInfoBuilder userInfoBuilder = mock(ProcessUserInfoBuilder.class);
-        ProcessUserInfo userInfo = new ProcessUserInfo(INFO_VMUSERID, INFO_VMUSERNAME);
-        when(userInfoBuilder.build(any(int.class))).thenReturn(userInfo);
-
-        WriterID id = mock(WriterID.class);
-        HostRef hostRef = mock(HostRef.class);
-        blacklist = mock(VmBlacklist.class);
-        hostListener = new JvmStatHostListener(vmInfoDAO, notifier, userInfoBuilder, id, hostRef, blacklist);
-        
-        host = mock(MonitoredHost.class);
-        HostIdentifier hostId = mock(HostIdentifier.class);
-        monitoredVm1 = mock(MonitoredVm.class);
-        monitoredVm2 = mock(MonitoredVm.class);
-        StringMonitor monitor = mock(StringMonitor.class);
-        VmIdentifier vmId1 = new VmIdentifier("1");
-        VmIdentifier vmId2 = new VmIdentifier("2");
-        
-        when(host.getHostIdentifier()).thenReturn(hostId);
-        when(host.getMonitoredVm(eq(vmId1))).thenReturn(monitoredVm1);
-        when(host.getMonitoredVm(eq(vmId2))).thenReturn(monitoredVm2);
-        when(hostId.resolve(eq(vmId1))).thenReturn(vmId1);
-        when(hostId.resolve(eq(vmId2))).thenReturn(vmId2);
-        when(monitoredVm1.findByName(any(String.class))).thenReturn(monitor);
-        when(monitoredVm2.findByName(any(String.class))).thenReturn(monitor);
-        when(monitor.stringValue()).thenReturn("test");
-        when(monitor.getValue()).thenReturn("test");
-        
-        extractor = mock(JvmStatDataExtractor.class);
-        
-        when(extractor.getCommandLine()).thenReturn(INFO_CMDLINE);
-        when(extractor.getJavaHome()).thenReturn(INFO_JAVAHOME);
-        when(extractor.getJavaVersion()).thenReturn(INFO_JAVAVER);
-        when(extractor.getMainClass()).thenReturn(INFO_MAINCLASS);
-        when(extractor.getVmArguments()).thenReturn(INFO_VMARGS);
-        when(extractor.getVmInfo()).thenReturn(INFO_VMINFO);
-        when(extractor.getVmName()).thenReturn(INFO_VMNAME);
-        when(extractor.getVmVersion()).thenReturn(INFO_VMVER);
-    }
-    
-    @Test
-    public void testNewVM() throws InterruptedException, MonitorException {
-        startVMs();
-        
-        assertTrue(hostListener.getMonitoredVms().containsKey(1));
-        assertTrue(hostListener.getMonitoredVms().containsKey(2));
-        assertEquals(monitoredVm1, hostListener.getMonitoredVms().get(1).getSecond());
-        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
-        
-        // Check valid UUIDs
-        UUID uuid1 = UUID.fromString(hostListener.getMonitoredVms().get(1).getFirst());
-        UUID uuid2 = UUID.fromString(hostListener.getMonitoredVms().get(2).getFirst());
-        assertFalse(uuid1.equals(uuid2));
-        
-        verify(notifier, times(2)).notifyVmStatusChange(eq(Status.VM_STARTED), anyString(), (isA(Integer.class)));
-    }
-    
-    @Test
-    public void testNewVMBlackListed() throws InterruptedException, MonitorException {
-        when(blacklist.isBlacklisted(any(VmRef.class))).thenReturn(true).thenReturn(false);
-        startVMs();
-        
-        assertFalse(hostListener.getMonitoredVms().containsKey(1));
-        assertTrue(hostListener.getMonitoredVms().containsKey(2));
-        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
-        
-        UUID uuid = UUID.fromString(hostListener.getMonitoredVms().get(2).getFirst());
-        verify(notifier).notifyVmStatusChange(eq(Status.VM_STARTED), eq(uuid.toString()), (isA(Integer.class)));
-    }
-    
-    @Test
-    public void testStoppedVM() throws InterruptedException, MonitorException {
-        final Set<Integer> stopped = new HashSet<>();
-        stopped.add(1);
-        
-        startVMs();
-        
-        // Trigger a change event
-        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
-        when(event.getMonitoredHost()).thenReturn(host);
-        when(event.getStarted()).thenReturn(Collections.<Integer>emptySet());
-        when(event.getTerminated()).thenReturn(stopped);
-        hostListener.vmStatusChanged(event);
-        
-        // Ensure only 1 removed
-        assertFalse(hostListener.getMonitoredVms().containsKey(1));
-        assertTrue(hostListener.getMonitoredVms().containsKey(2));
-        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
-
-        verify(notifier).notifyVmStatusChange(eq(Status.VM_STOPPED), anyString(), (isA(Integer.class)));
-
-    }
-    
-    @Test
-    public void testReusedPid() {
-        final Set<Integer> started = new HashSet<>();
-        started.add(1);
-        
-        // Start VM
-        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
-        when(event.getMonitoredHost()).thenReturn(host);
-        when(event.getStarted()).thenReturn(started);
-        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
-        hostListener.vmStatusChanged(event);
-        
-        ArgumentCaptor<String> vmIdCaptor = ArgumentCaptor.forClass(String.class);
-        
-        // Stop VM
-        event = mock(VmStatusChangeEvent.class);
-        when(event.getMonitoredHost()).thenReturn(host);
-        when(event.getStarted()).thenReturn(Collections.<Integer>emptySet());
-        when(event.getTerminated()).thenReturn(started);
-        hostListener.vmStatusChanged(event);
-        
-        // Start new VM
-        event = mock(VmStatusChangeEvent.class);
-        when(event.getMonitoredHost()).thenReturn(host);
-        when(event.getStarted()).thenReturn(started);
-        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
-        hostListener.vmStatusChanged(event);
-        
-        verify(notifier, times(2)).notifyVmStatusChange(eq(Status.VM_STARTED), vmIdCaptor.capture(), eq(1));
-        List<String> vmIds = vmIdCaptor.getAllValues();
-        
-        assertEquals(2, vmIds.size());
-        String vmId1 = vmIds.get(0);
-        String vmId2 = vmIds.get(1);
-        assertNotNull(vmId1);
-        assertNotNull(vmId2);
-        assertFalse(vmId1.equals(vmId2));
-    }
-
-    private void startVMs() throws InterruptedException, MonitorException {
-        final Set<Integer> started = new HashSet<>();
-        started.add(1);
-        started.add(2);
-
-        // Trigger a change event
-        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
-        when(event.getMonitoredHost()).thenReturn(host);
-        when(event.getStarted()).thenReturn(started);
-        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
-        hostListener.vmStatusChanged(event);
-    }
-
-    @Test
-    public void testCreateVmInfo() throws MonitorException {
-        final String INFO_ID = "vmId";
-        final int INFO_PID = 1;
-        final long INFO_STARTTIME = Long.MIN_VALUE;
-        final long INFO_STOPTIME = Long.MAX_VALUE;
-        VmInfo info = hostListener.createVmInfo(INFO_ID, INFO_PID, INFO_STARTTIME, INFO_STOPTIME, extractor);
-        
-        assertEquals(INFO_PID, info.getVmPid());
-        assertEquals(INFO_STARTTIME, info.getStartTimeStamp());
-        assertEquals(INFO_STOPTIME, info.getStopTimeStamp());
-        assertEquals(INFO_CMDLINE, info.getJavaCommandLine());
-        assertEquals(INFO_JAVAHOME, info.getJavaHome());
-        assertEquals(INFO_JAVAVER, info.getJavaVersion());
-        assertEquals(INFO_MAINCLASS, info.getMainClass());
-        assertEquals(INFO_VMARGS, info.getVmArguments());
-        assertEquals(INFO_VMINFO, info.getVmInfo());
-        assertEquals(INFO_VMNAME, info.getVmName());
-        assertEquals(INFO_VMVER, info.getVmVersion());
-        assertEquals(INFO_VMUSERID, info.getUid());
-        assertEquals(INFO_VMUSERNAME, info.getUsername());
-    }
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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 org.junit.Test;
-
-public class LsbReleaseTest {
-    
-    static final String NOT_EXISTING_LSB_RELEASE = "lsb_release-"
-            + UUID.randomUUID();
-
-    @Test
-    public void testName() throws IOException, InterruptedException {
-        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 {
-        BufferedReader reader = new BufferedReader(new StringReader("Release: Version"));
-        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
-        assertEquals("Version", info.getVersion());
-    }
-    
-    @Test
-    public void getDistributionInformationThrowsIOExceptionIfScriptNotThere() {
-        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/NetworkInfoBuilderTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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.Mockito.mock;
-
-import java.util.List;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class NetworkInfoBuilderTest {
-
-    @Test
-    public void testBuilder() {
-
-        WriterID id = mock(WriterID.class);
-        
-        NetworkInfoBuilder builder = new NetworkInfoBuilder(id);
-        List<NetworkInterfaceInfo> info = builder.build();
-        assertNotNull(info);
-        for (NetworkInterfaceInfo iface: info) {
-            assertNotNull(iface);
-            assertNotNull(iface.getInterfaceName());
-            if (iface.getIp4Addr() != null) {
-                // ipv4 address matches the form XX.XX.XX.XX
-                assertTrue(iface.getIp4Addr().matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
-            }
-            if (iface.getIp6Addr() != null) {
-                validateIpv6Address(iface.getIp6Addr());
-            }
-        }
-
-    }
-
-    private void validateIpv6Address(String address) {
-        // ipv6 addresses may contain a scope id
-        if (address.contains("%")) {
-            int index = address.indexOf("%");
-            assertTrue(index >= 0);
-            String scopeId = address.substring(index);
-            assertFalse(scopeId.isEmpty());
-            address = address.substring(0, index);
-        }
-
-        String[] parts = address.split(":");
-        assertEquals(8, parts.length);
-
-        for (String part : parts) {
-            assertNotNull(part);
-            if (!part.isEmpty()) {
-                assertTrue(part.matches("[0-9a-f]*"));
-            }
-        }
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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.Mockito.any;
-import static org.mockito.Mockito.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 org.junit.Test;
-
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.testutils.TestUtils;
-
-public class ProcessEnvironmentBuilderTest {
-
-    private final Random r = new Random();
-
-    @Test
-    public void testBasicBuild() {
-        ProcDataSource dataSource = new ProcDataSource();
-        Map<String, String> result = new ProcessEnvironmentBuilder(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 ProcessEnvironmentBuilder(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 ProcessEnvironmentBuilder(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/ProcessUserInfoBuilderTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.utils.ProcDataSource;
-import com.redhat.thermostat.agent.utils.username.UserNameLookupException;
-import com.redhat.thermostat.agent.utils.username.UserNameUtil;
-import com.redhat.thermostat.backend.system.ProcessUserInfoBuilder.ProcessUserInfo;
-import com.redhat.thermostat.common.tools.ApplicationException;
-
-public class ProcessUserInfoBuilderTest {
-    
-    @Test
-    public void testBuild() throws UserNameLookupException, IOException, ApplicationException {
-        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000");
-        ProcDataSource source = mock(ProcDataSource.class);
-        UserNameUtil util = mock(UserNameUtil.class);
-        when(util.getUserName(2000)).thenReturn("myUser");
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
-        ProcessUserInfo info = builder.build(0);
-        
-        assertEquals(2000, info.getUid());
-        assertEquals("myUser", info.getUsername());
-    }
-    
-    @Test
-    public void testBuildErrorUid() throws IOException, ApplicationException {
-        StringReader reader = new StringReader("");
-        ProcDataSource source = mock(ProcDataSource.class);
-        UserNameUtil util = mock(UserNameUtil.class);
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
-        ProcessUserInfo info = builder.build(0);
-        
-        assertEquals(-1, info.getUid());
-        assertEquals(null, info.getUsername());
-    }
-    
-    @Test
-    public void testBuildErrorUsername() throws IOException, UserNameLookupException, ApplicationException {
-        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000");
-        ProcDataSource source = mock(ProcDataSource.class);
-        UserNameUtil util = mock(UserNameUtil.class);
-        when(util.getUserName(2000)).thenReturn(null);
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
-        ProcessUserInfo info = builder.build(0);
-        
-        assertEquals(2000, info.getUid());
-        assertEquals(null, info.getUsername());
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.VmBlacklist;
-import com.redhat.thermostat.agent.utils.username.UserNameUtil;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.storage.dao.HostInfoDAO;
-import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.storage.dao.VmInfoDAO;
-
-public class SystemBackendTest {
-
-    private static final String VERSION = "0.0.0";
-    private SystemBackend b;
-
-    @Before
-    public void setUp() {
-        HostInfoDAO hDAO = mock(HostInfoDAO.class);
-        NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class);
-        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
-
-        Version version = mock(Version.class);
-        when(version.getVersionNumber()).thenReturn(VERSION);
-        
-        VmStatusChangeNotifier notifier = mock(VmStatusChangeNotifier.class);
-        UserNameUtil util = mock(UserNameUtil.class);
-
-        WriterID id = mock(WriterID.class);
-        VmBlacklist blacklist = mock(VmBlacklist.class);
-        b = new SystemBackend(hDAO, nDAO, vmInfoDAO, version, notifier, util, id, blacklist);
-    }
-
-    @Test
-    public void testBasicBackend() {
-        assertFalse(b.isActive());
-        b.activate();
-        assertTrue(b.isActive());
-        b.deactivate();
-        assertFalse(b.isActive());
-    }
-
-    @Test
-    public void testActivateTwice() {
-        b.activate();
-        b.activate();
-        assert(b.isActive());
-    }
-
-    @Test
-    public void testDeactiateWhenNotActive() {
-        b.deactivate();
-        b.deactivate();
-        assertFalse(b.isActive());
-    }
-    
-    @Test
-    public void testVersion() {
-        assertEquals(VERSION, b.getVersion());
-    }
-
-}
-
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/TestLogHandler.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-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/VmStatusChangeNotifierTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright 2012-2016 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;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.util.ConcurrentModificationException;
-
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.agent.VmStatusListener;
-import com.redhat.thermostat.agent.VmStatusListener.Status;
-import com.redhat.thermostat.testutils.StubBundleContext;
-
-public class VmStatusChangeNotifierTest {
-
-    @Test
-    public void verifyWorksWithoutAnyListeners() {
-        final String VM_ID = "vmId";
-        final int VM_PID = 2;
-        StubBundleContext bundleContext = new StubBundleContext();
-
-        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
-        notifier.start();
-        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
-
-        notifier.notifyVmStatusChange(Status.VM_STOPPED, VM_ID, VM_PID);
-    }
-
-    @Test
-    public void verifyAllListenersAreNotified() {
-        final String VM_ID = "vmId";
-        final int VM_PID = 2;
-        StubBundleContext bundleContext = new StubBundleContext();
-
-        VmStatusListener listener = mock(VmStatusListener.class);
-        bundleContext.registerService(VmStatusListener.class, listener, null);
-
-        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
-        notifier.start();
-        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
-
-        verify(listener).vmStatusChanged(Status.VM_STARTED, VM_ID, VM_PID);
-
-        notifier.notifyVmStatusChange(Status.VM_STOPPED, VM_ID, VM_PID);
-
-        verify(listener).vmStatusChanged(Status.VM_STOPPED, VM_ID, VM_PID);
-    }
-
-    @Test
-    public void verifyListenersAddedAfterVmStartRecieveVmActiveEvent() {
-        final String VM_ID = "vmId";
-        final int VM_PID = 2;
-        StubBundleContext bundleContext = new StubBundleContext();
-
-        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
-        notifier.start();
-        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
-
-        VmStatusListener listener = mock(VmStatusListener.class);
-        bundleContext.registerService(VmStatusListener.class, listener, null);
-
-        verify(listener).vmStatusChanged(Status.VM_ACTIVE, VM_ID, VM_PID);
-
-    }
-    
-    /*
-     * Some backends might activate on activation of another backend. If both of
-     * them are also VmStatusListener's, a concurrent modification exception
-     * might be thrown. This tests verifies it's OK to do so (concurrent modification).
-     */
-    @Test
-    public void canAddListenersWhileFiringEvent() throws InterruptedException {
-        StubBundleContext bundleContext = new StubBundleContext();
-        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
-        
-        // Add > 2 listeners. One of them registers another listener in vmStatusChanged()
-        // Thus provoking ConcurrentModificationException.
-        bundleContext.registerService(VmStatusListener.class, new TestVmStatusListener(bundleContext), null);
-        bundleContext.registerService(VmStatusListener.class, new VmStatusListener() {
-
-            @Override
-            public void vmStatusChanged(Status newStatus, String vmId,
-                    int pid) {
-                Debug.println("Second registered listener fired");
-            }
-            
-            @Override
-            public int hashCode() {
-                return 2; // second listener to be fired
-            }
-            
-        }, null);
-        bundleContext.registerService(VmStatusListener.class, new VmStatusListener() {
-
-            @Override
-            public void vmStatusChanged(Status newStatus, String vmId,
-                    int pid) {
-                Debug.println("Third registered listener fired");
-            }
-            
-            @Override
-            public int hashCode() {
-                return 3;
-            }
-            
-        }, null);
-        notifier.start();
-        
-        try {
-            notifier.notifyVmStatusChange(Status.VM_STARTED, "foo-vmid", 333);
-            // this will trigger the newly added listener being invoked and counting
-            // down the latch.
-            notifier.notifyVmStatusChange(Status.VM_STARTED, "foo-other", 9999);
-            // pass
-        } catch (ConcurrentModificationException e) {
-            fail("Unexpected conncurrent modification exception!");
-        }
-    }
-    
-    static class TestVmStatusListener implements VmStatusListener {
-
-        private final BundleContext context;
-        
-        private TestVmStatusListener(BundleContext context) {
-            this.context = context;
-        }
-        
-        @Override
-        public void vmStatusChanged(Status newStatus, String vmId, int pid) {
-            Debug.println("First registered listener fired");
-            context.registerService(VmStatusListener.class, new VmStatusListener() {
-
-                @Override
-                public void vmStatusChanged(Status newStatus, String vmId,
-                        int pid) {
-                    Debug.println("Listener registered in listener (between first and second) fired");
-                }
-                
-                @Override
-                public int hashCode() {
-                    // Pick a large hash code since that tends to result in
-                    // the listener being fired later on.
-                    return 101;
-                }
-                
-            }, null);
-        }
-        
-        @Override
-        public int hashCode() {
-            // Heuristic for HashMap it tends to be picked first when iterating over
-            return 1;
-        }
-        
-    }
-    
-    static class Debug {
-        
-        static final boolean debugOn = false; // set to true for debug output
-        
-        static void println(String msg) {
-            if (debugOn) {
-                System.err.println(msg);
-            }
-        }
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/DistributionInformationTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2012-2016 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 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 org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.TestUtils;
+
+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 (TestUtils.isLinux()) {
+            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 (TestUtils.isLinux()) {
+            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/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/EtcOsReleaseTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-2016 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 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 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() {
+        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/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/HostInfoBuilderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-2016 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 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 org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.backend.system.internal.HostInfoBuilder.HostCpuInfo;
+import com.redhat.thermostat.backend.system.internal.HostInfoBuilder.HostMemoryInfo;
+import com.redhat.thermostat.backend.system.internal.HostInfoBuilder.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() {
+        HostInfo info = new HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(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 HostInfoBuilder(dataSource, writerId).getHostName(address);
+        assertEquals("test-hostname", name);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/JvmStatDataExtractorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012-2016 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 static org.junit.Assert.assertEquals;
+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 org.junit.Test;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.StringMonitor;
+
+public class JvmStatDataExtractorTest {
+
+    private MonitoredVm buildStringMonitoredVm(String monitorName, String monitorReturn) throws MonitorException {
+        final StringMonitor monitor = mock(StringMonitor.class);
+        when(monitor.stringValue()).thenReturn(monitorReturn);
+        when(monitor.getValue()).thenReturn(monitorReturn);
+        MonitoredVm vm = mock(MonitoredVm.class);
+        when(vm.findByName(monitorName)).thenReturn(monitor);
+        return vm;
+    }
+
+    @Test
+    public void testCommandLine() throws MonitorException {
+        final String MONITOR_NAME = "sun.rt.javaCommand";
+        final String MONITOR_VALUE = "command line java";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getCommandLine();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testMainClass() throws MonitorException {
+        final String MONITOR_NAME = "sun.rt.javaCommand";
+        final String MONITOR_VALUE = "some.package.Main";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getMainClass();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testJavaVersion() throws MonitorException {
+        final String MONITOR_NAME = "java.property.java.version";
+        final String MONITOR_VALUE = "some java version";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getJavaVersion();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testJavaHome() throws MonitorException {
+        final String MONITOR_NAME = "java.property.java.home";
+        final String MONITOR_VALUE = "${java.home}";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getJavaHome();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testVmName() throws MonitorException {
+        final String MONITOR_NAME = "java.property.java.vm.name";
+        final String MONITOR_VALUE = "${vm.name}";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getVmName();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testVmInfo() throws MonitorException {
+        final String MONITOR_NAME = "java.property.java.vm.info";
+        final String MONITOR_VALUE = "${vm.info}";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getVmInfo();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testVmVersion() throws MonitorException {
+        final String MONITOR_NAME = "java.property.java.vm.version";
+        final String MONITOR_VALUE = "${vm.version}";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getVmVersion();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testVmArguments() throws MonitorException {
+        final String MONITOR_NAME = "java.rt.vmArgs";
+        final String MONITOR_VALUE = "${vm.arguments}";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getVmArguments();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/JvmStatHostListenerTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2012-2016 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 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.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.VmBlacklist;
+import com.redhat.thermostat.agent.VmStatusListener.Status;
+import com.redhat.thermostat.backend.system.internal.ProcessUserInfoBuilder.ProcessUserInfo;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
+
+import sun.jvmstat.monitor.HostIdentifier;
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.StringMonitor;
+import sun.jvmstat.monitor.VmIdentifier;
+import sun.jvmstat.monitor.event.VmStatusChangeEvent;
+
+public class JvmStatHostListenerTest {
+    
+    private static String INFO_CMDLINE = "/path/to/executable command line args";
+    private static String INFO_JAVAHOME = "/path/to/java";
+    private static String INFO_JAVAVER = "1.9001";
+    private static String INFO_MAINCLASS = "MyMainClass";
+    private static String INFO_VMARGS = "-Xarg1 -Xarg2";
+    private static String INFO_VMINFO = "Info";
+    private static String INFO_VMNAME = "MyJVM";
+    private static String INFO_VMVER = "90.01";
+    private static long INFO_VMUSERID = 2000;
+    private static String INFO_VMUSERNAME = "User";
+
+    private JvmStatHostListener hostListener;
+    private MonitoredHost host;
+    private MonitoredVm monitoredVm1;
+    private MonitoredVm monitoredVm2;
+    private JvmStatDataExtractor extractor;
+    private VmInfoDAO vmInfoDAO;
+    private VmStatusChangeNotifier notifier;
+    private VmBlacklist blacklist;
+
+    @Before
+    public void setup() throws MonitorException, URISyntaxException {
+        vmInfoDAO = mock(VmInfoDAO.class);
+        notifier = mock(VmStatusChangeNotifier.class);
+        
+        ProcessUserInfoBuilder userInfoBuilder = mock(ProcessUserInfoBuilder.class);
+        ProcessUserInfo userInfo = new ProcessUserInfo(INFO_VMUSERID, INFO_VMUSERNAME);
+        when(userInfoBuilder.build(any(int.class))).thenReturn(userInfo);
+
+        WriterID id = mock(WriterID.class);
+        HostRef hostRef = mock(HostRef.class);
+        blacklist = mock(VmBlacklist.class);
+        hostListener = new JvmStatHostListener(vmInfoDAO, notifier, userInfoBuilder, id, hostRef, blacklist);
+        
+        host = mock(MonitoredHost.class);
+        HostIdentifier hostId = mock(HostIdentifier.class);
+        monitoredVm1 = mock(MonitoredVm.class);
+        monitoredVm2 = mock(MonitoredVm.class);
+        StringMonitor monitor = mock(StringMonitor.class);
+        VmIdentifier vmId1 = new VmIdentifier("1");
+        VmIdentifier vmId2 = new VmIdentifier("2");
+        
+        when(host.getHostIdentifier()).thenReturn(hostId);
+        when(host.getMonitoredVm(eq(vmId1))).thenReturn(monitoredVm1);
+        when(host.getMonitoredVm(eq(vmId2))).thenReturn(monitoredVm2);
+        when(hostId.resolve(eq(vmId1))).thenReturn(vmId1);
+        when(hostId.resolve(eq(vmId2))).thenReturn(vmId2);
+        when(monitoredVm1.findByName(any(String.class))).thenReturn(monitor);
+        when(monitoredVm2.findByName(any(String.class))).thenReturn(monitor);
+        when(monitor.stringValue()).thenReturn("test");
+        when(monitor.getValue()).thenReturn("test");
+        
+        extractor = mock(JvmStatDataExtractor.class);
+        
+        when(extractor.getCommandLine()).thenReturn(INFO_CMDLINE);
+        when(extractor.getJavaHome()).thenReturn(INFO_JAVAHOME);
+        when(extractor.getJavaVersion()).thenReturn(INFO_JAVAVER);
+        when(extractor.getMainClass()).thenReturn(INFO_MAINCLASS);
+        when(extractor.getVmArguments()).thenReturn(INFO_VMARGS);
+        when(extractor.getVmInfo()).thenReturn(INFO_VMINFO);
+        when(extractor.getVmName()).thenReturn(INFO_VMNAME);
+        when(extractor.getVmVersion()).thenReturn(INFO_VMVER);
+    }
+    
+    @Test
+    public void testNewVM() throws InterruptedException, MonitorException {
+        startVMs();
+        
+        assertTrue(hostListener.getMonitoredVms().containsKey(1));
+        assertTrue(hostListener.getMonitoredVms().containsKey(2));
+        assertEquals(monitoredVm1, hostListener.getMonitoredVms().get(1).getSecond());
+        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
+        
+        // Check valid UUIDs
+        UUID uuid1 = UUID.fromString(hostListener.getMonitoredVms().get(1).getFirst());
+        UUID uuid2 = UUID.fromString(hostListener.getMonitoredVms().get(2).getFirst());
+        assertFalse(uuid1.equals(uuid2));
+        
+        verify(notifier, times(2)).notifyVmStatusChange(eq(Status.VM_STARTED), anyString(), (isA(Integer.class)));
+    }
+    
+    @Test
+    public void testNewVMBlackListed() throws InterruptedException, MonitorException {
+        when(blacklist.isBlacklisted(any(VmRef.class))).thenReturn(true).thenReturn(false);
+        startVMs();
+        
+        assertFalse(hostListener.getMonitoredVms().containsKey(1));
+        assertTrue(hostListener.getMonitoredVms().containsKey(2));
+        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
+        
+        UUID uuid = UUID.fromString(hostListener.getMonitoredVms().get(2).getFirst());
+        verify(notifier).notifyVmStatusChange(eq(Status.VM_STARTED), eq(uuid.toString()), (isA(Integer.class)));
+    }
+    
+    @Test
+    public void testStoppedVM() throws InterruptedException, MonitorException {
+        final Set<Integer> stopped = new HashSet<>();
+        stopped.add(1);
+        
+        startVMs();
+        
+        // Trigger a change event
+        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
+        when(event.getMonitoredHost()).thenReturn(host);
+        when(event.getStarted()).thenReturn(Collections.<Integer>emptySet());
+        when(event.getTerminated()).thenReturn(stopped);
+        hostListener.vmStatusChanged(event);
+        
+        // Ensure only 1 removed
+        assertFalse(hostListener.getMonitoredVms().containsKey(1));
+        assertTrue(hostListener.getMonitoredVms().containsKey(2));
+        assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2).getSecond());
+
+        verify(notifier).notifyVmStatusChange(eq(Status.VM_STOPPED), anyString(), (isA(Integer.class)));
+
+    }
+    
+    @Test
+    public void testReusedPid() {
+        final Set<Integer> started = new HashSet<>();
+        started.add(1);
+        
+        // Start VM
+        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
+        when(event.getMonitoredHost()).thenReturn(host);
+        when(event.getStarted()).thenReturn(started);
+        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
+        hostListener.vmStatusChanged(event);
+        
+        ArgumentCaptor<String> vmIdCaptor = ArgumentCaptor.forClass(String.class);
+        
+        // Stop VM
+        event = mock(VmStatusChangeEvent.class);
+        when(event.getMonitoredHost()).thenReturn(host);
+        when(event.getStarted()).thenReturn(Collections.<Integer>emptySet());
+        when(event.getTerminated()).thenReturn(started);
+        hostListener.vmStatusChanged(event);
+        
+        // Start new VM
+        event = mock(VmStatusChangeEvent.class);
+        when(event.getMonitoredHost()).thenReturn(host);
+        when(event.getStarted()).thenReturn(started);
+        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
+        hostListener.vmStatusChanged(event);
+        
+        verify(notifier, times(2)).notifyVmStatusChange(eq(Status.VM_STARTED), vmIdCaptor.capture(), eq(1));
+        List<String> vmIds = vmIdCaptor.getAllValues();
+        
+        assertEquals(2, vmIds.size());
+        String vmId1 = vmIds.get(0);
+        String vmId2 = vmIds.get(1);
+        assertNotNull(vmId1);
+        assertNotNull(vmId2);
+        assertFalse(vmId1.equals(vmId2));
+    }
+
+    private void startVMs() throws InterruptedException, MonitorException {
+        final Set<Integer> started = new HashSet<>();
+        started.add(1);
+        started.add(2);
+
+        // Trigger a change event
+        VmStatusChangeEvent event = mock(VmStatusChangeEvent.class);
+        when(event.getMonitoredHost()).thenReturn(host);
+        when(event.getStarted()).thenReturn(started);
+        when(event.getTerminated()).thenReturn(Collections.<Integer>emptySet());
+        hostListener.vmStatusChanged(event);
+    }
+
+    @Test
+    public void testCreateVmInfo() throws MonitorException {
+        final String INFO_ID = "vmId";
+        final int INFO_PID = 1;
+        final long INFO_STARTTIME = Long.MIN_VALUE;
+        final long INFO_STOPTIME = Long.MAX_VALUE;
+        VmInfo info = hostListener.createVmInfo(INFO_ID, INFO_PID, INFO_STARTTIME, INFO_STOPTIME, extractor);
+        
+        assertEquals(INFO_PID, info.getVmPid());
+        assertEquals(INFO_STARTTIME, info.getStartTimeStamp());
+        assertEquals(INFO_STOPTIME, info.getStopTimeStamp());
+        assertEquals(INFO_CMDLINE, info.getJavaCommandLine());
+        assertEquals(INFO_JAVAHOME, info.getJavaHome());
+        assertEquals(INFO_JAVAVER, info.getJavaVersion());
+        assertEquals(INFO_MAINCLASS, info.getMainClass());
+        assertEquals(INFO_VMARGS, info.getVmArguments());
+        assertEquals(INFO_VMINFO, info.getVmInfo());
+        assertEquals(INFO_VMNAME, info.getVmName());
+        assertEquals(INFO_VMVER, info.getVmVersion());
+        assertEquals(INFO_VMUSERID, info.getUid());
+        assertEquals(INFO_VMUSERNAME, info.getUsername());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/LsbReleaseTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-2016 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 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 org.junit.Test;
+
+public class LsbReleaseTest {
+    
+    static final String NOT_EXISTING_LSB_RELEASE = "lsb_release-"
+            + UUID.randomUUID();
+
+    @Test
+    public void testName() throws IOException, InterruptedException {
+        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 {
+        BufferedReader reader = new BufferedReader(new StringReader("Release: Version"));
+        DistributionInformation info = new LsbRelease().getFromLsbRelease(reader);
+        assertEquals("Version", info.getVersion());
+    }
+    
+    @Test
+    public void getDistributionInformationThrowsIOExceptionIfScriptNotThere() {
+        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/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/NetworkInfoBuilderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-2016 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 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.Mockito.mock;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class NetworkInfoBuilderTest {
+
+    @Test
+    public void testBuilder() {
+
+        WriterID id = mock(WriterID.class);
+        
+        NetworkInfoBuilder builder = new NetworkInfoBuilder(id);
+        List<NetworkInterfaceInfo> info = builder.build();
+        assertNotNull(info);
+        for (NetworkInterfaceInfo iface: info) {
+            assertNotNull(iface);
+            assertNotNull(iface.getInterfaceName());
+            if (iface.getIp4Addr() != null) {
+                // ipv4 address matches the form XX.XX.XX.XX
+                assertTrue(iface.getIp4Addr().matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
+            }
+            if (iface.getIp6Addr() != null) {
+                validateIpv6Address(iface.getIp6Addr());
+            }
+        }
+
+    }
+
+    private void validateIpv6Address(String address) {
+        // ipv6 addresses may contain a scope id
+        if (address.contains("%")) {
+            int index = address.indexOf("%");
+            assertTrue(index >= 0);
+            String scopeId = address.substring(index);
+            assertFalse(scopeId.isEmpty());
+            address = address.substring(0, index);
+        }
+
+        String[] parts = address.split(":");
+        assertEquals(8, parts.length);
+
+        for (String part : parts) {
+            assertNotNull(part);
+            if (!part.isEmpty()) {
+                assertTrue(part.matches("[0-9a-f]*"));
+            }
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/ProcessEnvironmentBuilderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-2016 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 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 org.junit.Test;
+
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.testutils.TestUtils;
+
+public class ProcessEnvironmentBuilderTest {
+
+    private final Random r = new Random();
+
+    @Test
+    public void testBasicBuild() {
+        ProcDataSource dataSource = new ProcDataSource();
+        Map<String, String> result = new ProcessEnvironmentBuilder(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 ProcessEnvironmentBuilder(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 ProcessEnvironmentBuilder(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;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/ProcessUserInfoBuilderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012-2016 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 static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.agent.utils.username.UserNameLookupException;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.backend.system.internal.ProcessUserInfoBuilder.ProcessUserInfo;
+import com.redhat.thermostat.common.tools.ApplicationException;
+
+public class ProcessUserInfoBuilderTest {
+    
+    @Test
+    public void testBuild() throws UserNameLookupException, IOException, ApplicationException {
+        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000");
+        ProcDataSource source = mock(ProcDataSource.class);
+        UserNameUtil util = mock(UserNameUtil.class);
+        when(util.getUserName(2000)).thenReturn("myUser");
+        when(source.getStatusReader(anyInt())).thenReturn(reader);
+        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
+        ProcessUserInfo info = builder.build(0);
+        
+        assertEquals(2000, info.getUid());
+        assertEquals("myUser", info.getUsername());
+    }
+    
+    @Test
+    public void testBuildErrorUid() throws IOException, ApplicationException {
+        StringReader reader = new StringReader("");
+        ProcDataSource source = mock(ProcDataSource.class);
+        UserNameUtil util = mock(UserNameUtil.class);
+        when(source.getStatusReader(anyInt())).thenReturn(reader);
+        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
+        ProcessUserInfo info = builder.build(0);
+        
+        assertEquals(-1, info.getUid());
+        assertEquals(null, info.getUsername());
+    }
+    
+    @Test
+    public void testBuildErrorUsername() throws IOException, UserNameLookupException, ApplicationException {
+        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000");
+        ProcDataSource source = mock(ProcDataSource.class);
+        UserNameUtil util = mock(UserNameUtil.class);
+        when(util.getUserName(2000)).thenReturn(null);
+        when(source.getStatusReader(anyInt())).thenReturn(reader);
+        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source, util);
+        ProcessUserInfo info = builder.build(0);
+        
+        assertEquals(2000, info.getUid());
+        assertEquals(null, info.getUsername());
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/SystemBackendTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012-2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.VmBlacklist;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+public class SystemBackendTest {
+
+    private static final String VERSION = "0.0.0";
+    private SystemBackend b;
+
+    @Before
+    public void setUp() {
+        HostInfoDAO hDAO = mock(HostInfoDAO.class);
+        NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class);
+        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
+
+        Version version = mock(Version.class);
+        when(version.getVersionNumber()).thenReturn(VERSION);
+        
+        VmStatusChangeNotifier notifier = mock(VmStatusChangeNotifier.class);
+        UserNameUtil util = mock(UserNameUtil.class);
+
+        WriterID id = mock(WriterID.class);
+        VmBlacklist blacklist = mock(VmBlacklist.class);
+        b = new SystemBackend(hDAO, nDAO, vmInfoDAO, version, notifier, util, id, blacklist);
+    }
+
+    @Test
+    public void testBasicBackend() {
+        assertFalse(b.isActive());
+        b.activate();
+        assertTrue(b.isActive());
+        b.deactivate();
+        assertFalse(b.isActive());
+    }
+
+    @Test
+    public void testActivateTwice() {
+        b.activate();
+        b.activate();
+        assert(b.isActive());
+    }
+
+    @Test
+    public void testDeactiateWhenNotActive() {
+        b.deactivate();
+        b.deactivate();
+        assertFalse(b.isActive());
+    }
+    
+    @Test
+    public void testVersion() {
+        assertEquals(VERSION, b.getVersion());
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/TestLogHandler.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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 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/system-backend/src/test/java/com/redhat/thermostat/backend/system/internal/VmStatusChangeNotifierTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2012-2016 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 static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.ConcurrentModificationException;
+
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.agent.VmStatusListener;
+import com.redhat.thermostat.agent.VmStatusListener.Status;
+import com.redhat.thermostat.testutils.StubBundleContext;
+
+public class VmStatusChangeNotifierTest {
+
+    @Test
+    public void verifyWorksWithoutAnyListeners() {
+        final String VM_ID = "vmId";
+        final int VM_PID = 2;
+        StubBundleContext bundleContext = new StubBundleContext();
+
+        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
+        notifier.start();
+        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
+
+        notifier.notifyVmStatusChange(Status.VM_STOPPED, VM_ID, VM_PID);
+    }
+
+    @Test
+    public void verifyAllListenersAreNotified() {
+        final String VM_ID = "vmId";
+        final int VM_PID = 2;
+        StubBundleContext bundleContext = new StubBundleContext();
+
+        VmStatusListener listener = mock(VmStatusListener.class);
+        bundleContext.registerService(VmStatusListener.class, listener, null);
+
+        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
+        notifier.start();
+        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
+
+        verify(listener).vmStatusChanged(Status.VM_STARTED, VM_ID, VM_PID);
+
+        notifier.notifyVmStatusChange(Status.VM_STOPPED, VM_ID, VM_PID);
+
+        verify(listener).vmStatusChanged(Status.VM_STOPPED, VM_ID, VM_PID);
+    }
+
+    @Test
+    public void verifyListenersAddedAfterVmStartRecieveVmActiveEvent() {
+        final String VM_ID = "vmId";
+        final int VM_PID = 2;
+        StubBundleContext bundleContext = new StubBundleContext();
+
+        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
+        notifier.start();
+        notifier.notifyVmStatusChange(Status.VM_STARTED, VM_ID, VM_PID);
+
+        VmStatusListener listener = mock(VmStatusListener.class);
+        bundleContext.registerService(VmStatusListener.class, listener, null);
+
+        verify(listener).vmStatusChanged(Status.VM_ACTIVE, VM_ID, VM_PID);
+
+    }
+    
+    /*
+     * Some backends might activate on activation of another backend. If both of
+     * them are also VmStatusListener's, a concurrent modification exception
+     * might be thrown. This tests verifies it's OK to do so (concurrent modification).
+     */
+    @Test
+    public void canAddListenersWhileFiringEvent() throws InterruptedException {
+        StubBundleContext bundleContext = new StubBundleContext();
+        VmStatusChangeNotifier notifier = new VmStatusChangeNotifier(bundleContext);
+        
+        // Add > 2 listeners. One of them registers another listener in vmStatusChanged()
+        // Thus provoking ConcurrentModificationException.
+        bundleContext.registerService(VmStatusListener.class, new TestVmStatusListener(bundleContext), null);
+        bundleContext.registerService(VmStatusListener.class, new VmStatusListener() {
+
+            @Override
+            public void vmStatusChanged(Status newStatus, String vmId,
+                    int pid) {
+                Debug.println("Second registered listener fired");
+            }
+            
+            @Override
+            public int hashCode() {
+                return 2; // second listener to be fired
+            }
+            
+        }, null);
+        bundleContext.registerService(VmStatusListener.class, new VmStatusListener() {
+
+            @Override
+            public void vmStatusChanged(Status newStatus, String vmId,
+                    int pid) {
+                Debug.println("Third registered listener fired");
+            }
+            
+            @Override
+            public int hashCode() {
+                return 3;
+            }
+            
+        }, null);
+        notifier.start();
+        
+        try {
+            notifier.notifyVmStatusChange(Status.VM_STARTED, "foo-vmid", 333);
+            // this will trigger the newly added listener being invoked and counting
+            // down the latch.
+            notifier.notifyVmStatusChange(Status.VM_STARTED, "foo-other", 9999);
+            // pass
+        } catch (ConcurrentModificationException e) {
+            fail("Unexpected conncurrent modification exception!");
+        }
+    }
+    
+    static class TestVmStatusListener implements VmStatusListener {
+
+        private final BundleContext context;
+        
+        private TestVmStatusListener(BundleContext context) {
+            this.context = context;
+        }
+        
+        @Override
+        public void vmStatusChanged(Status newStatus, String vmId, int pid) {
+            Debug.println("First registered listener fired");
+            context.registerService(VmStatusListener.class, new VmStatusListener() {
+
+                @Override
+                public void vmStatusChanged(Status newStatus, String vmId,
+                        int pid) {
+                    Debug.println("Listener registered in listener (between first and second) fired");
+                }
+                
+                @Override
+                public int hashCode() {
+                    // Pick a large hash code since that tends to result in
+                    // the listener being fired later on.
+                    return 101;
+                }
+                
+            }, null);
+        }
+        
+        @Override
+        public int hashCode() {
+            // Heuristic for HashMap it tends to be picked first when iterating over
+            return 1;
+        }
+        
+    }
+    
+    static class Debug {
+        
+        static final boolean debugOn = false; // set to true for debug output
+        
+        static void println(String msg) {
+            if (debugOn) {
+                System.err.println(msg);
+            }
+        }
+    }
+}
+
--- a/thermostat-plugin-validator/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/thermostat-plugin-validator/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -81,7 +81,6 @@
             </Export-Package>
             <Private-Package>
               com.redhat.thermostat.plugin.validator.internal,
-              com.redhat.thermostat.plugin.validator.locale,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/ValidationErrorsFormatter.java	Mon May 02 18:43:01 2016 +0200
+++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/ValidationErrorsFormatter.java	Tue May 03 15:49:54 2016 +0200
@@ -43,7 +43,7 @@
 import java.util.List;
 import java.util.Map;
 
-import com.redhat.thermostat.plugin.validator.locale.LocaleResources;
+import com.redhat.thermostat.plugin.validator.internal.LocaleResources;
 import com.redhat.thermostat.shared.locale.Translate;
 
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-2016 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.plugin.validator.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+
+public enum LocaleResources {
+    
+    VALIDATION_WARNING,
+    VALIDATION_ERROR,
+    VALIDATION_FATAL_ERROR,
+    ;
+
+    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.plugin.validator.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- a/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012-2016 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.plugin.validator.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-
-public enum LocaleResources {
-    
-    VALIDATION_WARNING,
-    VALIDATION_ERROR,
-    VALIDATION_FATAL_ERROR,
-    ;
-
-    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.plugin.validator.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 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.plugin.validator.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- a/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.plugin.validator.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/thread/harvester/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/thread/harvester/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -101,10 +101,10 @@
         <configuration>
           <instructions>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.thread.harvester.Activator</Bundle-Activator>
+            <Bundle-Activator>com.redhat.thermostat.thread.harvester.internal.Activator</Bundle-Activator>
             <Bundle-SymbolicName>com.redhat.thermostat.thread.harvester</Bundle-SymbolicName>
             <Private-Package>
-              com.redhat.thermostat.thread.harvester,
+              com.redhat.thermostat.thread.harvester.internal,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.util.tracker.ServiceTracker;
-
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.agent.command.ReceiverRegistry;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.LockInfoDao;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-
-public class Activator implements BundleActivator {
-    
-    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(24);
-
-    private MultipleServiceTracker connectionPoolTracker;
-    private ServiceTracker threadDaoTracker;
-    private ServiceRegistration backendRegistration;
-
-    private ReceiverRegistry registry;
-    private ThreadHarvester harvester;
-    private ThreadBackend backend;
-
-    private MultipleServiceTracker threadCountTracker;
-
-    private MultipleServiceTracker lockInfoTracker;
-    
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        final Version VERSION = new Version(context.getBundle());
-        final VmStatusListenerRegistrar VM_STATUS_REGISTRAR
-            = new VmStatusListenerRegistrar(context);
-
-        Class<?>[] threadCountDeps = new Class<?>[] {
-                WriterID.class,
-                ThreadDao.class,
-        };
-        threadCountTracker = new MultipleServiceTracker(context, threadCountDeps, new Action() {
-
-            private ServiceRegistration<Backend> registration;
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
-                ThreadDao dao = (ThreadDao) services.get(ThreadDao.class.getName());
-                Objects.requireNonNull(dao);
-                ThreadCountBackend threadCountBackend = new ThreadCountBackend(dao, VERSION, VM_STATUS_REGISTRAR, writerId);
-                registration = context.registerService(Backend.class, threadCountBackend, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                registration.unregister();
-                registration = null;
-            }
-        });
-        threadCountTracker.open();
-
-        Class<?>[] lockInfoDeps = new Class<?>[] {
-            WriterID.class,
-            LockInfoDao.class,
-        };
-        lockInfoTracker = new MultipleServiceTracker(context, lockInfoDeps, new Action() {
-
-            private ServiceRegistration<Backend> registration;
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
-                LockInfoDao dao = (LockInfoDao) services.get(LockInfoDao.class.getName());
-                Objects.requireNonNull(dao);
-                LockInfoBackend lockInfoBackend = new LockInfoBackend(dao, VERSION, VM_STATUS_REGISTRAR, writerId);
-                registration = context.registerService(Backend.class, lockInfoBackend, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                registration.unregister();
-                registration = null;
-            }
-        });
-        lockInfoTracker.open();
-
-        Class<?>[] deps = new Class<?>[] {
-                MXBeanConnectionPool.class,
-                WriterID.class,
-        };
-        connectionPoolTracker = new MultipleServiceTracker(context, deps, new Action() {
-            
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                MXBeanConnectionPool pool = (MXBeanConnectionPool) services.get(MXBeanConnectionPool.class.getName());
-                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
-                harvester = new ThreadHarvester(executor, pool, writerId);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                harvester = null;
-            }
-        });
-        connectionPoolTracker.open();
-
-        registry = new ReceiverRegistry(context);
-
-        /*
-         * dont register anything just yet, let the backend handle the
-         * registration, deregistration it when it's activated or deactivated
-         */
-
-        backend = new ThreadBackend(VERSION, VM_STATUS_REGISTRAR, registry, harvester);
-        backendRegistration = context.registerService(Backend.class, backend, null);
-
-        threadDaoTracker = new ServiceTracker(context, ThreadDao.class.getName(), null) {
-            @Override
-            public Object addingService(ServiceReference reference) {
-                ThreadDao threadDao = (ThreadDao) context.getService(reference);
-                harvester.setThreadDao(threadDao);
-                return super.addingService(reference);
-            }
-
-            @Override
-            public void removedService(ServiceReference reference, Object service) {
-                if (harvester != null) {
-                    harvester.setThreadDao(null);
-                }
-                context.ungetService(reference);
-                super.removedService(reference, service);
-            }
-        };
-        threadDaoTracker.open();
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        if (backend.isActive()) {
-            backend.deactivate();
-        }
-
-        threadCountTracker.close();
-        lockInfoTracker.close();
-
-        backendRegistration.unregister();
-
-        connectionPoolTracker.close();
-        threadDaoTracker.close();
-
-        if (executor != null) {
-            executor.shutdown();
-        }        
-    }
-}
-
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/DeadlockHelper.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.VmDeadLockData;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
-/**
- */
-public class DeadlockHelper {
-
-    private final ThreadDao threadDao;
-    private final SystemClock systemClock;
-    private final String vmId;
-    private final WriterID id;
-
-    public DeadlockHelper(ThreadDao threadDao, SystemClock systemClock,
-                          String vmId, WriterID id)
-    {
-        this.threadDao = threadDao;
-        this.systemClock = systemClock;
-        this.vmId = vmId;
-        this.id = id;
-    }
-
-    void saveDeadlockInformation(ThreadMXBean collector) {
-        String description = null;
-        long timeStamp = systemClock.getRealTimeMillis();
-        long[] ids = collector.findDeadlockedThreads();
-        if (ids == null) {
-            description = VmDeadLockData.NO_DEADLOCK;
-        } else {
-            ThreadInfo[] infos = collector.getThreadInfo(ids, true, true);
-            StringBuilder descriptionBuilder = new StringBuilder();
-            for (ThreadInfo info : infos) {
-                descriptionBuilder.append(info.toString()).append("\n");
-            }
-            description = descriptionBuilder.toString();
-        }
-
-        String wId = id.getWriterID();
-        VmDeadLockData data = new VmDeadLockData(wId);
-        data.setTimeStamp(timeStamp);
-        data.setVmId(vmId);
-        data.setDeadLockDescription(description);
-
-        threadDao.saveDeadLockStatus(data);
-    }
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/Harvester.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionException;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSession;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadMXBean;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.management.MalformedObjectNameException;
-
-@SuppressWarnings("restriction")
-class Harvester {
-
-    static final long DEFAULT_INITIAL_DELAY = 0;
-    static final long DEFAULT_PERIOD = 250;
-    static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
-
-    private static final Logger logger = LoggingUtils.getLogger(Harvester.class);
-
-    private final ScheduledExecutorService threadPool;
-    private final int pid;
-
-    private boolean isConnected;
-    private ScheduledFuture<?> harvester;
-    private MXBeanConnection connection;
-    private ThreadMXBean collectorBean;
-
-    private HarvesterHelper harvesterHelper;
-    private final MXBeanConnectionPool connectionPool;
-    private final DeadlockHelper deadlockHelper;
-
-    public Harvester(ThreadDao threadDao, ScheduledExecutorService threadPool,
-                     String vmId, int pid, MXBeanConnectionPool connectionPool,
-                     WriterID writerId)
-    {
-        this(pid, threadPool, connectionPool,
-             new HarvesterHelper(threadDao, new SystemClock(), vmId, writerId),
-             new DeadlockHelper(threadDao, new SystemClock(), vmId, writerId));
-    }
-
-    Harvester(int pid, ScheduledExecutorService threadPool,
-              MXBeanConnectionPool connectionPool,
-              HarvesterHelper harvesterHelper,
-              DeadlockHelper deadlockHelper)
-    {
-        this.pid = pid;
-        this.threadPool = threadPool;
-        this.connectionPool = connectionPool;
-        this.harvesterHelper = harvesterHelper;
-        this.deadlockHelper = deadlockHelper;
-    }
-    
-    synchronized boolean start() {
-        if (isConnected()) {
-            return true;
-        }
-
-        if (!connect()) {
-            return false;
-        }
-
-        harvester = threadPool.scheduleAtFixedRate(new HarvesterAction(true),
-                                                   DEFAULT_INITIAL_DELAY,
-                                                   DEFAULT_PERIOD,
-                                                   DEFAULT_TIME_UNIT);
-
-        return isConnected();
-    }
-
-    private synchronized boolean connect() {
-        try {
-            connection = connectionPool.acquire(pid);
-        } catch (MXBeanConnectionException ex) {
-            logger.log(Level.SEVERE, "can't connect", ex);
-            return false;
-        }
-
-        setConnected(true);
-        return true;
-    }
-
-    synchronized boolean isConnected() {
-        return isConnected;
-    }
-
-    synchronized void setConnected(boolean isConnected) {
-        this.isConnected = isConnected;
-    }
-
-    synchronized boolean stop() {
-        if (!isConnected()) {
-            return true;
-        }
-        
-        harvester.cancel(false);
-        
-        return disconnect();
-    }
-    
-    int getPid() {
-        return pid;
-    }
-
-    private boolean disconnect() {
-        if (collectorBean != null) {
-            collectorBean = null;
-        }
-        
-        setConnected(false);
-
-        try {
-            connectionPool.release(pid, connection);
-        } catch (MXBeanConnectionException ex) {
-            logger.log(Level.SEVERE, "can't disconnect", ex);
-            return false;
-        }
-
-        return true;
-    }
-    
-    ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
-
-        if (connection == null) {
-            logger.log(Level.WARNING, "MXBeanConnection is null");
-            return null;
-        }
-
-        ThreadMXBean bean = null;
-        try {
-            bean = connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
-                                          com.sun.management.ThreadMXBean.class);
-        } catch (MalformedObjectNameException e) {
-            logger.log(Level.FINE,
-                       "com.sun.management.ThreadMXBean.class not " +
-                       "available for " +
-                       ManagementFactory.THREAD_MXBEAN_NAME, e);
-        }
-
-        if (bean == null) {
-            try {
-                bean = connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
-                                              ThreadMXBean.class);
-            } catch (MalformedObjectNameException e) {
-                logger.log(Level.WARNING,
-                           "java.lang.management.ThreadMXBean.class not " +
-                           "available for " +
-                           ManagementFactory.THREAD_MXBEAN_NAME, e);
-            }
-        }
-
-        return bean;
-    }
-
-    private class HarvesterAction implements Runnable {
-
-        private boolean newSession;
-        private ThreadSession session;
-
-        private HarvesterAction(boolean newSession) {
-            this.newSession = newSession;
-        }
-
-        @Override
-        public void run() {
-            if (collectorBean == null) {
-                collectorBean = getDataCollectorBean(connection);
-            }
-
-            // FIXME: should we do something in case this is still null?
-            // it basically means JMX is not available at this point...
-            if (collectorBean != null) {
-
-                // try to set some properties we're going to need
-                try {
-                    if (collectorBean.isCurrentThreadCpuTimeSupported() &&
-                        !collectorBean.isThreadCpuTimeEnabled())
-                    {
-                        collectorBean.setThreadCpuTimeEnabled(true);
-                    }
-
-                    if (collectorBean.isThreadContentionMonitoringSupported() &&
-                        !collectorBean.isThreadContentionMonitoringEnabled())
-                    {
-                        collectorBean.setThreadContentionMonitoringEnabled(true);
-                    }
-                } catch (UnsupportedOperationException ignore) {}
-
-                if (newSession) {
-                    session = harvesterHelper.createSession();
-                    harvesterHelper.saveSession(session);
-
-                    newSession = false;
-                }
-
-                harvesterHelper.collectAndSaveThreadData(session, collectorBean);
-
-            } else {
-                logger.log(Level.WARNING, "ThreadMXBean is null, is JMX available?");
-            }
-        }
-    }
-
-    public boolean saveDeadLockData() {
-        boolean disconnectAtEnd = false;
-        if (!isConnected()) {
-            disconnectAtEnd = true;
-
-            connect();
-        }
-
-        if (collectorBean == null) {
-            collectorBean = getDataCollectorBean(connection);
-        }
-
-        if (collectorBean != null) {
-            deadlockHelper.saveDeadlockInformation(collectorBean);
-        }
-
-        if (disconnectAtEnd) {
-            disconnect();
-        }
-
-        return true;
-    }
-    
-}
-
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/HarvesterHelper.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSession;
-import com.redhat.thermostat.thread.model.ThreadState;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
-/*
- */
-class HarvesterHelper {
-
-    private Clock clock;
-    private String vmId;
-
-    private ThreadStateHelper stateHelper;
-    private ThreadSessionHelper sessionHelper;
-
-    HarvesterHelper(ThreadDao threadDao, Clock clock, String vmId, WriterID writerId)
-    {
-        this(clock, vmId,
-             new ThreadStateHelper(threadDao, writerId, vmId),
-             new ThreadSessionHelper(threadDao, writerId, vmId, clock));
-    }
-
-    HarvesterHelper(Clock clock, String vmId,
-                    ThreadStateHelper stateHelper,
-                    ThreadSessionHelper sessionHelper)
-    {
-        this.vmId = vmId;
-        this.clock = clock;
-
-        this.stateHelper = stateHelper;
-        this.sessionHelper = sessionHelper;
-    }
-
-    synchronized void collectAndSaveThreadData(ThreadSession session,
-                                               ThreadMXBean collectorBean)
-    {
-        long timestamp = clock.getRealTimeMillis();
-
-        // this two can't be null, but the check is there to allow for
-        // nicer tests
-        long [] ids = collectorBean.getAllThreadIds();
-        if (ids == null) {
-            return;
-        }
-
-        // same as above
-        ThreadInfo[] threadInfos = collectorBean.getThreadInfo(ids, true, true);
-        if (threadInfos == null) {
-            return;
-        }
-
-        for (int i = 0; i < ids.length; i++) {
-
-            ThreadInfo beanInfo = threadInfos[i];
-
-            // state information
-            ThreadState state =
-                    stateHelper.createThreadState(beanInfo,
-                                                  session.getSessionID(),
-                                                  timestamp);
-            stateHelper.saveThreadState(state);
-        }
-    }
-
-    public ThreadSession createSession() {
-        return sessionHelper.createSession();
-    }
-
-    public void saveSession(ThreadSession sessionID) {
-        sessionHelper.saveSession(sessionID);
-    }
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/LockInfoBackend.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.Objects;
-
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.backend.VmListenerBackend;
-import com.redhat.thermostat.backend.VmUpdateListener;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.LockInfoDao;
-
-public class LockInfoBackend extends VmListenerBackend {
-
-    private LockInfoDao lockDao;
-
-    public LockInfoBackend(LockInfoDao lockDao, Version version,
-                VmStatusListenerRegistrar registrar, WriterID writerId) {
-        super("VM Lock Info Backend",
-              "Gathers lock statistics for a JVM",
-              "Red Hat, Inc.", version.getVersionNumber(), true, registrar, writerId);
-        this.lockDao = lockDao;
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_THREAD_GROUP + 10;
-    }
-
-    @Override
-    protected VmUpdateListener createVmListener(String writerId, String vmId, int pid) {
-        Objects.requireNonNull(lockDao);
-        return new LockInfoUpdater(lockDao, writerId, vmId);
-    }
-
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/LockInfoUpdater.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.backend.VmUpdate;
-import com.redhat.thermostat.backend.VmUpdateException;
-import com.redhat.thermostat.backend.VmUpdateListener;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.thread.dao.LockInfoDao;
-import com.redhat.thermostat.thread.model.LockInfo;
-
-public class LockInfoUpdater implements VmUpdateListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(LockInfoUpdater.class);
-
-    private final Clock clock;
-    private LockInfoDao lockDao;
-    private String writerId;
-    private String vmId;
-
-    public LockInfoUpdater(LockInfoDao lockDao, String writerId, String vmId) {
-        this(new SystemClock(), lockDao, writerId, vmId);
-    }
-
-    LockInfoUpdater(Clock clock, LockInfoDao lockDao, String writerId, String vmId) {
-        this.clock = clock;
-        this.lockDao = lockDao;
-        this.writerId = writerId;
-        this.vmId = vmId;
-    }
-
-    @Override
-    public void countersUpdated(VmUpdate update) {
-        long timeStamp = clock.getRealTimeMillis();
-
-        try {
-            long contendedLockAttempts = getCounter(update, "ContendedLockAttempts");
-            long deflations = getCounter(update, "Deflations");
-            long emptyNotifications = getCounter(update, "EmptyNotifications");
-            long failedSpins = getCounter(update, "FailedSpins");
-            long futileWakeups = getCounter(update, "FutileWakeups");
-            long inflations = getCounter(update, "Inflations");
-            long monExtant = getCounter(update, "MonExtant");
-            long monInCirculation = getCounter(update, "MonInCirculation");
-            long monScavenged = getCounter(update, "MonScavenged");
-            long notifications = getCounter(update, "Notifications");
-            long parks = getCounter(update, "Parks");
-            long privateA = getCounter(update, "PrivateA");
-            long privateB = getCounter(update, "PrivateB");
-            long slowEnter = getCounter(update, "SlowEnter");
-            long slowExit = getCounter(update, "SlowExit");
-            long slowNotify = getCounter(update, "SlowNotify");
-            long slowNotifyAll = getCounter(update, "SlowNotifyAll");
-            long successfulSpins = getCounter(update, "SuccessfulSpins");
-
-            LockInfo data = new LockInfo(timeStamp, writerId, vmId,
-                    contendedLockAttempts, deflations, emptyNotifications,
-                    failedSpins, futileWakeups, inflations,
-                    monExtant, monInCirculation, monScavenged,
-                    notifications, parks, privateA, privateB,
-                    slowEnter, slowExit, slowNotify, slowNotifyAll,
-                    successfulSpins);
-
-            lockDao.saveLockInfo(data);
-        } catch (VmUpdateException e) {
-            logger.log(Level.WARNING, "Unable to get counter", e);
-        }
-    }
-
-    private long getCounter(VmUpdate update, final String value) throws VmUpdateException {
-        final String PREFIX = "sun.rt._sync_";
-        try {
-            return update.getPerformanceCounterLong(PREFIX + value);
-        } catch (Exception e) {
-            logger.log(Level.WARNING, "Unable to read counter: " + PREFIX + value);
-            return LockInfo.UNKNOWN;
-        }
-    }
-
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadBackend.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.VmStatusListener;
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.agent.command.ReceiverRegistry;
-import com.redhat.thermostat.backend.BaseBackend;
-import com.redhat.thermostat.common.Pair;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class ThreadBackend extends BaseBackend implements VmStatusListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(ThreadBackend.class);
-
-    private final ReceiverRegistry registry;
-    private final ThreadHarvester harvester;
-
-    private boolean active = false;
-    private VmStatusListenerRegistrar vmListener;
-    private final List<Pair<String, Integer>> vmsToHarvestOnEnable = new ArrayList<>();
-
-    public ThreadBackend(Version version, VmStatusListenerRegistrar registrar, ReceiverRegistry registry, ThreadHarvester harvester) {
-        super("VM Thread Backend", "Gathers thread information about a JVM", "Red Hat, Inc", version.getVersionNumber());
-
-        this.vmListener = registrar;
-        this.registry = registry;
-        this.harvester = harvester;
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_THREAD_GROUP;
-    }
-
-    @Override
-    public boolean activate() {
-        if (active) {
-            return true;
-        }
-
-        // bring back all harvesters that were active
-        Iterator<Pair<String, Integer>> iter = vmsToHarvestOnEnable.iterator();
-        while (iter.hasNext()) {
-            Pair<String, Integer> saved = iter.next();
-            harvester.startHarvester(saved.getFirst(), saved.getSecond());
-            iter.remove();
-        }
-
-        vmListener.register(this);
-        registry.registerReceiver(harvester);
-
-        active = true;
-        return true;
-    }
-
-    @Override
-    public boolean deactivate() {
-        if (!active) {
-            return true;
-        }
-        vmListener.unregister(this);
-        registry.unregisterReceivers();
-
-        // stop all currently active harvesters
-        vmsToHarvestOnEnable.addAll(harvester.stopAndRemoveAllHarvesters());
-
-        active = false;
-        return true;
-    }
-
-    @Override
-    public boolean isActive() {
-        return active;
-    }
-
-    @Override
-    public void vmStatusChanged(Status newStatus, String vmId, int pid) {
-        switch (newStatus) {
-        case VM_STARTED: case VM_ACTIVE:
-            /* this is blocking */
-            harvester.addThreadHarvestingStatus(vmId);
-            break;
-        case VM_STOPPED:
-            harvester.stopHarvester(vmId);
-            break;
-        default:
-            logger.warning("Unexpected VM state: " + newStatus);
-        }
-    }
-
-}
-
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadCountBackend.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.Objects;
-
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.backend.VmListenerBackend;
-import com.redhat.thermostat.backend.VmUpdateListener;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-
-public class ThreadCountBackend extends VmListenerBackend {
-
-    private ThreadDao threadDao;
-
-    public ThreadCountBackend(ThreadDao threadDao, Version version,
-            VmStatusListenerRegistrar registrar, WriterID writerId) {
-        super("VM Thread Counting Backend",
-              "Gathers thread counts for a JVM",
-              "Red Hat, Inc.", version.getVersionNumber(), true, registrar, writerId);
-        this.threadDao = threadDao;
-    }
-
-    @Override
-    public int getOrderValue() {
-        return ORDER_THREAD_GROUP;
-    }
-
-    @Override
-    protected VmUpdateListener createVmListener(String writerId, String vmId, int pid) {
-        Objects.requireNonNull(threadDao);
-        return new ThreadCountUpdater(threadDao, writerId, vmId);
-    }
-
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadCountUpdater.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.backend.VmUpdate;
-import com.redhat.thermostat.backend.VmUpdateException;
-import com.redhat.thermostat.backend.VmUpdateListener;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSummary;
-
-public class ThreadCountUpdater implements VmUpdateListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(ThreadCountUpdater.class);
-
-    private final Clock clock;
-    private final ThreadSummaryHelper summaryHelper;
-
-    public ThreadCountUpdater(ThreadDao threadDao, String writerId, String vmId) {
-        this(new SystemClock(), new ThreadSummaryHelper(threadDao, writerId, vmId));
-    }
-
-    ThreadCountUpdater(Clock clock, ThreadSummaryHelper summaryHelper) {
-        this.clock = clock;
-        this.summaryHelper = summaryHelper;
-    }
-
-    @Override
-    public void countersUpdated(VmUpdate update) {
-        long timeStamp = clock.getRealTimeMillis();
-
-        try {
-            int liveThreads = (int) (long)
-                    update.getPerformanceCounterLong("java.threads.live");
-            int daemonThreads = (int) (long)
-                    update.getPerformanceCounterLong("java.threads.daemon");
-
-            ThreadSummary summary = summaryHelper.createThreadSummary(timeStamp, liveThreads, daemonThreads);
-
-            summaryHelper.saveSummary(summary);
-        } catch (VmUpdateException e) {
-            logger.log(Level.WARNING, "Unable to get counter", e);
-        }
-    }
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHarvester.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.command.RequestReceiver;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.Pair;
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.collector.HarvesterCommand;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadHarvestingStatus;
-
-public class ThreadHarvester implements RequestReceiver {
-
-    private static final Logger logger = LoggingUtils.getLogger(ThreadHarvester.class);
-    
-    private final ScheduledExecutorService executor;
-    final Map<String, Harvester> connectors;
-
-    private final Clock clock;
-    private final MXBeanConnectionPool connectionPool;
-    private final WriterID writerId;
-    private ThreadDao dao;
-
-    public ThreadHarvester(ScheduledExecutorService executor, MXBeanConnectionPool pool, WriterID writerID) {
-        this(executor, new SystemClock(), pool, writerID);
-    }
-    
-    public ThreadHarvester(ScheduledExecutorService executor, Clock clock, MXBeanConnectionPool connectionPool, WriterID writerId) {
-        this.executor = executor;
-        this.connectors = new HashMap<>();
-        this.clock = clock;
-        this.connectionPool = connectionPool;
-        this.writerId = writerId;
-    }
-    
-    /**
-     * Set the new implementation of thread DAO to be used as storage
-     * @param dao
-     */
-    public void setThreadDao(ThreadDao dao) {
-        // stop everything using the old implementation
-        List<Pair<String, Integer>> allSaved = new ArrayList<>();
-        if (this.dao != null) {
-            allSaved.addAll(stopAndRemoveAllHarvesters());
-        }
-
-        this.dao = dao;
-        // re-enable all existing harvesters
-        for (Pair<String, Integer> saved : allSaved) {
-            startHarvester(saved.getFirst(), saved.getSecond());
-        }
-    }
-    
-    @Override
-    public Response receive(Request request) {
-        if (!allRequirementsAvailable()) {
-            return new Response(ResponseType.ERROR);
-        }
-        
-        boolean result = false;
-        
-        String command = request.getParameter(HarvesterCommand.class.getName());
-        switch (HarvesterCommand.valueOf(command)) {
-        case START: {
-            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
-            String strPid = request.getParameter(HarvesterCommand.VM_PID.name());
-            try {
-                Integer pid = Integer.parseInt(strPid);
-                result = startHarvester(vmId, pid);
-            } catch (NumberFormatException e) {
-                logger.log(Level.WARNING, "Invalid pid: " + strPid, e);
-            }
-            break;
-        }   
-        case STOP: {
-            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
-            result = stopHarvester(vmId);
-            break;
-        }
-        case FIND_DEADLOCKS:
-            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
-            String strPid = request.getParameter(HarvesterCommand.VM_PID.name());
-            try {
-                Integer pid = Integer.parseInt(strPid);
-                result = findAndSaveDeadLockInformation(vmId, pid);
-            } catch (NumberFormatException e) {
-                logger.log(Level.WARNING, "Invalid pid: " + strPid, e);
-            }
-            break;
-        default:
-            result = false;
-            break;
-        }
-        
-        if (result) {
-            return new Response(ResponseType.OK);            
-        } else {
-            return new Response(ResponseType.ERROR);
-        }
-    }
-
-    /**
-     * Attaches and starts a harvester to the given PID.
-     * <p>
-     * Saves current harvesting status to storage.
-     */
-    public boolean startHarvester(String vmId, int pid) {
-        Harvester harvester = getHarvester(vmId, pid);
-        boolean result = harvester.start();
-        if (result) {
-            updateHarvestingStatus(vmId, result);
-        }
-        return result;
-    }
-
-    /**
-     * Stops and detaches a harvester from the given PID.
-     * <p>
-     * Saves current harvesting status to storage.
-     */
-    public boolean stopHarvester(String vmId) {
-        Harvester harvester = connectors.get(vmId);
-        boolean result = true;
-        if (harvester != null) {
-            result = harvester.stop();
-        }
-        updateHarvestingStatus(vmId, false);
-        return result;
-    }
-
-    /** Save current status to storage */
-    public void addThreadHarvestingStatus(String vmId) {
-        boolean harvesting = false;
-        Harvester harvester = connectors.get(vmId);
-        if (harvester != null) {
-            harvesting = harvester.isConnected();
-        }
-        updateHarvestingStatus(vmId, harvesting);
-    }
-
-    private void updateHarvestingStatus(String vmId, boolean harvesting) {
-        String wId = writerId.getWriterID();
-        ThreadHarvestingStatus status = new ThreadHarvestingStatus(wId);
-        status.setTimeStamp(clock.getRealTimeMillis());
-        status.setVmId(vmId);
-        status.setHarvesting(harvesting);
-        dao.saveHarvestingStatus(status);
-    }
-
-    private Harvester getHarvester(String vmId, int pid) {
-        Harvester harvester = connectors.get(vmId);
-        if (harvester == null) {
-            harvester = createHarvester(vmId, pid);
-            connectors.put(vmId, harvester);
-        }
-        
-        return harvester;
-    }
-
-    Harvester createHarvester(String vmId, int pid) {
-        return new Harvester(dao, executor, vmId, pid, connectionPool, writerId);
-    }
-
-    /**
-     * Returns a list of VM ID, PID pairs which can be used to resume
-     * the harvesters at a later time.
-     */
-    public List<Pair<String, Integer>> stopAndRemoveAllHarvesters() {
-        List<Pair<String, Integer>> result = new ArrayList<>();
-        Iterator<Entry<String, Harvester>> iter = connectors.entrySet().iterator();
-        while (iter.hasNext()) {
-            Entry<String, Harvester> entry = iter.next();
-            String vmId = entry.getKey();
-            Harvester harvester = entry.getValue();
-            harvester.stop();
-            updateHarvestingStatus(vmId, false);
-            iter.remove();
-            result.add(new Pair<>(vmId, harvester.getPid()));
-        }
-        return result;
-    }
-
-    private boolean allRequirementsAvailable() {
-        return dao != null;
-    }
-
-    public boolean findAndSaveDeadLockInformation(String vmId, int pid) {
-        Harvester harvester = getHarvester(vmId, pid);
-        boolean result = harvester.saveDeadLockData();
-        return result;
-    }
-    
-}
-
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSessionHelper.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.SessionID;
-import com.redhat.thermostat.thread.model.ThreadSession;
-
-/**
- *
- */
-class ThreadSessionHelper {
-    private final ThreadDao threadDao;
-    private final WriterID writerId;
-    private final String vmId;
-    private final Clock clock;
-
-    public ThreadSessionHelper(ThreadDao threadDao, WriterID writerId, String vmId, Clock clock) {
-
-        this.threadDao = threadDao;
-        this.writerId = writerId;
-        this.vmId = vmId;
-        this.clock = clock;
-    }
-
-    ThreadSession createSession() {
-        ThreadSession session = new ThreadSession();
-
-        session.setSession(new SessionID().get());
-        session.setTimeStamp(clock.getRealTimeMillis());
-        session.setVmId(vmId);
-        session.setAgentId(writerId.getWriterID());
-
-        return session;
-    }
-
-    void saveSession(ThreadSession session) {
-        threadDao.saveSession(session);
-    }
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadStateHelper.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.SessionID;
-import com.redhat.thermostat.thread.model.ThreadState;
-import java.lang.management.ThreadInfo;
-
-public class ThreadStateHelper {
-
-    private ThreadDao threadDao;
-    private final WriterID writerId;
-    private final String vmId;
-
-    public ThreadStateHelper(ThreadDao threadDao,
-                             WriterID writerId, String vmId)
-    {
-        this.threadDao = threadDao;
-        this.writerId = writerId;
-        this.vmId = vmId;
-    }
-
-    public ThreadState createThreadState(ThreadInfo beanInfo,
-                                         SessionID sessionID,
-                                         long timestamp)
-    {
-        ThreadState state = new ThreadState(writerId.getWriterID());
-
-        // generic information
-        state.setTimeStamp(timestamp);
-        state.setSession(sessionID.get());
-        state.setVmId(vmId);
-
-        // ids
-        state.setName(beanInfo.getThreadName());
-        state.setId(beanInfo.getThreadId());
-
-        // execution information
-        state.setState(beanInfo.getThreadState().name());
-        state.setSuspended(beanInfo.isSuspended());
-        state.setInNative(beanInfo.isInNative());
-
-        // synchronization statistics
-        state.setBlockedCount(beanInfo.getBlockedCount());
-        state.setBlockedTime(beanInfo.getBlockedTime());
-        state.setWaitedCount(beanInfo.getWaitedCount());
-        state.setWaitedTime(beanInfo.getWaitedTime());
-
-        // TODO: lock information
-
-        return state;
-    }
-
-    public void saveThreadState(ThreadState thread) {
-        threadDao.addThreadState(thread);
-    }
-}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelper.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSummary;
-
-class ThreadSummaryHelper {
-
-    private String vmId;
-    private String writerId;
-    private ThreadDao threadDao;
-
-    ThreadSummaryHelper(ThreadDao threadDao, String writerId, String vmId) {
-        this.vmId = vmId;
-        this.writerId = writerId;
-        this.threadDao = threadDao;
-    }
-
-    ThreadSummary createThreadSummary(long timestamp, long liveThreads, long daemonThreads) {
-        ThreadSummary summary = new ThreadSummary(writerId);
-
-        summary.setCurrentLiveThreads(liveThreads);
-        summary.setCurrentDaemonThreads(daemonThreads);
-        summary.setTimeStamp(timestamp);
-        summary.setVmId(vmId);
-
-        return summary;
-    }
-
-    public void saveSummary(ThreadSummary summary) {
-        threadDao.saveSummary(summary);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.LockInfoDao;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+
+public class Activator implements BundleActivator {
+    
+    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(24);
+
+    private MultipleServiceTracker connectionPoolTracker;
+    private ServiceTracker threadDaoTracker;
+    private ServiceRegistration backendRegistration;
+
+    private ReceiverRegistry registry;
+    private ThreadHarvester harvester;
+    private ThreadBackend backend;
+
+    private MultipleServiceTracker threadCountTracker;
+
+    private MultipleServiceTracker lockInfoTracker;
+    
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        final Version VERSION = new Version(context.getBundle());
+        final VmStatusListenerRegistrar VM_STATUS_REGISTRAR
+            = new VmStatusListenerRegistrar(context);
+
+        Class<?>[] threadCountDeps = new Class<?>[] {
+                WriterID.class,
+                ThreadDao.class,
+        };
+        threadCountTracker = new MultipleServiceTracker(context, threadCountDeps, new Action() {
+
+            private ServiceRegistration<Backend> registration;
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
+                ThreadDao dao = (ThreadDao) services.get(ThreadDao.class.getName());
+                Objects.requireNonNull(dao);
+                ThreadCountBackend threadCountBackend = new ThreadCountBackend(dao, VERSION, VM_STATUS_REGISTRAR, writerId);
+                registration = context.registerService(Backend.class, threadCountBackend, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                registration.unregister();
+                registration = null;
+            }
+        });
+        threadCountTracker.open();
+
+        Class<?>[] lockInfoDeps = new Class<?>[] {
+            WriterID.class,
+            LockInfoDao.class,
+        };
+        lockInfoTracker = new MultipleServiceTracker(context, lockInfoDeps, new Action() {
+
+            private ServiceRegistration<Backend> registration;
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
+                LockInfoDao dao = (LockInfoDao) services.get(LockInfoDao.class.getName());
+                Objects.requireNonNull(dao);
+                LockInfoBackend lockInfoBackend = new LockInfoBackend(dao, VERSION, VM_STATUS_REGISTRAR, writerId);
+                registration = context.registerService(Backend.class, lockInfoBackend, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                registration.unregister();
+                registration = null;
+            }
+        });
+        lockInfoTracker.open();
+
+        Class<?>[] deps = new Class<?>[] {
+                MXBeanConnectionPool.class,
+                WriterID.class,
+        };
+        connectionPoolTracker = new MultipleServiceTracker(context, deps, new Action() {
+            
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                MXBeanConnectionPool pool = (MXBeanConnectionPool) services.get(MXBeanConnectionPool.class.getName());
+                WriterID writerId = (WriterID) services.get(WriterID.class.getName());
+                harvester = new ThreadHarvester(executor, pool, writerId);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                harvester = null;
+            }
+        });
+        connectionPoolTracker.open();
+
+        registry = new ReceiverRegistry(context);
+
+        /*
+         * dont register anything just yet, let the backend handle the
+         * registration, deregistration it when it's activated or deactivated
+         */
+
+        backend = new ThreadBackend(VERSION, VM_STATUS_REGISTRAR, registry, harvester);
+        backendRegistration = context.registerService(Backend.class, backend, null);
+
+        threadDaoTracker = new ServiceTracker(context, ThreadDao.class.getName(), null) {
+            @Override
+            public Object addingService(ServiceReference reference) {
+                ThreadDao threadDao = (ThreadDao) context.getService(reference);
+                harvester.setThreadDao(threadDao);
+                return super.addingService(reference);
+            }
+
+            @Override
+            public void removedService(ServiceReference reference, Object service) {
+                if (harvester != null) {
+                    harvester.setThreadDao(null);
+                }
+                context.ungetService(reference);
+                super.removedService(reference, service);
+            }
+        };
+        threadDaoTracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        if (backend.isActive()) {
+            backend.deactivate();
+        }
+
+        threadCountTracker.close();
+        lockInfoTracker.close();
+
+        backendRegistration.unregister();
+
+        connectionPoolTracker.close();
+        threadDaoTracker.close();
+
+        if (executor != null) {
+            executor.shutdown();
+        }        
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/DeadlockHelper.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.VmDeadLockData;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+/**
+ */
+public class DeadlockHelper {
+
+    private final ThreadDao threadDao;
+    private final SystemClock systemClock;
+    private final String vmId;
+    private final WriterID id;
+
+    public DeadlockHelper(ThreadDao threadDao, SystemClock systemClock,
+                          String vmId, WriterID id)
+    {
+        this.threadDao = threadDao;
+        this.systemClock = systemClock;
+        this.vmId = vmId;
+        this.id = id;
+    }
+
+    void saveDeadlockInformation(ThreadMXBean collector) {
+        String description = null;
+        long timeStamp = systemClock.getRealTimeMillis();
+        long[] ids = collector.findDeadlockedThreads();
+        if (ids == null) {
+            description = VmDeadLockData.NO_DEADLOCK;
+        } else {
+            ThreadInfo[] infos = collector.getThreadInfo(ids, true, true);
+            StringBuilder descriptionBuilder = new StringBuilder();
+            for (ThreadInfo info : infos) {
+                descriptionBuilder.append(info.toString()).append("\n");
+            }
+            description = descriptionBuilder.toString();
+        }
+
+        String wId = id.getWriterID();
+        VmDeadLockData data = new VmDeadLockData(wId);
+        data.setTimeStamp(timeStamp);
+        data.setVmId(vmId);
+        data.setDeadLockDescription(description);
+
+        threadDao.saveDeadLockStatus(data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/Harvester.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionException;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSession;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.management.MalformedObjectNameException;
+
+@SuppressWarnings("restriction")
+class Harvester {
+
+    static final long DEFAULT_INITIAL_DELAY = 0;
+    static final long DEFAULT_PERIOD = 250;
+    static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;
+
+    private static final Logger logger = LoggingUtils.getLogger(Harvester.class);
+
+    private final ScheduledExecutorService threadPool;
+    private final int pid;
+
+    private boolean isConnected;
+    private ScheduledFuture<?> harvester;
+    private MXBeanConnection connection;
+    private ThreadMXBean collectorBean;
+
+    private HarvesterHelper harvesterHelper;
+    private final MXBeanConnectionPool connectionPool;
+    private final DeadlockHelper deadlockHelper;
+
+    public Harvester(ThreadDao threadDao, ScheduledExecutorService threadPool,
+                     String vmId, int pid, MXBeanConnectionPool connectionPool,
+                     WriterID writerId)
+    {
+        this(pid, threadPool, connectionPool,
+             new HarvesterHelper(threadDao, new SystemClock(), vmId, writerId),
+             new DeadlockHelper(threadDao, new SystemClock(), vmId, writerId));
+    }
+
+    Harvester(int pid, ScheduledExecutorService threadPool,
+              MXBeanConnectionPool connectionPool,
+              HarvesterHelper harvesterHelper,
+              DeadlockHelper deadlockHelper)
+    {
+        this.pid = pid;
+        this.threadPool = threadPool;
+        this.connectionPool = connectionPool;
+        this.harvesterHelper = harvesterHelper;
+        this.deadlockHelper = deadlockHelper;
+    }
+    
+    synchronized boolean start() {
+        if (isConnected()) {
+            return true;
+        }
+
+        if (!connect()) {
+            return false;
+        }
+
+        harvester = threadPool.scheduleAtFixedRate(new HarvesterAction(true),
+                                                   DEFAULT_INITIAL_DELAY,
+                                                   DEFAULT_PERIOD,
+                                                   DEFAULT_TIME_UNIT);
+
+        return isConnected();
+    }
+
+    private synchronized boolean connect() {
+        try {
+            connection = connectionPool.acquire(pid);
+        } catch (MXBeanConnectionException ex) {
+            logger.log(Level.SEVERE, "can't connect", ex);
+            return false;
+        }
+
+        setConnected(true);
+        return true;
+    }
+
+    synchronized boolean isConnected() {
+        return isConnected;
+    }
+
+    synchronized void setConnected(boolean isConnected) {
+        this.isConnected = isConnected;
+    }
+
+    synchronized boolean stop() {
+        if (!isConnected()) {
+            return true;
+        }
+        
+        harvester.cancel(false);
+        
+        return disconnect();
+    }
+    
+    int getPid() {
+        return pid;
+    }
+
+    private boolean disconnect() {
+        if (collectorBean != null) {
+            collectorBean = null;
+        }
+        
+        setConnected(false);
+
+        try {
+            connectionPool.release(pid, connection);
+        } catch (MXBeanConnectionException ex) {
+            logger.log(Level.SEVERE, "can't disconnect", ex);
+            return false;
+        }
+
+        return true;
+    }
+    
+    ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
+
+        if (connection == null) {
+            logger.log(Level.WARNING, "MXBeanConnection is null");
+            return null;
+        }
+
+        ThreadMXBean bean = null;
+        try {
+            bean = connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
+                                          com.sun.management.ThreadMXBean.class);
+        } catch (MalformedObjectNameException e) {
+            logger.log(Level.FINE,
+                       "com.sun.management.ThreadMXBean.class not " +
+                       "available for " +
+                       ManagementFactory.THREAD_MXBEAN_NAME, e);
+        }
+
+        if (bean == null) {
+            try {
+                bean = connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
+                                              ThreadMXBean.class);
+            } catch (MalformedObjectNameException e) {
+                logger.log(Level.WARNING,
+                           "java.lang.management.ThreadMXBean.class not " +
+                           "available for " +
+                           ManagementFactory.THREAD_MXBEAN_NAME, e);
+            }
+        }
+
+        return bean;
+    }
+
+    private class HarvesterAction implements Runnable {
+
+        private boolean newSession;
+        private ThreadSession session;
+
+        private HarvesterAction(boolean newSession) {
+            this.newSession = newSession;
+        }
+
+        @Override
+        public void run() {
+            if (collectorBean == null) {
+                collectorBean = getDataCollectorBean(connection);
+            }
+
+            // FIXME: should we do something in case this is still null?
+            // it basically means JMX is not available at this point...
+            if (collectorBean != null) {
+
+                // try to set some properties we're going to need
+                try {
+                    if (collectorBean.isCurrentThreadCpuTimeSupported() &&
+                        !collectorBean.isThreadCpuTimeEnabled())
+                    {
+                        collectorBean.setThreadCpuTimeEnabled(true);
+                    }
+
+                    if (collectorBean.isThreadContentionMonitoringSupported() &&
+                        !collectorBean.isThreadContentionMonitoringEnabled())
+                    {
+                        collectorBean.setThreadContentionMonitoringEnabled(true);
+                    }
+                } catch (UnsupportedOperationException ignore) {}
+
+                if (newSession) {
+                    session = harvesterHelper.createSession();
+                    harvesterHelper.saveSession(session);
+
+                    newSession = false;
+                }
+
+                harvesterHelper.collectAndSaveThreadData(session, collectorBean);
+
+            } else {
+                logger.log(Level.WARNING, "ThreadMXBean is null, is JMX available?");
+            }
+        }
+    }
+
+    public boolean saveDeadLockData() {
+        boolean disconnectAtEnd = false;
+        if (!isConnected()) {
+            disconnectAtEnd = true;
+
+            connect();
+        }
+
+        if (collectorBean == null) {
+            collectorBean = getDataCollectorBean(connection);
+        }
+
+        if (collectorBean != null) {
+            deadlockHelper.saveDeadlockInformation(collectorBean);
+        }
+
+        if (disconnectAtEnd) {
+            disconnect();
+        }
+
+        return true;
+    }
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/HarvesterHelper.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSession;
+import com.redhat.thermostat.thread.model.ThreadState;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+/*
+ */
+class HarvesterHelper {
+
+    private Clock clock;
+    private String vmId;
+
+    private ThreadStateHelper stateHelper;
+    private ThreadSessionHelper sessionHelper;
+
+    HarvesterHelper(ThreadDao threadDao, Clock clock, String vmId, WriterID writerId)
+    {
+        this(clock, vmId,
+             new ThreadStateHelper(threadDao, writerId, vmId),
+             new ThreadSessionHelper(threadDao, writerId, vmId, clock));
+    }
+
+    HarvesterHelper(Clock clock, String vmId,
+                    ThreadStateHelper stateHelper,
+                    ThreadSessionHelper sessionHelper)
+    {
+        this.vmId = vmId;
+        this.clock = clock;
+
+        this.stateHelper = stateHelper;
+        this.sessionHelper = sessionHelper;
+    }
+
+    synchronized void collectAndSaveThreadData(ThreadSession session,
+                                               ThreadMXBean collectorBean)
+    {
+        long timestamp = clock.getRealTimeMillis();
+
+        // this two can't be null, but the check is there to allow for
+        // nicer tests
+        long [] ids = collectorBean.getAllThreadIds();
+        if (ids == null) {
+            return;
+        }
+
+        // same as above
+        ThreadInfo[] threadInfos = collectorBean.getThreadInfo(ids, true, true);
+        if (threadInfos == null) {
+            return;
+        }
+
+        for (int i = 0; i < ids.length; i++) {
+
+            ThreadInfo beanInfo = threadInfos[i];
+
+            // state information
+            ThreadState state =
+                    stateHelper.createThreadState(beanInfo,
+                                                  session.getSessionID(),
+                                                  timestamp);
+            stateHelper.saveThreadState(state);
+        }
+    }
+
+    public ThreadSession createSession() {
+        return sessionHelper.createSession();
+    }
+
+    public void saveSession(ThreadSession sessionID) {
+        sessionHelper.saveSession(sessionID);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/LockInfoBackend.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.Objects;
+
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.backend.VmListenerBackend;
+import com.redhat.thermostat.backend.VmUpdateListener;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.LockInfoDao;
+
+public class LockInfoBackend extends VmListenerBackend {
+
+    private LockInfoDao lockDao;
+
+    public LockInfoBackend(LockInfoDao lockDao, Version version,
+                VmStatusListenerRegistrar registrar, WriterID writerId) {
+        super("VM Lock Info Backend",
+              "Gathers lock statistics for a JVM",
+              "Red Hat, Inc.", version.getVersionNumber(), true, registrar, writerId);
+        this.lockDao = lockDao;
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_THREAD_GROUP + 10;
+    }
+
+    @Override
+    protected VmUpdateListener createVmListener(String writerId, String vmId, int pid) {
+        Objects.requireNonNull(lockDao);
+        return new LockInfoUpdater(lockDao, writerId, vmId);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/LockInfoUpdater.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.backend.VmUpdate;
+import com.redhat.thermostat.backend.VmUpdateException;
+import com.redhat.thermostat.backend.VmUpdateListener;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.thread.dao.LockInfoDao;
+import com.redhat.thermostat.thread.model.LockInfo;
+
+public class LockInfoUpdater implements VmUpdateListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(LockInfoUpdater.class);
+
+    private final Clock clock;
+    private LockInfoDao lockDao;
+    private String writerId;
+    private String vmId;
+
+    public LockInfoUpdater(LockInfoDao lockDao, String writerId, String vmId) {
+        this(new SystemClock(), lockDao, writerId, vmId);
+    }
+
+    LockInfoUpdater(Clock clock, LockInfoDao lockDao, String writerId, String vmId) {
+        this.clock = clock;
+        this.lockDao = lockDao;
+        this.writerId = writerId;
+        this.vmId = vmId;
+    }
+
+    @Override
+    public void countersUpdated(VmUpdate update) {
+        long timeStamp = clock.getRealTimeMillis();
+
+        try {
+            long contendedLockAttempts = getCounter(update, "ContendedLockAttempts");
+            long deflations = getCounter(update, "Deflations");
+            long emptyNotifications = getCounter(update, "EmptyNotifications");
+            long failedSpins = getCounter(update, "FailedSpins");
+            long futileWakeups = getCounter(update, "FutileWakeups");
+            long inflations = getCounter(update, "Inflations");
+            long monExtant = getCounter(update, "MonExtant");
+            long monInCirculation = getCounter(update, "MonInCirculation");
+            long monScavenged = getCounter(update, "MonScavenged");
+            long notifications = getCounter(update, "Notifications");
+            long parks = getCounter(update, "Parks");
+            long privateA = getCounter(update, "PrivateA");
+            long privateB = getCounter(update, "PrivateB");
+            long slowEnter = getCounter(update, "SlowEnter");
+            long slowExit = getCounter(update, "SlowExit");
+            long slowNotify = getCounter(update, "SlowNotify");
+            long slowNotifyAll = getCounter(update, "SlowNotifyAll");
+            long successfulSpins = getCounter(update, "SuccessfulSpins");
+
+            LockInfo data = new LockInfo(timeStamp, writerId, vmId,
+                    contendedLockAttempts, deflations, emptyNotifications,
+                    failedSpins, futileWakeups, inflations,
+                    monExtant, monInCirculation, monScavenged,
+                    notifications, parks, privateA, privateB,
+                    slowEnter, slowExit, slowNotify, slowNotifyAll,
+                    successfulSpins);
+
+            lockDao.saveLockInfo(data);
+        } catch (VmUpdateException e) {
+            logger.log(Level.WARNING, "Unable to get counter", e);
+        }
+    }
+
+    private long getCounter(VmUpdate update, final String value) throws VmUpdateException {
+        final String PREFIX = "sun.rt._sync_";
+        try {
+            return update.getPerformanceCounterLong(PREFIX + value);
+        } catch (Exception e) {
+            logger.log(Level.WARNING, "Unable to read counter: " + PREFIX + value);
+            return LockInfo.UNKNOWN;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadBackend.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.VmStatusListener;
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
+import com.redhat.thermostat.backend.BaseBackend;
+import com.redhat.thermostat.common.Pair;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class ThreadBackend extends BaseBackend implements VmStatusListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(ThreadBackend.class);
+
+    private final ReceiverRegistry registry;
+    private final ThreadHarvester harvester;
+
+    private boolean active = false;
+    private VmStatusListenerRegistrar vmListener;
+    private final List<Pair<String, Integer>> vmsToHarvestOnEnable = new ArrayList<>();
+
+    public ThreadBackend(Version version, VmStatusListenerRegistrar registrar, ReceiverRegistry registry, ThreadHarvester harvester) {
+        super("VM Thread Backend", "Gathers thread information about a JVM", "Red Hat, Inc", version.getVersionNumber());
+
+        this.vmListener = registrar;
+        this.registry = registry;
+        this.harvester = harvester;
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_THREAD_GROUP;
+    }
+
+    @Override
+    public boolean activate() {
+        if (active) {
+            return true;
+        }
+
+        // bring back all harvesters that were active
+        Iterator<Pair<String, Integer>> iter = vmsToHarvestOnEnable.iterator();
+        while (iter.hasNext()) {
+            Pair<String, Integer> saved = iter.next();
+            harvester.startHarvester(saved.getFirst(), saved.getSecond());
+            iter.remove();
+        }
+
+        vmListener.register(this);
+        registry.registerReceiver(harvester);
+
+        active = true;
+        return true;
+    }
+
+    @Override
+    public boolean deactivate() {
+        if (!active) {
+            return true;
+        }
+        vmListener.unregister(this);
+        registry.unregisterReceivers();
+
+        // stop all currently active harvesters
+        vmsToHarvestOnEnable.addAll(harvester.stopAndRemoveAllHarvesters());
+
+        active = false;
+        return true;
+    }
+
+    @Override
+    public boolean isActive() {
+        return active;
+    }
+
+    @Override
+    public void vmStatusChanged(Status newStatus, String vmId, int pid) {
+        switch (newStatus) {
+        case VM_STARTED: case VM_ACTIVE:
+            /* this is blocking */
+            harvester.addThreadHarvestingStatus(vmId);
+            break;
+        case VM_STOPPED:
+            harvester.stopHarvester(vmId);
+            break;
+        default:
+            logger.warning("Unexpected VM state: " + newStatus);
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountBackend.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.Objects;
+
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.backend.VmListenerBackend;
+import com.redhat.thermostat.backend.VmUpdateListener;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+
+public class ThreadCountBackend extends VmListenerBackend {
+
+    private ThreadDao threadDao;
+
+    public ThreadCountBackend(ThreadDao threadDao, Version version,
+            VmStatusListenerRegistrar registrar, WriterID writerId) {
+        super("VM Thread Counting Backend",
+              "Gathers thread counts for a JVM",
+              "Red Hat, Inc.", version.getVersionNumber(), true, registrar, writerId);
+        this.threadDao = threadDao;
+    }
+
+    @Override
+    public int getOrderValue() {
+        return ORDER_THREAD_GROUP;
+    }
+
+    @Override
+    protected VmUpdateListener createVmListener(String writerId, String vmId, int pid) {
+        Objects.requireNonNull(threadDao);
+        return new ThreadCountUpdater(threadDao, writerId, vmId);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountUpdater.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.backend.VmUpdate;
+import com.redhat.thermostat.backend.VmUpdateException;
+import com.redhat.thermostat.backend.VmUpdateListener;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSummary;
+
+public class ThreadCountUpdater implements VmUpdateListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(ThreadCountUpdater.class);
+
+    private final Clock clock;
+    private final ThreadSummaryHelper summaryHelper;
+
+    public ThreadCountUpdater(ThreadDao threadDao, String writerId, String vmId) {
+        this(new SystemClock(), new ThreadSummaryHelper(threadDao, writerId, vmId));
+    }
+
+    ThreadCountUpdater(Clock clock, ThreadSummaryHelper summaryHelper) {
+        this.clock = clock;
+        this.summaryHelper = summaryHelper;
+    }
+
+    @Override
+    public void countersUpdated(VmUpdate update) {
+        long timeStamp = clock.getRealTimeMillis();
+
+        try {
+            int liveThreads = (int) (long)
+                    update.getPerformanceCounterLong("java.threads.live");
+            int daemonThreads = (int) (long)
+                    update.getPerformanceCounterLong("java.threads.daemon");
+
+            ThreadSummary summary = summaryHelper.createThreadSummary(timeStamp, liveThreads, daemonThreads);
+
+            summaryHelper.saveSummary(summary);
+        } catch (VmUpdateException e) {
+            logger.log(Level.WARNING, "Unable to get counter", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadHarvester.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.command.RequestReceiver;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.Pair;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.collector.HarvesterCommand;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadHarvestingStatus;
+
+public class ThreadHarvester implements RequestReceiver {
+
+    private static final Logger logger = LoggingUtils.getLogger(ThreadHarvester.class);
+    
+    private final ScheduledExecutorService executor;
+    final Map<String, Harvester> connectors;
+
+    private final Clock clock;
+    private final MXBeanConnectionPool connectionPool;
+    private final WriterID writerId;
+    private ThreadDao dao;
+
+    public ThreadHarvester(ScheduledExecutorService executor, MXBeanConnectionPool pool, WriterID writerID) {
+        this(executor, new SystemClock(), pool, writerID);
+    }
+    
+    public ThreadHarvester(ScheduledExecutorService executor, Clock clock, MXBeanConnectionPool connectionPool, WriterID writerId) {
+        this.executor = executor;
+        this.connectors = new HashMap<>();
+        this.clock = clock;
+        this.connectionPool = connectionPool;
+        this.writerId = writerId;
+    }
+    
+    /**
+     * Set the new implementation of thread DAO to be used as storage
+     * @param dao
+     */
+    public void setThreadDao(ThreadDao dao) {
+        // stop everything using the old implementation
+        List<Pair<String, Integer>> allSaved = new ArrayList<>();
+        if (this.dao != null) {
+            allSaved.addAll(stopAndRemoveAllHarvesters());
+        }
+
+        this.dao = dao;
+        // re-enable all existing harvesters
+        for (Pair<String, Integer> saved : allSaved) {
+            startHarvester(saved.getFirst(), saved.getSecond());
+        }
+    }
+    
+    @Override
+    public Response receive(Request request) {
+        if (!allRequirementsAvailable()) {
+            return new Response(ResponseType.ERROR);
+        }
+        
+        boolean result = false;
+        
+        String command = request.getParameter(HarvesterCommand.class.getName());
+        switch (HarvesterCommand.valueOf(command)) {
+        case START: {
+            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
+            String strPid = request.getParameter(HarvesterCommand.VM_PID.name());
+            try {
+                Integer pid = Integer.parseInt(strPid);
+                result = startHarvester(vmId, pid);
+            } catch (NumberFormatException e) {
+                logger.log(Level.WARNING, "Invalid pid: " + strPid, e);
+            }
+            break;
+        }   
+        case STOP: {
+            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
+            result = stopHarvester(vmId);
+            break;
+        }
+        case FIND_DEADLOCKS:
+            String vmId = request.getParameter(HarvesterCommand.VM_ID.name());
+            String strPid = request.getParameter(HarvesterCommand.VM_PID.name());
+            try {
+                Integer pid = Integer.parseInt(strPid);
+                result = findAndSaveDeadLockInformation(vmId, pid);
+            } catch (NumberFormatException e) {
+                logger.log(Level.WARNING, "Invalid pid: " + strPid, e);
+            }
+            break;
+        default:
+            result = false;
+            break;
+        }
+        
+        if (result) {
+            return new Response(ResponseType.OK);            
+        } else {
+            return new Response(ResponseType.ERROR);
+        }
+    }
+
+    /**
+     * Attaches and starts a harvester to the given PID.
+     * <p>
+     * Saves current harvesting status to storage.
+     */
+    public boolean startHarvester(String vmId, int pid) {
+        Harvester harvester = getHarvester(vmId, pid);
+        boolean result = harvester.start();
+        if (result) {
+            updateHarvestingStatus(vmId, result);
+        }
+        return result;
+    }
+
+    /**
+     * Stops and detaches a harvester from the given PID.
+     * <p>
+     * Saves current harvesting status to storage.
+     */
+    public boolean stopHarvester(String vmId) {
+        Harvester harvester = connectors.get(vmId);
+        boolean result = true;
+        if (harvester != null) {
+            result = harvester.stop();
+        }
+        updateHarvestingStatus(vmId, false);
+        return result;
+    }
+
+    /** Save current status to storage */
+    public void addThreadHarvestingStatus(String vmId) {
+        boolean harvesting = false;
+        Harvester harvester = connectors.get(vmId);
+        if (harvester != null) {
+            harvesting = harvester.isConnected();
+        }
+        updateHarvestingStatus(vmId, harvesting);
+    }
+
+    private void updateHarvestingStatus(String vmId, boolean harvesting) {
+        String wId = writerId.getWriterID();
+        ThreadHarvestingStatus status = new ThreadHarvestingStatus(wId);
+        status.setTimeStamp(clock.getRealTimeMillis());
+        status.setVmId(vmId);
+        status.setHarvesting(harvesting);
+        dao.saveHarvestingStatus(status);
+    }
+
+    private Harvester getHarvester(String vmId, int pid) {
+        Harvester harvester = connectors.get(vmId);
+        if (harvester == null) {
+            harvester = createHarvester(vmId, pid);
+            connectors.put(vmId, harvester);
+        }
+        
+        return harvester;
+    }
+
+    Harvester createHarvester(String vmId, int pid) {
+        return new Harvester(dao, executor, vmId, pid, connectionPool, writerId);
+    }
+
+    /**
+     * Returns a list of VM ID, PID pairs which can be used to resume
+     * the harvesters at a later time.
+     */
+    public List<Pair<String, Integer>> stopAndRemoveAllHarvesters() {
+        List<Pair<String, Integer>> result = new ArrayList<>();
+        Iterator<Entry<String, Harvester>> iter = connectors.entrySet().iterator();
+        while (iter.hasNext()) {
+            Entry<String, Harvester> entry = iter.next();
+            String vmId = entry.getKey();
+            Harvester harvester = entry.getValue();
+            harvester.stop();
+            updateHarvestingStatus(vmId, false);
+            iter.remove();
+            result.add(new Pair<>(vmId, harvester.getPid()));
+        }
+        return result;
+    }
+
+    private boolean allRequirementsAvailable() {
+        return dao != null;
+    }
+
+    public boolean findAndSaveDeadLockInformation(String vmId, int pid) {
+        Harvester harvester = getHarvester(vmId, pid);
+        boolean result = harvester.saveDeadLockData();
+        return result;
+    }
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadSessionHelper.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.SessionID;
+import com.redhat.thermostat.thread.model.ThreadSession;
+
+/**
+ *
+ */
+class ThreadSessionHelper {
+    private final ThreadDao threadDao;
+    private final WriterID writerId;
+    private final String vmId;
+    private final Clock clock;
+
+    public ThreadSessionHelper(ThreadDao threadDao, WriterID writerId, String vmId, Clock clock) {
+
+        this.threadDao = threadDao;
+        this.writerId = writerId;
+        this.vmId = vmId;
+        this.clock = clock;
+    }
+
+    ThreadSession createSession() {
+        ThreadSession session = new ThreadSession();
+
+        session.setSession(new SessionID().get());
+        session.setTimeStamp(clock.getRealTimeMillis());
+        session.setVmId(vmId);
+        session.setAgentId(writerId.getWriterID());
+
+        return session;
+    }
+
+    void saveSession(ThreadSession session) {
+        threadDao.saveSession(session);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadStateHelper.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.SessionID;
+import com.redhat.thermostat.thread.model.ThreadState;
+import java.lang.management.ThreadInfo;
+
+public class ThreadStateHelper {
+
+    private ThreadDao threadDao;
+    private final WriterID writerId;
+    private final String vmId;
+
+    public ThreadStateHelper(ThreadDao threadDao,
+                             WriterID writerId, String vmId)
+    {
+        this.threadDao = threadDao;
+        this.writerId = writerId;
+        this.vmId = vmId;
+    }
+
+    public ThreadState createThreadState(ThreadInfo beanInfo,
+                                         SessionID sessionID,
+                                         long timestamp)
+    {
+        ThreadState state = new ThreadState(writerId.getWriterID());
+
+        // generic information
+        state.setTimeStamp(timestamp);
+        state.setSession(sessionID.get());
+        state.setVmId(vmId);
+
+        // ids
+        state.setName(beanInfo.getThreadName());
+        state.setId(beanInfo.getThreadId());
+
+        // execution information
+        state.setState(beanInfo.getThreadState().name());
+        state.setSuspended(beanInfo.isSuspended());
+        state.setInNative(beanInfo.isInNative());
+
+        // synchronization statistics
+        state.setBlockedCount(beanInfo.getBlockedCount());
+        state.setBlockedTime(beanInfo.getBlockedTime());
+        state.setWaitedCount(beanInfo.getWaitedCount());
+        state.setWaitedTime(beanInfo.getWaitedTime());
+
+        // TODO: lock information
+
+        return state;
+    }
+
+    public void saveThreadState(ThreadState thread) {
+        threadDao.addThreadState(thread);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/internal/ThreadSummaryHelper.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSummary;
+
+class ThreadSummaryHelper {
+
+    private String vmId;
+    private String writerId;
+    private ThreadDao threadDao;
+
+    ThreadSummaryHelper(ThreadDao threadDao, String writerId, String vmId) {
+        this.vmId = vmId;
+        this.writerId = writerId;
+        this.threadDao = threadDao;
+    }
+
+    ThreadSummary createThreadSummary(long timestamp, long liveThreads, long daemonThreads) {
+        ThreadSummary summary = new ThreadSummary(writerId);
+
+        summary.setCurrentLiveThreads(liveThreads);
+        summary.setCurrentDaemonThreads(daemonThreads);
+        summary.setTimeStamp(timestamp);
+        summary.setVmId(vmId);
+
+        return summary;
+    }
+
+    public void saveSummary(ThreadSummary summary) {
+        threadDao.saveSummary(summary);
+    }
+}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Version;
-
-import com.redhat.thermostat.backend.VmUpdateListener;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-
-public class ActivatorTest {
-
-    private Bundle bundle;
-    private Version version;
-    private WriterID writerId;
-    private ThreadDao threadDao;
-
-    @Before
-    public void setUp() {
-        version = new Version("0.1.2");
-
-        bundle = mock(Bundle.class);
-        when(bundle.getVersion()).thenReturn(version);
-
-        writerId = mock(WriterID.class);
-
-        threadDao = mock(ThreadDao.class);
-    }
-
-    @Ignore("Activator assumes that Harvester is always registered and fails with NullPointerException")
-    @Test
-    public void verifyThreadCountUpdaterIsRegistered() throws Exception {
-        StubBundleContext bundleContext = new StubBundleContext();
-        bundleContext.setBundle(bundle);
-
-        bundleContext.registerService(WriterID.class, writerId, null);
-        bundleContext.registerService(ThreadDao.class, threadDao, null);
-
-        Activator activator = new Activator();
-
-        activator.start(bundleContext);
-
-        assertTrue(bundleContext.isServiceRegistered(VmUpdateListener.class.getName(), ThreadCountBackend.class));
-
-        activator.stop(bundleContext);
-    }
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/DeadlockHelperTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.VmDeadLockData;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DeadlockHelperTest {
-
-    private static final String DEFAULT_W_ID = "0xcafe";
-    private static final long TIME_IN_MILLIS = 101010l;
-
-    private String vmId;
-    private WriterID writerId;
-    private ThreadDao threadDao;
-    private SystemClock clock;
-
-    private ThreadMXBean collectorBean;
-
-    @Before
-    public void setUp() throws Exception {
-
-        clock = mock(SystemClock.class);
-        when(clock.getRealTimeMillis()).thenReturn(TIME_IN_MILLIS);
-
-        vmId = "testVM";
-        writerId  = mock(WriterID.class);
-        when(writerId.getWriterID()).thenReturn(DEFAULT_W_ID);
-
-        threadDao = mock(ThreadDao.class);
-
-        collectorBean = mock(ThreadMXBean.class);
-    }
-
-    @Test
-    public void testSaveDeadlockInformation() throws Exception {
-
-        long[] infos = new long[] { -1, 0, 1 };
-
-        ThreadInfo[] threadInfo = new ThreadInfo[0];
-        when(collectorBean.findDeadlockedThreads()).thenReturn(infos);
-        when(collectorBean.getThreadInfo(infos, true, true)).thenReturn(threadInfo);
-
-        ArgumentCaptor<VmDeadLockData> deadLockCapture = ArgumentCaptor.forClass(VmDeadLockData.class);
-
-        DeadlockHelper deadlockHelper = new DeadlockHelper(threadDao, clock, vmId, writerId);
-
-        deadlockHelper.saveDeadlockInformation(collectorBean);
-        verify(threadDao).saveDeadLockStatus(deadLockCapture.capture());
-
-        verify(collectorBean).getThreadInfo(infos, true, true);
-        verify(collectorBean).findDeadlockedThreads();
-
-        VmDeadLockData data = deadLockCapture.getValue();
-
-        assertEquals(vmId, data.getVmId());
-        assertEquals(TIME_IN_MILLIS, data.getTimeStamp());
-        assertEquals("", data.getDeadLockDescription());
-    }
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterHelperTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSession;
-import com.redhat.thermostat.thread.model.ThreadState;
-import com.redhat.thermostat.thread.model.ThreadSummary;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import org.junit.Before;
-import org.junit.Test;
-
-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;
-
-/*
- */
-public class HarvesterHelperTest {
-
-    private static final long DEFAULT_TIMESTAMP = -1l;
-
-    private ThreadDao threadDao;
-
-    private Clock clock;
-    private String vmId;
-
-    private ThreadSummaryHelper summaryHelper;
-    private ThreadStateHelper stateHelper;
-    private ThreadSessionHelper threadSessionHelper;
-
-    private ThreadMXBean collectorBean;
-    private ThreadSession session;
-    @Before
-    public void setUp() {
-        summaryHelper = mock(ThreadSummaryHelper.class);
-        stateHelper = mock(ThreadStateHelper.class);
-
-        threadDao = mock(ThreadDao.class);
-        collectorBean = mock(ThreadMXBean.class);
-
-        clock = mock(Clock.class);
-        when(clock.getRealTimeMillis()).thenReturn(DEFAULT_TIMESTAMP);
-
-        vmId = "42";
-
-        session = new ThreadSession();
-        session.setSession("0xcafe");
-
-        threadSessionHelper = mock(ThreadSessionHelper.class);
-    }
-
-    @Test
-    public void testThreadInfoRetrievedMatchThreadIDs() {
-
-        long[] ids = new long[] {0l, 1l, 2l};
-        when(collectorBean.getAllThreadIds()).thenReturn(ids);
-
-        HarvesterHelper harvester = new HarvesterHelper(clock, vmId,
-                                                        stateHelper,
-                                                        threadSessionHelper);
-        harvester.collectAndSaveThreadData(session, collectorBean);
-        verify(collectorBean).getAllThreadIds();
-
-        verify(collectorBean).getThreadInfo(ids, true, true);
-    }
-
-    @Test
-    public void testThreadInfoPassedToThreadStateHelper() {
-
-        long[] ids = new long[] { 0l, 1l, 2l };
-
-        when(collectorBean.getAllThreadIds()).thenReturn(ids);
-
-        ThreadInfo[] infos = new ThreadInfo[3];
-        infos[0] = mock(ThreadInfo.class);
-        infos[1] = mock(ThreadInfo.class);
-        infos[2] = mock(ThreadInfo.class);
-
-        when(collectorBean.getThreadInfo(any(long[].class), eq(true), eq(true))).thenReturn(infos);
-
-        ThreadState state1 = mock(ThreadState.class);
-        ThreadState state2 = mock(ThreadState.class);
-        ThreadState state3 = mock(ThreadState.class);
-
-        when(stateHelper.createThreadState(eq(infos[0]),eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state1);
-        when(stateHelper.createThreadState(eq(infos[1]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state2);
-        when(stateHelper.createThreadState(eq(infos[2]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state3);
-
-        HarvesterHelper harvester = new HarvesterHelper(clock, vmId,
-                                                        stateHelper,
-                                                        threadSessionHelper);
-        harvester.collectAndSaveThreadData(session, collectorBean);
-
-        verify(stateHelper).saveThreadState(state1);
-        verify(stateHelper).saveThreadState(state2);
-        verify(stateHelper).saveThreadState(state3);
-    }
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSession;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadMXBean;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-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.anyLong;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class HarvesterTest {
-
-    private WriterID writerId;
-    private int pid;
-
-    private ScheduledExecutorService executor;
-    private ThreadDao dao;
-    private MXBeanConnectionPool pool;
-    private MXBeanConnection connection;
-    private DeadlockHelper deadlockHelper;
-
-    @Before
-    public void setup() throws Exception {
-        writerId = mock(WriterID.class);
-        pid = 42;
-
-        int pid = 42;
-
-        deadlockHelper = mock(DeadlockHelper.class);
-
-        executor = mock(ScheduledExecutorService.class);
-        dao = mock(ThreadDao.class);
-        pool = mock(MXBeanConnectionPool.class);
-        connection = mock(MXBeanConnection.class);
-        when(pool.acquire(pid)).thenReturn(connection);
-    }
-
-    @Test
-    public void testStart() throws Exception {
-
-        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
-        ArgumentCaptor<Long> arg1 = ArgumentCaptor.forClass(Long.class);
-        ArgumentCaptor<Long> arg2 = ArgumentCaptor.forClass(Long.class);
-        ArgumentCaptor<TimeUnit> arg3 = ArgumentCaptor.forClass(TimeUnit.class);
-
-        when(executor.scheduleAtFixedRate(arg0.capture(), arg1.capture(),
-                                          arg2.capture(), arg3.capture())).
-            thenReturn(null);
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-
-        verify(executor).scheduleAtFixedRate(any(Runnable.class), anyLong(),
-                                             anyLong(), any(TimeUnit.class));
-        verify(pool).acquire(pid);
-
-        assertTrue(arg1.getValue() == Harvester.DEFAULT_INITIAL_DELAY);
-        assertTrue(arg2.getValue() == Harvester.DEFAULT_PERIOD);
-        assertEquals(Harvester.DEFAULT_TIME_UNIT, arg3.getValue());
-
-        Runnable action = arg0.getValue();
-        assertNotNull(action);
-        assertTrue(harvester.isConnected());
-    }
-
-    @Test
-    public void testStartTwice() throws Exception {
-        // Mostly the same as testStart, but we call harvester.start() twice
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-        harvester.start();
-
-        verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class),
-                                                       anyLong(),
-                                                       anyLong(),
-                                                       any(TimeUnit.class));
-        assertTrue(harvester.isConnected());
-        verify(pool, times(1)).acquire(pid);
-    }
-
-    @Test
-    public void testStopAfterStarting() throws Exception {
-        // Calls start and then stop
-
-        ScheduledFuture future = mock(ScheduledFuture.class);
-        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
-                                          anyLong(), any(TimeUnit.class))).
-            thenReturn(future);
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-        assertTrue(harvester.isConnected());
-        verify(pool).acquire(pid);
-
-        harvester.stop();
-        assertFalse(harvester.isConnected());
-        verify(pool).release(pid, connection);
-        verify(future).cancel(false);
-    }
-
-    @Test
-    public void testStopTwiceAfterStarting() throws Exception {
-        // like before, but stop is called twice
-
-        ScheduledFuture future = mock(ScheduledFuture.class);
-        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
-                                          anyLong(), any(TimeUnit.class))).
-            thenReturn(future);
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-        assertTrue(harvester.isConnected());
-        verify(pool).acquire(pid);
-
-        harvester.stop();
-        harvester.stop();
-
-        assertFalse(harvester.isConnected());
-        verify(pool, times(1)).release(pid, connection);
-        verify(future, times(1)).cancel(false);
-    }
-
-    @Test
-    public void testStopNotStarted() throws Exception {
-        // calls stop on an harvester that was never started
-
-        ScheduledFuture future = mock(ScheduledFuture.class);
-        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
-                                          anyLong(), any(TimeUnit.class))).
-            thenReturn(future);
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        assertFalse(harvester.isConnected());
-
-        harvester.stop();
-
-        assertFalse(harvester.isConnected());
-        verify(pool, times(0)).release(pid, connection);
-        verify(future, times(0)).cancel(false);
-    }
-
-    @Test
-    public void testHarvestingLoopWithSunBean() throws Exception {
-        // test that the harvester loop calls the appropriate helpers
-
-        com.sun.management.ThreadMXBean sunBean =
-                mock(com.sun.management.ThreadMXBean.class);
-
-        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
-        ScheduledFuture future = mock(ScheduledFuture.class);
-        when(executor.scheduleAtFixedRate(arg0.capture(), anyLong(),
-                                          anyLong(), any(TimeUnit.class))).
-            thenReturn(future);
-
-
-        // simulate the sun bean first
-        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
-                                    com.sun.management.ThreadMXBean.class)).
-            thenReturn(sunBean);
-
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-
-        Runnable harvesterRunnable = arg0.getValue();
-        assertNotNull(harvesterRunnable);
-
-        harvesterRunnable.run();
-
-        verify(helper).collectAndSaveThreadData(any(ThreadSession.class), eq(sunBean));
-    }
-
-    @Test
-    public void testHarvestingLoopWithMXBean() throws Exception {
-        // test that the harvester loop calls the appropriate helpers,
-        // this time with the standard mxbean
-
-        ThreadMXBean mxBean = mock(ThreadMXBean.class);
-
-        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
-        ScheduledFuture future = mock(ScheduledFuture.class);
-        when(executor.scheduleAtFixedRate(arg0.capture(), anyLong(),
-                                          anyLong(), any(TimeUnit.class))).
-            thenReturn(future);
-
-        // simulate the sun bean first
-        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
-                                    com.sun.management.ThreadMXBean.class)).
-                thenReturn(null);
-        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
-                                    ThreadMXBean.class)).
-                thenReturn(mxBean);
-
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper);
-
-        harvester.start();
-
-        Runnable harvesterRunnable = arg0.getValue();
-        assertNotNull(harvesterRunnable);
-
-        harvesterRunnable.run();
-
-        verify(helper).collectAndSaveThreadData(any(ThreadSession.class), eq(mxBean));
-    }
-
-    @Test
-    public void testSaveDeadlockData() {
-
-        final ThreadMXBean mxBean = mock(ThreadMXBean.class);
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper)
-        {
-            @Override
-            ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
-                return mxBean;
-            }
-
-            @Override
-            synchronized boolean isConnected() {
-                return true;
-            }
-        };
-
-        harvester.saveDeadLockData();
-
-        verify(deadlockHelper).saveDeadlockInformation(mxBean);
-    }
-
-    @Test
-    public void testSaveDeadlockDataUnconnectedWillDisconnectAgain() throws Exception {
-
-        final ThreadMXBean mxBean = mock(ThreadMXBean.class);
-        HarvesterHelper helper = mock(HarvesterHelper.class);
-
-        Harvester harvester = new Harvester(pid, executor, pool, helper,
-                                            deadlockHelper)
-        {
-            @Override
-            ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
-                return mxBean;
-            }
-        };
-
-        harvester.saveDeadLockData();
-
-        verify(pool).acquire(pid);
-        verify(deadlockHelper).saveDeadlockInformation(mxBean);
-        verify(pool).release(pid, connection);
-    }
-}
-
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/LockInfoBackendTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.common.Ordered;
-import com.redhat.thermostat.common.Version;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.LockInfoDao;
-
-public class LockInfoBackendTest {
-
-    private LockInfoBackend backend;
-
-    @Before
-    public void setup() {
-        LockInfoDao lockInfoDao = mock(LockInfoDao.class);
-
-        Version version = mock(Version.class);
-        when(version.getVersionNumber()).thenReturn("0.0.0");
-
-        VmStatusListenerRegistrar registrar = mock(VmStatusListenerRegistrar.class);
-
-        WriterID id = mock(WriterID.class);
-        backend = new LockInfoBackend(lockInfoDao, version, registrar, id);
-    }
-
-    @Test
-    public void testOrderValue() {
-        int order = backend.getOrderValue();
-        assertTrue(order >= Ordered.ORDER_THREAD_GROUP);
-        assertTrue(order < Ordered.ORDER_USER_GROUP);
-    }
-
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/LockInfoUpdaterTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.backend.VmUpdate;
-import com.redhat.thermostat.backend.VmUpdateException;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.thread.dao.LockInfoDao;
-import com.redhat.thermostat.thread.model.LockInfo;
-
-public class LockInfoUpdaterTest {
-
-    private LockInfoUpdater lockInfoUpdater;
-
-    private Clock clock;
-    private LockInfoDao lockInfoDao;
-    private VmUpdate update;
-
-    private static final String AGENT_ID = "agent-id";
-    private static final String VM_ID = "vm-id";
-    private static final long TIMESTAMP = 1234l;
-
-    @Before
-    public void setup() throws VmUpdateException {
-        clock = mock(Clock.class);
-        lockInfoDao = mock(LockInfoDao.class);
-        lockInfoUpdater = new LockInfoUpdater(clock, lockInfoDao, AGENT_ID, VM_ID);
-
-        update = mock(VmUpdate.class);
-    }
-
-    @Test
-    public void verifyMissingValuesPopulatesWithUnknown() throws Exception {
-        when(clock.getRealTimeMillis()).thenReturn(TIMESTAMP);
-
-        VmUpdateException counterNotFound = new VmUpdateException();
-        when(update.getPerformanceCounterLong(anyString())).thenThrow(counterNotFound);
-
-        ArgumentCaptor<LockInfo> runCaptor = ArgumentCaptor.forClass(LockInfo.class);
-        lockInfoUpdater.countersUpdated(update);
-
-        verify(lockInfoDao).saveLockInfo(runCaptor.capture());
-
-        LockInfo value = runCaptor.getValue();
-        assertEquals(AGENT_ID, value.getAgentId());
-        assertEquals(VM_ID, value.getVmId());
-        assertEquals(TIMESTAMP, value.getTimeStamp());
-        assertEquals(LockInfo.UNKNOWN, value.getContendedLockAttempts());
-        assertEquals(LockInfo.UNKNOWN, value.getDeflations());
-        assertEquals(LockInfo.UNKNOWN, value.getEmptyNotifications());
-        assertEquals(LockInfo.UNKNOWN, value.getFailedSpins());
-        assertEquals(LockInfo.UNKNOWN, value.getFutileWakeups());
-        assertEquals(LockInfo.UNKNOWN, value.getInflations());
-        assertEquals(LockInfo.UNKNOWN, value.getMonExtant());
-        assertEquals(LockInfo.UNKNOWN, value.getMonInCirculation());
-        assertEquals(LockInfo.UNKNOWN, value.getMonScavenged());
-        assertEquals(LockInfo.UNKNOWN, value.getNotifications());
-        assertEquals(LockInfo.UNKNOWN, value.getParks());
-        assertEquals(LockInfo.UNKNOWN, value.getPrivateA());
-        assertEquals(LockInfo.UNKNOWN, value.getPrivateB());
-        assertEquals(LockInfo.UNKNOWN, value.getSlowEnter());
-        assertEquals(LockInfo.UNKNOWN, value.getSlowExit());
-        assertEquals(LockInfo.UNKNOWN, value.getSlowNotify());
-        assertEquals(LockInfo.UNKNOWN, value.getSlowNotifyAll());
-        assertEquals(LockInfo.UNKNOWN, value.getSuccessfulSpins());
-    }
-
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadBackendTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.VmStatusListener.Status;
-import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
-import com.redhat.thermostat.agent.command.ReceiverRegistry;
-import com.redhat.thermostat.common.Pair;
-import com.redhat.thermostat.common.Version;
-
-public class ThreadBackendTest {
-
-    private Version version;
-    private VmStatusListenerRegistrar vmListenerRegistrar;
-    private ReceiverRegistry receiverRegistry;
-    private ThreadHarvester threadHarvester;
-
-    private ThreadBackend backend;
-
-    @Before
-    public void setUp() {
-        version = mock(Version.class);
-        when(version.getVersionNumber()).thenReturn("foobar");
-        vmListenerRegistrar = mock(VmStatusListenerRegistrar.class);
-        receiverRegistry = mock(ReceiverRegistry.class);
-        threadHarvester = mock(ThreadHarvester.class);
-
-        backend = new ThreadBackend(version, vmListenerRegistrar, receiverRegistry, threadHarvester);
-    }
-
-    @Test
-    public void testActivate() {
-        assertTrue(backend.activate());
-
-        verify(vmListenerRegistrar).register(backend);
-        verify(receiverRegistry).registerReceiver(threadHarvester);
-    }
-
-    @Test
-    public void testDeactivate() {
-        assertTrue(backend.activate());
-        assertTrue(backend.isActive());
-        assertTrue(backend.deactivate());
-        assertFalse(backend.isActive());
-
-        verify(vmListenerRegistrar).unregister(backend);
-        verify(receiverRegistry).unregisterReceivers();
-        verify(threadHarvester).stopAndRemoveAllHarvesters();
-    }
-
-    @Test
-    public void testActivateAfterDeactivate() {
-        when(threadHarvester.stopAndRemoveAllHarvesters()).thenReturn(Arrays.asList(new Pair<>("vmId", 10)));
-
-        assertTrue(backend.activate());
-        assertTrue(backend.deactivate());
-        assertTrue(backend.activate());
-        assertTrue(backend.isActive());
-
-        verify(threadHarvester).startHarvester("vmId", 10);
-    }
-
-    @Test
-    public void testVmStarts() {
-        backend.vmStatusChanged(Status.VM_STARTED, "vmId", 10);
-
-        verify(threadHarvester).addThreadHarvestingStatus("vmId");
-    }
-
-    @Test
-    public void testVmStops() {
-        backend.vmStatusChanged(Status.VM_STOPPED, "vmId", 10);
-
-        verify(threadHarvester).stopHarvester("vmId");
-    }
-}
-
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadCountUpdaterTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.backend.VmUpdate;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.thread.model.ThreadSummary;
-
-public class ThreadCountUpdaterTest {
-
-    private Clock clock;
-    private ThreadSummaryHelper summaryHelper;
-    private VmUpdate update;
-
-    @Before
-    public void setUp() {
-        clock = mock(Clock.class);
-
-        summaryHelper = mock(ThreadSummaryHelper.class);
-
-        update = mock(VmUpdate.class);
-    }
-
-    @Test
-    public void testThreadSummarySaved() throws Exception {
-        final long SOME_TIMESTAMP = 1;
-        final long LIVE_THREADS = 2;
-        final long DAEMON_THREADS = 3;
-
-        when(clock.getRealTimeMillis()).thenReturn(SOME_TIMESTAMP);
-
-        ThreadSummary summary = mock(ThreadSummary.class);
-        when(summaryHelper.createThreadSummary(SOME_TIMESTAMP, LIVE_THREADS, DAEMON_THREADS)).
-            thenReturn(summary);
-
-        when(update.getPerformanceCounterLong("java.threads.live")).thenReturn(LIVE_THREADS);
-        when(update.getPerformanceCounterLong("java.threads.daemon")).thenReturn(DAEMON_THREADS);
-
-        ThreadCountUpdater updater = new ThreadCountUpdater(clock, summaryHelper);
-        updater.countersUpdated(update);
-
-        verify(summaryHelper).saveSummary(summary);
-    }
-
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHarvesterTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.Pair;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.collector.HarvesterCommand;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadHarvestingStatus;
-import java.util.List;
-import java.util.concurrent.ScheduledExecutorService;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ThreadHarvesterTest {
-
-    private MXBeanConnectionPool pool;
-    private ScheduledExecutorService executor;
-    private WriterID writerId;
-
-    @Before
-    public void setUp() {
-        pool = mock(MXBeanConnectionPool.class);
-        executor = mock(ScheduledExecutorService.class);
-        writerId = mock(WriterID.class);
-    }
-
-    @Test
-    public void testStart() {
-        ThreadDao dao = mock(ThreadDao.class);
-        Request request = mock(Request.class);
-        
-        final boolean[] createHarvesterCalled = new boolean[1];
-        final Harvester harverster = mock(Harvester.class);
-        when(harverster.start()).thenReturn(true);
-        
-        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
-        
-        when(request.getParameter(captor.capture())).
-            thenReturn(HarvesterCommand.START.name()).
-            thenReturn("vmId").
-            thenReturn("42").
-            thenReturn("0xcafe");
-        
-        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
-            @Override
-            Harvester createHarvester(String vmId, int pid) {
-                
-                createHarvesterCalled[0] = true;
-                assertEquals("vmId", vmId);
-                assertEquals(42, pid);
-                
-                return harverster;
-            }
-        };
-        threadHarvester.setThreadDao(dao);
-        threadHarvester.receive(request);
-        
-        List<String> values = captor.getAllValues();
-        assertEquals(3, values.size());
-        
-        assertEquals(HarvesterCommand.class.getName(), values.get(0));
-        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
-        assertEquals(HarvesterCommand.VM_PID.name(), values.get(2));
-        
-        assertTrue(createHarvesterCalled[0]);
-        
-        verify(harverster).start();
-    }
-
-    @Test
-    public void testStop() {
-        ThreadDao dao = mock(ThreadDao.class);
-        Request request = mock(Request.class);
-
-        final Harvester harverster = mock(Harvester.class);
-        
-        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
-        
-        when(request.getParameter(captor.capture())).
-            thenReturn(HarvesterCommand.STOP.name()).
-            thenReturn("vmId");
-        
-        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
-            { connectors.put("vmId", harverster); }
-        };
-        threadHarvester.setThreadDao(dao);
-        threadHarvester.receive(request);
-        
-        List<String> values = captor.getAllValues();
-        assertEquals(2, values.size());
-        
-        assertEquals(HarvesterCommand.class.getName(), values.get(0));
-        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
-                
-        verify(harverster).stop();        
-    }
-    
-    @Test
-    public void testFindDeadLocks() {
-        ThreadDao dao = mock(ThreadDao.class);
-        Request request = mock(Request.class);
-
-        final boolean[] createHarvesterCalled = new boolean[1];
-        final Harvester harvester = mock(Harvester.class);
-        when(harvester.start()).thenReturn(true);
-
-        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
-
-        when(request.getParameter(captor.capture())).
-                thenReturn(HarvesterCommand.FIND_DEADLOCKS.name()).
-                thenReturn("vmId").
-                thenReturn("42").
-                thenReturn("0xcafe");
-
-        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
-            @Override
-            Harvester createHarvester(String vmId, int pid) {
-
-                createHarvesterCalled[0] = true;
-                assertEquals("vmId", vmId);
-                assertEquals(42, pid);
-
-                return harvester;
-            }
-        };
-        threadHarvester.setThreadDao(dao);
-        threadHarvester.receive(request);
-
-        List<String> values = captor.getAllValues();
-        assertEquals(3, values.size());
-
-        assertEquals(HarvesterCommand.class.getName(), values.get(0));
-        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
-        assertEquals(HarvesterCommand.VM_PID.name(), values.get(2));
-
-        assertTrue(createHarvesterCalled[0]);
-
-        verify(harvester).saveDeadLockData();
-    }
-
-    @Test
-    public void testReceiveWithoutDaosFails() {
-        ThreadHarvester harvester = new ThreadHarvester(executor, pool, writerId);
-        Response response = harvester.receive(mock(Request.class));
-
-        assertEquals(ResponseType.ERROR, response.getType());
-    }
-
-    @Test
-    public void testHarvestingStatus() {
-        Clock clock = mock(Clock.class);
-        when(clock.getRealTimeMillis()).thenReturn(1l);
-        ThreadDao dao = mock(ThreadDao.class);
-
-        ThreadHarvester harvester = new ThreadHarvester(executor, clock, pool, writerId);
-        harvester.setThreadDao(dao);
-
-        harvester.addThreadHarvestingStatus("vmId");
-
-        ArgumentCaptor<ThreadHarvestingStatus> statusCaptor = ArgumentCaptor.forClass(ThreadHarvestingStatus.class);
-        verify(dao).saveHarvestingStatus(statusCaptor.capture());
-
-        ThreadHarvestingStatus status = statusCaptor.getValue();
-        assertEquals("vmId", status.getVmId());
-        assertEquals(false, status.isHarvesting());
-        assertEquals(1, status.getTimeStamp());
-    }
-
-    @Test
-    public void testStopAndRemoveAll() {
-        Clock clock = mock(Clock.class);
-        when(clock.getRealTimeMillis()).thenReturn(1l);
-        ThreadDao dao = mock(ThreadDao.class);
-
-        final Harvester javaHarvester = mock(Harvester.class);
-        when(javaHarvester.start()).thenReturn(true);
-        when(javaHarvester.stop()).thenReturn(true);
-        when(javaHarvester.getPid()).thenReturn(42);
-
-        ThreadHarvester harvester = new ThreadHarvester(executor, clock, pool, writerId) {
-            @Override
-            Harvester createHarvester(String vmId, int pid) {
-                assertEquals("vmId", vmId);
-                assertEquals(42, pid);
-
-                return javaHarvester;
-            }
-        };
-        
-        harvester.setThreadDao(dao);
-        harvester.startHarvester("vmId", 42);
-        
-        // Reset DAO
-        harvester.setThreadDao(dao);
-
-        assertTrue(harvester.startHarvester("vmId", 42));
-
-        List<Pair<String, Integer>> allSaved = harvester.stopAndRemoveAllHarvesters();
-        assertEquals(1, allSaved.size());
-        Pair<String, Integer> saved = allSaved.get(0);
-        assertEquals("vmId", saved.getFirst());
-        assertEquals(42, saved.getSecond().intValue());
-    }
-}
-
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadStateHelperTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.SessionID;
-import com.redhat.thermostat.thread.model.ThreadState;
-import java.lang.management.ThreadInfo;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-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 ThreadStateHelperTest {
-
-    private static String DEFAULT_W_ID = "0xcafe";
-    private static String DEFAULT_HEADER_REF_ID = "42";
-    private static String DEFAULT_SESSION_ID = "This Session";
-
-    private String vmId;
-    private WriterID writerId;
-    private ThreadDao threadDao;
-
-    private SessionID sessionID;
-
-    @Before
-    public void setUp() throws Exception {
-        vmId = "testVM";
-        writerId  = mock(WriterID.class);
-        when(writerId.getWriterID()).thenReturn(DEFAULT_W_ID);
-
-        threadDao = mock(ThreadDao.class);
-
-        sessionID = mock(SessionID.class);
-        when(sessionID.get()).thenReturn(DEFAULT_SESSION_ID);
-    }
-
-    @Test
-    public void testCreateThreadState() throws Exception {
-        ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId);
-
-        ThreadInfo info = mock(ThreadInfo.class);
-        when(info.getThreadState()).thenReturn(Thread.State.BLOCKED);
-
-        long timestamp = -1l;
-
-        ThreadState state = helper.createThreadState(info, sessionID, timestamp);
-        assertNotNull(state);
-
-        assertEquals(timestamp, state.getTimeStamp());
-        assertEquals(Thread.State.BLOCKED.name(), state.getState());
-        assertEquals(DEFAULT_SESSION_ID, state.getSession());
-    }
-
-    @Test
-    public void testSaveThreadState() throws Exception {
-        ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId);
-        ThreadState state = mock(ThreadState.class);
-
-        helper.saveThreadState(state);
-
-        ArgumentCaptor<ThreadState> captor =
-                ArgumentCaptor.forClass(ThreadState.class);
-        verify(threadDao).addThreadState(captor.capture());
-
-        ThreadState argumentToDao = captor.getValue();
-        assertEquals(argumentToDao, state);
-    }
-}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelperTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012-2016 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.thread.harvester;
-
-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 org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.thread.dao.ThreadDao;
-import com.redhat.thermostat.thread.model.ThreadSummary;
-
-/*
- */
-public class ThreadSummaryHelperTest {
-
-    private static final String DEFAULT_WRITER_ID = "0xcafe";
-    private static final int DEFAULT_THREAD_COUNT = 42;
-    private static final int DEFAULT_DAEMON_THREAD_COUNT = 7;
-
-    private String vmId;
-    private String writerId;
-    private ThreadDao threadDao;
-
-    @Before
-    public void setUp() throws Exception {
-        vmId = "testVM";
-        writerId  = DEFAULT_WRITER_ID;
-
-        threadDao = mock(ThreadDao.class);
-
-    }
-
-    @Test
-    public void testCreateThreadSummary() throws Exception {
-        ThreadSummaryHelper helper =
-                new ThreadSummaryHelper(threadDao, writerId, vmId);
-
-        long timestamp = -1l;
-
-        ThreadSummary summary = helper.createThreadSummary(
-                timestamp, DEFAULT_THREAD_COUNT, DEFAULT_DAEMON_THREAD_COUNT);
-
-        assertNotNull(summary);
-
-        assertEquals(summary.getAgentId(), DEFAULT_WRITER_ID);
-        assertEquals(summary.getVmId(), vmId);
-
-        assertEquals(summary.getCurrentLiveThreads(), DEFAULT_THREAD_COUNT);
-        assertEquals(summary.getCurrentDaemonThreads(), DEFAULT_DAEMON_THREAD_COUNT);
-        assertEquals(summary.getTimeStamp(), timestamp);
-    }
-
-    @Test
-    public void testSaveSummary() throws Exception {
-        ThreadSummaryHelper helper =
-                new ThreadSummaryHelper(threadDao, writerId, vmId);
-
-        ThreadSummary summary  = mock(ThreadSummary.class);
-        helper.saveSummary(summary);
-        
-        verify(threadDao).saveSummary(summary);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+import com.redhat.thermostat.backend.VmUpdateListener;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.testutils.StubBundleContext;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+
+public class ActivatorTest {
+
+    private Bundle bundle;
+    private Version version;
+    private WriterID writerId;
+    private ThreadDao threadDao;
+
+    @Before
+    public void setUp() {
+        version = new Version("0.1.2");
+
+        bundle = mock(Bundle.class);
+        when(bundle.getVersion()).thenReturn(version);
+
+        writerId = mock(WriterID.class);
+
+        threadDao = mock(ThreadDao.class);
+    }
+
+    @Ignore("Activator assumes that Harvester is always registered and fails with NullPointerException")
+    @Test
+    public void verifyThreadCountUpdaterIsRegistered() throws Exception {
+        StubBundleContext bundleContext = new StubBundleContext();
+        bundleContext.setBundle(bundle);
+
+        bundleContext.registerService(WriterID.class, writerId, null);
+        bundleContext.registerService(ThreadDao.class, threadDao, null);
+
+        Activator activator = new Activator();
+
+        activator.start(bundleContext);
+
+        assertTrue(bundleContext.isServiceRegistered(VmUpdateListener.class.getName(), ThreadCountBackend.class));
+
+        activator.stop(bundleContext);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/DeadlockHelperTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.VmDeadLockData;
+
+public class DeadlockHelperTest {
+
+    private static final String DEFAULT_W_ID = "0xcafe";
+    private static final long TIME_IN_MILLIS = 101010l;
+
+    private String vmId;
+    private WriterID writerId;
+    private ThreadDao threadDao;
+    private SystemClock clock;
+
+    private ThreadMXBean collectorBean;
+
+    @Before
+    public void setUp() throws Exception {
+
+        clock = mock(SystemClock.class);
+        when(clock.getRealTimeMillis()).thenReturn(TIME_IN_MILLIS);
+
+        vmId = "testVM";
+        writerId  = mock(WriterID.class);
+        when(writerId.getWriterID()).thenReturn(DEFAULT_W_ID);
+
+        threadDao = mock(ThreadDao.class);
+
+        collectorBean = mock(ThreadMXBean.class);
+    }
+
+    @Test
+    public void testSaveDeadlockInformation() throws Exception {
+
+        long[] infos = new long[] { -1, 0, 1 };
+
+        ThreadInfo[] threadInfo = new ThreadInfo[0];
+        when(collectorBean.findDeadlockedThreads()).thenReturn(infos);
+        when(collectorBean.getThreadInfo(infos, true, true)).thenReturn(threadInfo);
+
+        ArgumentCaptor<VmDeadLockData> deadLockCapture = ArgumentCaptor.forClass(VmDeadLockData.class);
+
+        DeadlockHelper deadlockHelper = new DeadlockHelper(threadDao, clock, vmId, writerId);
+
+        deadlockHelper.saveDeadlockInformation(collectorBean);
+        verify(threadDao).saveDeadLockStatus(deadLockCapture.capture());
+
+        verify(collectorBean).getThreadInfo(infos, true, true);
+        verify(collectorBean).findDeadlockedThreads();
+
+        VmDeadLockData data = deadLockCapture.getValue();
+
+        assertEquals(vmId, data.getVmId());
+        assertEquals(TIME_IN_MILLIS, data.getTimeStamp());
+        assertEquals("", data.getDeadLockDescription());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/HarvesterHelperTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+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.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSession;
+import com.redhat.thermostat.thread.model.ThreadState;
+
+/*
+ */
+public class HarvesterHelperTest {
+
+    private static final long DEFAULT_TIMESTAMP = -1l;
+
+    private ThreadDao threadDao;
+
+    private Clock clock;
+    private String vmId;
+
+    private ThreadSummaryHelper summaryHelper;
+    private ThreadStateHelper stateHelper;
+    private ThreadSessionHelper threadSessionHelper;
+
+    private ThreadMXBean collectorBean;
+    private ThreadSession session;
+    @Before
+    public void setUp() {
+        summaryHelper = mock(ThreadSummaryHelper.class);
+        stateHelper = mock(ThreadStateHelper.class);
+
+        threadDao = mock(ThreadDao.class);
+        collectorBean = mock(ThreadMXBean.class);
+
+        clock = mock(Clock.class);
+        when(clock.getRealTimeMillis()).thenReturn(DEFAULT_TIMESTAMP);
+
+        vmId = "42";
+
+        session = new ThreadSession();
+        session.setSession("0xcafe");
+
+        threadSessionHelper = mock(ThreadSessionHelper.class);
+    }
+
+    @Test
+    public void testThreadInfoRetrievedMatchThreadIDs() {
+
+        long[] ids = new long[] {0l, 1l, 2l};
+        when(collectorBean.getAllThreadIds()).thenReturn(ids);
+
+        HarvesterHelper harvester = new HarvesterHelper(clock, vmId,
+                                                        stateHelper,
+                                                        threadSessionHelper);
+        harvester.collectAndSaveThreadData(session, collectorBean);
+        verify(collectorBean).getAllThreadIds();
+
+        verify(collectorBean).getThreadInfo(ids, true, true);
+    }
+
+    @Test
+    public void testThreadInfoPassedToThreadStateHelper() {
+
+        long[] ids = new long[] { 0l, 1l, 2l };
+
+        when(collectorBean.getAllThreadIds()).thenReturn(ids);
+
+        ThreadInfo[] infos = new ThreadInfo[3];
+        infos[0] = mock(ThreadInfo.class);
+        infos[1] = mock(ThreadInfo.class);
+        infos[2] = mock(ThreadInfo.class);
+
+        when(collectorBean.getThreadInfo(any(long[].class), eq(true), eq(true))).thenReturn(infos);
+
+        ThreadState state1 = mock(ThreadState.class);
+        ThreadState state2 = mock(ThreadState.class);
+        ThreadState state3 = mock(ThreadState.class);
+
+        when(stateHelper.createThreadState(eq(infos[0]),eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state1);
+        when(stateHelper.createThreadState(eq(infos[1]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state2);
+        when(stateHelper.createThreadState(eq(infos[2]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state3);
+
+        HarvesterHelper harvester = new HarvesterHelper(clock, vmId,
+                                                        stateHelper,
+                                                        threadSessionHelper);
+        harvester.collectAndSaveThreadData(session, collectorBean);
+
+        verify(stateHelper).saveThreadState(state1);
+        verify(stateHelper).saveThreadState(state2);
+        verify(stateHelper).saveThreadState(state3);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/HarvesterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+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.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSession;
+
+public class HarvesterTest {
+
+    private WriterID writerId;
+    private int pid;
+
+    private ScheduledExecutorService executor;
+    private ThreadDao dao;
+    private MXBeanConnectionPool pool;
+    private MXBeanConnection connection;
+    private DeadlockHelper deadlockHelper;
+
+    @Before
+    public void setup() throws Exception {
+        writerId = mock(WriterID.class);
+        pid = 42;
+
+        int pid = 42;
+
+        deadlockHelper = mock(DeadlockHelper.class);
+
+        executor = mock(ScheduledExecutorService.class);
+        dao = mock(ThreadDao.class);
+        pool = mock(MXBeanConnectionPool.class);
+        connection = mock(MXBeanConnection.class);
+        when(pool.acquire(pid)).thenReturn(connection);
+    }
+
+    @Test
+    public void testStart() throws Exception {
+
+        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
+        ArgumentCaptor<Long> arg1 = ArgumentCaptor.forClass(Long.class);
+        ArgumentCaptor<Long> arg2 = ArgumentCaptor.forClass(Long.class);
+        ArgumentCaptor<TimeUnit> arg3 = ArgumentCaptor.forClass(TimeUnit.class);
+
+        when(executor.scheduleAtFixedRate(arg0.capture(), arg1.capture(),
+                                          arg2.capture(), arg3.capture())).
+            thenReturn(null);
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+
+        verify(executor).scheduleAtFixedRate(any(Runnable.class), anyLong(),
+                                             anyLong(), any(TimeUnit.class));
+        verify(pool).acquire(pid);
+
+        assertTrue(arg1.getValue() == Harvester.DEFAULT_INITIAL_DELAY);
+        assertTrue(arg2.getValue() == Harvester.DEFAULT_PERIOD);
+        assertEquals(Harvester.DEFAULT_TIME_UNIT, arg3.getValue());
+
+        Runnable action = arg0.getValue();
+        assertNotNull(action);
+        assertTrue(harvester.isConnected());
+    }
+
+    @Test
+    public void testStartTwice() throws Exception {
+        // Mostly the same as testStart, but we call harvester.start() twice
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+        harvester.start();
+
+        verify(executor, times(1)).scheduleAtFixedRate(any(Runnable.class),
+                                                       anyLong(),
+                                                       anyLong(),
+                                                       any(TimeUnit.class));
+        assertTrue(harvester.isConnected());
+        verify(pool, times(1)).acquire(pid);
+    }
+
+    @Test
+    public void testStopAfterStarting() throws Exception {
+        // Calls start and then stop
+
+        ScheduledFuture future = mock(ScheduledFuture.class);
+        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
+                                          anyLong(), any(TimeUnit.class))).
+            thenReturn(future);
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+        assertTrue(harvester.isConnected());
+        verify(pool).acquire(pid);
+
+        harvester.stop();
+        assertFalse(harvester.isConnected());
+        verify(pool).release(pid, connection);
+        verify(future).cancel(false);
+    }
+
+    @Test
+    public void testStopTwiceAfterStarting() throws Exception {
+        // like before, but stop is called twice
+
+        ScheduledFuture future = mock(ScheduledFuture.class);
+        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
+                                          anyLong(), any(TimeUnit.class))).
+            thenReturn(future);
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+        assertTrue(harvester.isConnected());
+        verify(pool).acquire(pid);
+
+        harvester.stop();
+        harvester.stop();
+
+        assertFalse(harvester.isConnected());
+        verify(pool, times(1)).release(pid, connection);
+        verify(future, times(1)).cancel(false);
+    }
+
+    @Test
+    public void testStopNotStarted() throws Exception {
+        // calls stop on an harvester that was never started
+
+        ScheduledFuture future = mock(ScheduledFuture.class);
+        when(executor.scheduleAtFixedRate(any(Runnable.class), anyLong(),
+                                          anyLong(), any(TimeUnit.class))).
+            thenReturn(future);
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        assertFalse(harvester.isConnected());
+
+        harvester.stop();
+
+        assertFalse(harvester.isConnected());
+        verify(pool, times(0)).release(pid, connection);
+        verify(future, times(0)).cancel(false);
+    }
+
+    @Test
+    public void testHarvestingLoopWithSunBean() throws Exception {
+        // test that the harvester loop calls the appropriate helpers
+
+        com.sun.management.ThreadMXBean sunBean =
+                mock(com.sun.management.ThreadMXBean.class);
+
+        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
+        ScheduledFuture future = mock(ScheduledFuture.class);
+        when(executor.scheduleAtFixedRate(arg0.capture(), anyLong(),
+                                          anyLong(), any(TimeUnit.class))).
+            thenReturn(future);
+
+
+        // simulate the sun bean first
+        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
+                                    com.sun.management.ThreadMXBean.class)).
+            thenReturn(sunBean);
+
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+
+        Runnable harvesterRunnable = arg0.getValue();
+        assertNotNull(harvesterRunnable);
+
+        harvesterRunnable.run();
+
+        verify(helper).collectAndSaveThreadData(any(ThreadSession.class), eq(sunBean));
+    }
+
+    @Test
+    public void testHarvestingLoopWithMXBean() throws Exception {
+        // test that the harvester loop calls the appropriate helpers,
+        // this time with the standard mxbean
+
+        ThreadMXBean mxBean = mock(ThreadMXBean.class);
+
+        ArgumentCaptor<Runnable> arg0 = ArgumentCaptor.forClass(Runnable.class);
+        ScheduledFuture future = mock(ScheduledFuture.class);
+        when(executor.scheduleAtFixedRate(arg0.capture(), anyLong(),
+                                          anyLong(), any(TimeUnit.class))).
+            thenReturn(future);
+
+        // simulate the sun bean first
+        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
+                                    com.sun.management.ThreadMXBean.class)).
+                thenReturn(null);
+        when(connection.createProxy(ManagementFactory.THREAD_MXBEAN_NAME,
+                                    ThreadMXBean.class)).
+                thenReturn(mxBean);
+
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper);
+
+        harvester.start();
+
+        Runnable harvesterRunnable = arg0.getValue();
+        assertNotNull(harvesterRunnable);
+
+        harvesterRunnable.run();
+
+        verify(helper).collectAndSaveThreadData(any(ThreadSession.class), eq(mxBean));
+    }
+
+    @Test
+    public void testSaveDeadlockData() {
+
+        final ThreadMXBean mxBean = mock(ThreadMXBean.class);
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper)
+        {
+            @Override
+            ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
+                return mxBean;
+            }
+
+            @Override
+            synchronized boolean isConnected() {
+                return true;
+            }
+        };
+
+        harvester.saveDeadLockData();
+
+        verify(deadlockHelper).saveDeadlockInformation(mxBean);
+    }
+
+    @Test
+    public void testSaveDeadlockDataUnconnectedWillDisconnectAgain() throws Exception {
+
+        final ThreadMXBean mxBean = mock(ThreadMXBean.class);
+        HarvesterHelper helper = mock(HarvesterHelper.class);
+
+        Harvester harvester = new Harvester(pid, executor, pool, helper,
+                                            deadlockHelper)
+        {
+            @Override
+            ThreadMXBean getDataCollectorBean(MXBeanConnection connection) {
+                return mxBean;
+            }
+        };
+
+        harvester.saveDeadLockData();
+
+        verify(pool).acquire(pid);
+        verify(deadlockHelper).saveDeadlockInformation(mxBean);
+        verify(pool).release(pid, connection);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/LockInfoBackendTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.common.Ordered;
+import com.redhat.thermostat.common.Version;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.LockInfoDao;
+
+public class LockInfoBackendTest {
+
+    private LockInfoBackend backend;
+
+    @Before
+    public void setup() {
+        LockInfoDao lockInfoDao = mock(LockInfoDao.class);
+
+        Version version = mock(Version.class);
+        when(version.getVersionNumber()).thenReturn("0.0.0");
+
+        VmStatusListenerRegistrar registrar = mock(VmStatusListenerRegistrar.class);
+
+        WriterID id = mock(WriterID.class);
+        backend = new LockInfoBackend(lockInfoDao, version, registrar, id);
+    }
+
+    @Test
+    public void testOrderValue() {
+        int order = backend.getOrderValue();
+        assertTrue(order >= Ordered.ORDER_THREAD_GROUP);
+        assertTrue(order < Ordered.ORDER_USER_GROUP);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/LockInfoUpdaterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.backend.VmUpdate;
+import com.redhat.thermostat.backend.VmUpdateException;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.thread.dao.LockInfoDao;
+import com.redhat.thermostat.thread.model.LockInfo;
+
+public class LockInfoUpdaterTest {
+
+    private LockInfoUpdater lockInfoUpdater;
+
+    private Clock clock;
+    private LockInfoDao lockInfoDao;
+    private VmUpdate update;
+
+    private static final String AGENT_ID = "agent-id";
+    private static final String VM_ID = "vm-id";
+    private static final long TIMESTAMP = 1234l;
+
+    @Before
+    public void setup() throws VmUpdateException {
+        clock = mock(Clock.class);
+        lockInfoDao = mock(LockInfoDao.class);
+        lockInfoUpdater = new LockInfoUpdater(clock, lockInfoDao, AGENT_ID, VM_ID);
+
+        update = mock(VmUpdate.class);
+    }
+
+    @Test
+    public void verifyMissingValuesPopulatesWithUnknown() throws Exception {
+        when(clock.getRealTimeMillis()).thenReturn(TIMESTAMP);
+
+        VmUpdateException counterNotFound = new VmUpdateException();
+        when(update.getPerformanceCounterLong(anyString())).thenThrow(counterNotFound);
+
+        ArgumentCaptor<LockInfo> runCaptor = ArgumentCaptor.forClass(LockInfo.class);
+        lockInfoUpdater.countersUpdated(update);
+
+        verify(lockInfoDao).saveLockInfo(runCaptor.capture());
+
+        LockInfo value = runCaptor.getValue();
+        assertEquals(AGENT_ID, value.getAgentId());
+        assertEquals(VM_ID, value.getVmId());
+        assertEquals(TIMESTAMP, value.getTimeStamp());
+        assertEquals(LockInfo.UNKNOWN, value.getContendedLockAttempts());
+        assertEquals(LockInfo.UNKNOWN, value.getDeflations());
+        assertEquals(LockInfo.UNKNOWN, value.getEmptyNotifications());
+        assertEquals(LockInfo.UNKNOWN, value.getFailedSpins());
+        assertEquals(LockInfo.UNKNOWN, value.getFutileWakeups());
+        assertEquals(LockInfo.UNKNOWN, value.getInflations());
+        assertEquals(LockInfo.UNKNOWN, value.getMonExtant());
+        assertEquals(LockInfo.UNKNOWN, value.getMonInCirculation());
+        assertEquals(LockInfo.UNKNOWN, value.getMonScavenged());
+        assertEquals(LockInfo.UNKNOWN, value.getNotifications());
+        assertEquals(LockInfo.UNKNOWN, value.getParks());
+        assertEquals(LockInfo.UNKNOWN, value.getPrivateA());
+        assertEquals(LockInfo.UNKNOWN, value.getPrivateB());
+        assertEquals(LockInfo.UNKNOWN, value.getSlowEnter());
+        assertEquals(LockInfo.UNKNOWN, value.getSlowExit());
+        assertEquals(LockInfo.UNKNOWN, value.getSlowNotify());
+        assertEquals(LockInfo.UNKNOWN, value.getSlowNotifyAll());
+        assertEquals(LockInfo.UNKNOWN, value.getSuccessfulSpins());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadBackendTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.VmStatusListener.Status;
+import com.redhat.thermostat.agent.VmStatusListenerRegistrar;
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
+import com.redhat.thermostat.common.Pair;
+import com.redhat.thermostat.common.Version;
+
+public class ThreadBackendTest {
+
+    private Version version;
+    private VmStatusListenerRegistrar vmListenerRegistrar;
+    private ReceiverRegistry receiverRegistry;
+    private ThreadHarvester threadHarvester;
+
+    private ThreadBackend backend;
+
+    @Before
+    public void setUp() {
+        version = mock(Version.class);
+        when(version.getVersionNumber()).thenReturn("foobar");
+        vmListenerRegistrar = mock(VmStatusListenerRegistrar.class);
+        receiverRegistry = mock(ReceiverRegistry.class);
+        threadHarvester = mock(ThreadHarvester.class);
+
+        backend = new ThreadBackend(version, vmListenerRegistrar, receiverRegistry, threadHarvester);
+    }
+
+    @Test
+    public void testActivate() {
+        assertTrue(backend.activate());
+
+        verify(vmListenerRegistrar).register(backend);
+        verify(receiverRegistry).registerReceiver(threadHarvester);
+    }
+
+    @Test
+    public void testDeactivate() {
+        assertTrue(backend.activate());
+        assertTrue(backend.isActive());
+        assertTrue(backend.deactivate());
+        assertFalse(backend.isActive());
+
+        verify(vmListenerRegistrar).unregister(backend);
+        verify(receiverRegistry).unregisterReceivers();
+        verify(threadHarvester).stopAndRemoveAllHarvesters();
+    }
+
+    @Test
+    public void testActivateAfterDeactivate() {
+        when(threadHarvester.stopAndRemoveAllHarvesters()).thenReturn(Arrays.asList(new Pair<>("vmId", 10)));
+
+        assertTrue(backend.activate());
+        assertTrue(backend.deactivate());
+        assertTrue(backend.activate());
+        assertTrue(backend.isActive());
+
+        verify(threadHarvester).startHarvester("vmId", 10);
+    }
+
+    @Test
+    public void testVmStarts() {
+        backend.vmStatusChanged(Status.VM_STARTED, "vmId", 10);
+
+        verify(threadHarvester).addThreadHarvestingStatus("vmId");
+    }
+
+    @Test
+    public void testVmStops() {
+        backend.vmStatusChanged(Status.VM_STOPPED, "vmId", 10);
+
+        verify(threadHarvester).stopHarvester("vmId");
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadCountUpdaterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.backend.VmUpdate;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.thread.model.ThreadSummary;
+
+public class ThreadCountUpdaterTest {
+
+    private Clock clock;
+    private ThreadSummaryHelper summaryHelper;
+    private VmUpdate update;
+
+    @Before
+    public void setUp() {
+        clock = mock(Clock.class);
+
+        summaryHelper = mock(ThreadSummaryHelper.class);
+
+        update = mock(VmUpdate.class);
+    }
+
+    @Test
+    public void testThreadSummarySaved() throws Exception {
+        final long SOME_TIMESTAMP = 1;
+        final long LIVE_THREADS = 2;
+        final long DAEMON_THREADS = 3;
+
+        when(clock.getRealTimeMillis()).thenReturn(SOME_TIMESTAMP);
+
+        ThreadSummary summary = mock(ThreadSummary.class);
+        when(summaryHelper.createThreadSummary(SOME_TIMESTAMP, LIVE_THREADS, DAEMON_THREADS)).
+            thenReturn(summary);
+
+        when(update.getPerformanceCounterLong("java.threads.live")).thenReturn(LIVE_THREADS);
+        when(update.getPerformanceCounterLong("java.threads.daemon")).thenReturn(DAEMON_THREADS);
+
+        ThreadCountUpdater updater = new ThreadCountUpdater(clock, summaryHelper);
+        updater.countersUpdated(update);
+
+        verify(summaryHelper).saveSummary(summary);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadHarvesterTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.Pair;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.collector.HarvesterCommand;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadHarvestingStatus;
+
+public class ThreadHarvesterTest {
+
+    private MXBeanConnectionPool pool;
+    private ScheduledExecutorService executor;
+    private WriterID writerId;
+
+    @Before
+    public void setUp() {
+        pool = mock(MXBeanConnectionPool.class);
+        executor = mock(ScheduledExecutorService.class);
+        writerId = mock(WriterID.class);
+    }
+
+    @Test
+    public void testStart() {
+        ThreadDao dao = mock(ThreadDao.class);
+        Request request = mock(Request.class);
+        
+        final boolean[] createHarvesterCalled = new boolean[1];
+        final Harvester harverster = mock(Harvester.class);
+        when(harverster.start()).thenReturn(true);
+        
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+        
+        when(request.getParameter(captor.capture())).
+            thenReturn(HarvesterCommand.START.name()).
+            thenReturn("vmId").
+            thenReturn("42").
+            thenReturn("0xcafe");
+        
+        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
+            @Override
+            Harvester createHarvester(String vmId, int pid) {
+                
+                createHarvesterCalled[0] = true;
+                assertEquals("vmId", vmId);
+                assertEquals(42, pid);
+                
+                return harverster;
+            }
+        };
+        threadHarvester.setThreadDao(dao);
+        threadHarvester.receive(request);
+        
+        List<String> values = captor.getAllValues();
+        assertEquals(3, values.size());
+        
+        assertEquals(HarvesterCommand.class.getName(), values.get(0));
+        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
+        assertEquals(HarvesterCommand.VM_PID.name(), values.get(2));
+        
+        assertTrue(createHarvesterCalled[0]);
+        
+        verify(harverster).start();
+    }
+
+    @Test
+    public void testStop() {
+        ThreadDao dao = mock(ThreadDao.class);
+        Request request = mock(Request.class);
+
+        final Harvester harverster = mock(Harvester.class);
+        
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+        
+        when(request.getParameter(captor.capture())).
+            thenReturn(HarvesterCommand.STOP.name()).
+            thenReturn("vmId");
+        
+        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
+            { connectors.put("vmId", harverster); }
+        };
+        threadHarvester.setThreadDao(dao);
+        threadHarvester.receive(request);
+        
+        List<String> values = captor.getAllValues();
+        assertEquals(2, values.size());
+        
+        assertEquals(HarvesterCommand.class.getName(), values.get(0));
+        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
+                
+        verify(harverster).stop();        
+    }
+    
+    @Test
+    public void testFindDeadLocks() {
+        ThreadDao dao = mock(ThreadDao.class);
+        Request request = mock(Request.class);
+
+        final boolean[] createHarvesterCalled = new boolean[1];
+        final Harvester harvester = mock(Harvester.class);
+        when(harvester.start()).thenReturn(true);
+
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+
+        when(request.getParameter(captor.capture())).
+                thenReturn(HarvesterCommand.FIND_DEADLOCKS.name()).
+                thenReturn("vmId").
+                thenReturn("42").
+                thenReturn("0xcafe");
+
+        ThreadHarvester threadHarvester = new ThreadHarvester(executor, pool, writerId) {
+            @Override
+            Harvester createHarvester(String vmId, int pid) {
+
+                createHarvesterCalled[0] = true;
+                assertEquals("vmId", vmId);
+                assertEquals(42, pid);
+
+                return harvester;
+            }
+        };
+        threadHarvester.setThreadDao(dao);
+        threadHarvester.receive(request);
+
+        List<String> values = captor.getAllValues();
+        assertEquals(3, values.size());
+
+        assertEquals(HarvesterCommand.class.getName(), values.get(0));
+        assertEquals(HarvesterCommand.VM_ID.name(), values.get(1));
+        assertEquals(HarvesterCommand.VM_PID.name(), values.get(2));
+
+        assertTrue(createHarvesterCalled[0]);
+
+        verify(harvester).saveDeadLockData();
+    }
+
+    @Test
+    public void testReceiveWithoutDaosFails() {
+        ThreadHarvester harvester = new ThreadHarvester(executor, pool, writerId);
+        Response response = harvester.receive(mock(Request.class));
+
+        assertEquals(ResponseType.ERROR, response.getType());
+    }
+
+    @Test
+    public void testHarvestingStatus() {
+        Clock clock = mock(Clock.class);
+        when(clock.getRealTimeMillis()).thenReturn(1l);
+        ThreadDao dao = mock(ThreadDao.class);
+
+        ThreadHarvester harvester = new ThreadHarvester(executor, clock, pool, writerId);
+        harvester.setThreadDao(dao);
+
+        harvester.addThreadHarvestingStatus("vmId");
+
+        ArgumentCaptor<ThreadHarvestingStatus> statusCaptor = ArgumentCaptor.forClass(ThreadHarvestingStatus.class);
+        verify(dao).saveHarvestingStatus(statusCaptor.capture());
+
+        ThreadHarvestingStatus status = statusCaptor.getValue();
+        assertEquals("vmId", status.getVmId());
+        assertEquals(false, status.isHarvesting());
+        assertEquals(1, status.getTimeStamp());
+    }
+
+    @Test
+    public void testStopAndRemoveAll() {
+        Clock clock = mock(Clock.class);
+        when(clock.getRealTimeMillis()).thenReturn(1l);
+        ThreadDao dao = mock(ThreadDao.class);
+
+        final Harvester javaHarvester = mock(Harvester.class);
+        when(javaHarvester.start()).thenReturn(true);
+        when(javaHarvester.stop()).thenReturn(true);
+        when(javaHarvester.getPid()).thenReturn(42);
+
+        ThreadHarvester harvester = new ThreadHarvester(executor, clock, pool, writerId) {
+            @Override
+            Harvester createHarvester(String vmId, int pid) {
+                assertEquals("vmId", vmId);
+                assertEquals(42, pid);
+
+                return javaHarvester;
+            }
+        };
+        
+        harvester.setThreadDao(dao);
+        harvester.startHarvester("vmId", 42);
+        
+        // Reset DAO
+        harvester.setThreadDao(dao);
+
+        assertTrue(harvester.startHarvester("vmId", 42));
+
+        List<Pair<String, Integer>> allSaved = harvester.stopAndRemoveAllHarvesters();
+        assertEquals(1, allSaved.size());
+        Pair<String, Integer> saved = allSaved.get(0);
+        assertEquals("vmId", saved.getFirst());
+        assertEquals(42, saved.getSecond().intValue());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadStateHelperTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+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.lang.management.ThreadInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.storage.core.WriterID;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.SessionID;
+import com.redhat.thermostat.thread.model.ThreadState;
+
+/**
+ */
+public class ThreadStateHelperTest {
+
+    private static String DEFAULT_W_ID = "0xcafe";
+    private static String DEFAULT_HEADER_REF_ID = "42";
+    private static String DEFAULT_SESSION_ID = "This Session";
+
+    private String vmId;
+    private WriterID writerId;
+    private ThreadDao threadDao;
+
+    private SessionID sessionID;
+
+    @Before
+    public void setUp() throws Exception {
+        vmId = "testVM";
+        writerId  = mock(WriterID.class);
+        when(writerId.getWriterID()).thenReturn(DEFAULT_W_ID);
+
+        threadDao = mock(ThreadDao.class);
+
+        sessionID = mock(SessionID.class);
+        when(sessionID.get()).thenReturn(DEFAULT_SESSION_ID);
+    }
+
+    @Test
+    public void testCreateThreadState() throws Exception {
+        ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId);
+
+        ThreadInfo info = mock(ThreadInfo.class);
+        when(info.getThreadState()).thenReturn(Thread.State.BLOCKED);
+
+        long timestamp = -1l;
+
+        ThreadState state = helper.createThreadState(info, sessionID, timestamp);
+        assertNotNull(state);
+
+        assertEquals(timestamp, state.getTimeStamp());
+        assertEquals(Thread.State.BLOCKED.name(), state.getState());
+        assertEquals(DEFAULT_SESSION_ID, state.getSession());
+    }
+
+    @Test
+    public void testSaveThreadState() throws Exception {
+        ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId);
+        ThreadState state = mock(ThreadState.class);
+
+        helper.saveThreadState(state);
+
+        ArgumentCaptor<ThreadState> captor =
+                ArgumentCaptor.forClass(ThreadState.class);
+        verify(threadDao).addThreadState(captor.capture());
+
+        ThreadState argumentToDao = captor.getValue();
+        assertEquals(argumentToDao, state);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/internal/ThreadSummaryHelperTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012-2016 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.thread.harvester.internal;
+
+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 org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.thread.dao.ThreadDao;
+import com.redhat.thermostat.thread.model.ThreadSummary;
+
+/*
+ */
+public class ThreadSummaryHelperTest {
+
+    private static final String DEFAULT_WRITER_ID = "0xcafe";
+    private static final int DEFAULT_THREAD_COUNT = 42;
+    private static final int DEFAULT_DAEMON_THREAD_COUNT = 7;
+
+    private String vmId;
+    private String writerId;
+    private ThreadDao threadDao;
+
+    @Before
+    public void setUp() throws Exception {
+        vmId = "testVM";
+        writerId  = DEFAULT_WRITER_ID;
+
+        threadDao = mock(ThreadDao.class);
+
+    }
+
+    @Test
+    public void testCreateThreadSummary() throws Exception {
+        ThreadSummaryHelper helper =
+                new ThreadSummaryHelper(threadDao, writerId, vmId);
+
+        long timestamp = -1l;
+
+        ThreadSummary summary = helper.createThreadSummary(
+                timestamp, DEFAULT_THREAD_COUNT, DEFAULT_DAEMON_THREAD_COUNT);
+
+        assertNotNull(summary);
+
+        assertEquals(summary.getAgentId(), DEFAULT_WRITER_ID);
+        assertEquals(summary.getVmId(), vmId);
+
+        assertEquals(summary.getCurrentLiveThreads(), DEFAULT_THREAD_COUNT);
+        assertEquals(summary.getCurrentDaemonThreads(), DEFAULT_DAEMON_THREAD_COUNT);
+        assertEquals(summary.getTimeStamp(), timestamp);
+    }
+
+    @Test
+    public void testSaveSummary() throws Exception {
+        ThreadSummaryHelper helper =
+                new ThreadSummaryHelper(threadDao, writerId, vmId);
+
+        ThreadSummary summary  = mock(ThreadSummary.class);
+        helper.saveSummary(summary);
+        
+        verify(threadDao).saveSummary(summary);
+    }
+}
--- a/validate-command/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/validate-command/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -59,12 +59,8 @@
           <instructions>
             <Bundle-SymbolicName>com.redhat.thermostat.validate.command</Bundle-SymbolicName>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Export-Package>
-              com.redhat.thermostat.validate.command,
-            </Export-Package>
             <Private-Package>
               com.redhat.thermostat.validate.command.internal,
-              com.redhat.thermostat.validate.command.locale,
             </Private-Package>
             <Bundle-Activator>com.redhat.thermostat.validate.command.internal.Activator</Bundle-Activator>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/ValidateCommand.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012-2016 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.validate.command;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
-import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
-import com.redhat.thermostat.plugin.validator.PluginValidator;
-import com.redhat.thermostat.plugin.validator.ValidationErrorsFormatter;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.validate.command.locale.LocaleResources;
-
-public class ValidateCommand implements Command {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-    private PluginValidator validator;
-
-    public void run(CommandContext ctx) throws CommandException {
-        Arguments args = ctx.getArguments();
-        validator = new PluginValidator();
-        File pluginFile = null;
-        String argString = null;
-        
-            try {
-                argString = args.getNonOptionArguments().get(0);
-                pluginFile = new File(argString);
-                validator.validate(pluginFile);
-                ctx.getConsole().getOutput().println(translator.localize(
-                                LocaleResources.VALIDATION_SUCCESSFUL, pluginFile.getAbsolutePath())
-                                .getContents());
-                
-            } catch (PluginConfigurationValidatorException e) {
-                ValidationErrorsFormatter formatter = new ValidationErrorsFormatter();
-                ctx.getConsole().getError().println(formatter.format(e.getAllErrors()));
-                ctx.getConsole().getError().println(translator.localize(
-                                LocaleResources.VALIDATION_FAILED, pluginFile.getAbsolutePath())
-                               .getContents());
-                
-            } catch (IndexOutOfBoundsException | NullPointerException e) {
-                throw new CommandLineArgumentParseException
-                (translator.localize(
-                        LocaleResources.FILE_REQUIRED));
-                
-            } catch (FileNotFoundException fnfe) {
-                throw new CommandLineArgumentParseException
-                (translator.localize(
-                        LocaleResources.FILE_NOT_FOUND, pluginFile.getAbsolutePath()));
-            }        
-    }
-
-    public boolean isStorageRequired() {
-        return false;
-    }
-
-}
-
--- a/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -43,7 +43,6 @@
 import org.osgi.framework.ServiceRegistration;
 
 import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.validate.command.ValidateCommand;
 
 public class Activator implements BundleActivator {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-2016 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.validate.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+
+public enum LocaleResources {
+    
+    VALIDATION_SUCCESSFUL,
+    VALIDATION_FAILED, 
+    
+    FILE_REQUIRED,
+    FILE_NOT_FOUND, 
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.validate.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/ValidateCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012-2016 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.validate.command.internal;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
+import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
+import com.redhat.thermostat.plugin.validator.PluginValidator;
+import com.redhat.thermostat.plugin.validator.ValidationErrorsFormatter;
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class ValidateCommand implements Command {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    private PluginValidator validator;
+
+    public void run(CommandContext ctx) throws CommandException {
+        Arguments args = ctx.getArguments();
+        validator = new PluginValidator();
+        File pluginFile = null;
+        String argString = null;
+        
+            try {
+                argString = args.getNonOptionArguments().get(0);
+                pluginFile = new File(argString);
+                validator.validate(pluginFile);
+                ctx.getConsole().getOutput().println(translator.localize(
+                                LocaleResources.VALIDATION_SUCCESSFUL, pluginFile.getAbsolutePath())
+                                .getContents());
+                
+            } catch (PluginConfigurationValidatorException e) {
+                ValidationErrorsFormatter formatter = new ValidationErrorsFormatter();
+                ctx.getConsole().getError().println(formatter.format(e.getAllErrors()));
+                ctx.getConsole().getError().println(translator.localize(
+                                LocaleResources.VALIDATION_FAILED, pluginFile.getAbsolutePath())
+                               .getContents());
+                
+            } catch (IndexOutOfBoundsException | NullPointerException e) {
+                throw new CommandLineArgumentParseException
+                (translator.localize(
+                        LocaleResources.FILE_REQUIRED));
+                
+            } catch (FileNotFoundException fnfe) {
+                throw new CommandLineArgumentParseException
+                (translator.localize(
+                        LocaleResources.FILE_NOT_FOUND, pluginFile.getAbsolutePath()));
+            }        
+    }
+
+    public boolean isStorageRequired() {
+        return false;
+    }
+
+}
+
--- a/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012-2016 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.validate.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-
-public enum LocaleResources {
-    
-    VALIDATION_SUCCESSFUL,
-    VALIDATION_FAILED, 
-    
-    FILE_REQUIRED,
-    FILE_NOT_FOUND, 
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.validate.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- a/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/ValidateCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright 2012-2016 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.validate.command;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.cli.MissingArgumentException;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
-import com.redhat.thermostat.common.cli.Console;
-import com.redhat.thermostat.plugin.validator.PluginValidator;
-
-public class ValidateCommandTest {
-    
-    private ValidateCommand cmd;
-    private CommandContext ctxt;
-    private Arguments mockArgs;
-    private Console console;
-    private String fileName;
-    private List<String> list = new ArrayList<>();
-    private ByteArrayOutputStream outputBaos, errorBaos;
-    private PrintStream output, error;
-        
-    @Before
-    public void setUp() {
-        
-        cmd = new ValidateCommand();
-        ctxt = mock(CommandContext.class);
-        mockArgs = mock(Arguments.class);
-        console = mock(Console.class);
-
-        outputBaos = new ByteArrayOutputStream();
-        output = new PrintStream(outputBaos);
-        
-        errorBaos = new ByteArrayOutputStream();
-        error = new PrintStream(errorBaos);
-        
-        when(ctxt.getArguments()).thenReturn(mockArgs);
-        when(ctxt.getConsole()).thenReturn(console);
-        when(console.getError()).thenReturn(error);
-        when(console.getOutput()).thenReturn(output);
-        when(mockArgs.getNonOptionArguments()).thenReturn(list);
-        
-    }
-    
-    @Test
-    public void validateIncorrectFile() throws CommandException, MissingArgumentException {
-        fileName = PluginValidator.class.getResource("/incorrectPlugin.xml").getPath().toString();
-        list.add(fileName);
-        
-        cmd.run(ctxt);
-        String errorOutput = new String(errorBaos.toByteArray());
-        String validateOutput = buildErrorMessage();
-        
-        assertEquals(validateOutput, errorOutput);
-        assertEquals("", new String(outputBaos.toByteArray()));
-    }
-
-    @Test
-    public void validateCorrectFile() throws CommandException, MissingArgumentException {
-        fileName = PluginValidator.class.getResource("/correctPlugin.xml").getPath().toString();
-        list.add(fileName);
-        
-        cmd.run(ctxt);
-        
-        String expected = "Validation successful for file " + fileName + "\n\n";
-        String actual = new String(outputBaos.toByteArray());
-        assertEquals(expected, actual);
-        
-        assertEquals("", new String(errorBaos.toByteArray()));
-    }
-    
-    @Test
-    public void validateNonExistingFile() throws CommandException, MissingArgumentException {
-        fileName = "/nonExistingFile.xml";
-        list.add(fileName);
-        
-        try {
-            cmd.run(ctxt);    
-        } catch(CommandLineArgumentParseException clpae) {
-            // pass
-        }
-    }
-    
-    @Test
-    public void missingFileAsArgument() throws CommandException, MissingArgumentException {
-        
-        try {
-            cmd.run(ctxt);    
-        } catch(CommandLineArgumentParseException clpae) {
-            // pass
-        }
-    }
-    
-    @Test
-    public void testStorageRequired() {
-        assertFalse(cmd.isStorageRequired());
-    }
-    
-    private String buildErrorMessage() {
-        String LS = System.getProperty("line.separator");
-        StringBuilder builder = new StringBuilder();
-        
-        
-        builder.append("Error in file ").append(fileName).append(":10.60").append(LS);
-        builder.append("cvc-complex-type.2.4.b: The content of element 'bundle' is not complete. One of '{version}' is expected.").append(LS).append(LS);
-
-        builder.append("      <name>test</name>").append(LS);
-        builder.append("      <bundles>").append(LS);
-        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
-        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
-        builder.append("                                                          ^").append(LS);
-        builder.append("Error in file ").append(fileName).append(":11.29").append(LS);
-        builder.append("cvc-complex-type.2.3: Element 'bundle' cannot have character [children], because the type's content type is element-only.").append(LS).append(LS);
-
-        builder.append("      <bundles>").append(LS);
-        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
-        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
-        builder.append("        <bundle>baz</bundle>").append(LS);
-        builder.append("                           ^").append(LS);
-        builder.append("Error in file ").append(fileName).append(":11.29").append(LS);
-        builder.append("cvc-complex-type.2.4.b: The content of element 'bundle' is not complete. One of '{symbolic-name}' is expected.").append(LS).append(LS);
-
-        builder.append("      <bundles>").append(LS);
-        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
-        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
-        builder.append("        <bundle>baz</bundle>").append(LS);
-        builder.append("                           ^").append(LS);
-        builder.append("Error in file ").append(fileName).append(":13.21").append(LS);
-        builder.append("cvc-complex-type.2.4.d: Invalid content was found starting with element 'dependencies'. No child element is expected at this point.").append(LS).append(LS);
-
-        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
-        builder.append("        <bundle>baz</bundle>").append(LS);
-        builder.append("      </bundles>").append(LS);
-        builder.append("      <dependencies>").append(LS);
-        builder.append("                   ^").append(LS).append(LS);
-        builder.append("Validation failed for file ").append(fileName).append(LS).append(LS);
-
-        return builder.toString();
-    }
-
-}
-
--- a/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -42,7 +42,6 @@
 import org.junit.Test;
 
 import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.validate.command.ValidateCommand;
 
 public class ActivatorTest {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 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.validate.command.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ValidateCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012-2016 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.validate.command.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.cli.MissingArgumentException;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
+import com.redhat.thermostat.common.cli.Console;
+import com.redhat.thermostat.plugin.validator.PluginValidator;
+
+public class ValidateCommandTest {
+    
+    private ValidateCommand cmd;
+    private CommandContext ctxt;
+    private Arguments mockArgs;
+    private Console console;
+    private String fileName;
+    private List<String> list = new ArrayList<>();
+    private ByteArrayOutputStream outputBaos, errorBaos;
+    private PrintStream output, error;
+        
+    @Before
+    public void setUp() {
+        
+        cmd = new ValidateCommand();
+        ctxt = mock(CommandContext.class);
+        mockArgs = mock(Arguments.class);
+        console = mock(Console.class);
+
+        outputBaos = new ByteArrayOutputStream();
+        output = new PrintStream(outputBaos);
+        
+        errorBaos = new ByteArrayOutputStream();
+        error = new PrintStream(errorBaos);
+        
+        when(ctxt.getArguments()).thenReturn(mockArgs);
+        when(ctxt.getConsole()).thenReturn(console);
+        when(console.getError()).thenReturn(error);
+        when(console.getOutput()).thenReturn(output);
+        when(mockArgs.getNonOptionArguments()).thenReturn(list);
+        
+    }
+    
+    @Test
+    public void validateIncorrectFile() throws CommandException, MissingArgumentException {
+        fileName = PluginValidator.class.getResource("/incorrectPlugin.xml").getPath().toString();
+        list.add(fileName);
+        
+        cmd.run(ctxt);
+        String errorOutput = new String(errorBaos.toByteArray());
+        String validateOutput = buildErrorMessage();
+        
+        assertEquals(validateOutput, errorOutput);
+        assertEquals("", new String(outputBaos.toByteArray()));
+    }
+
+    @Test
+    public void validateCorrectFile() throws CommandException, MissingArgumentException {
+        fileName = PluginValidator.class.getResource("/correctPlugin.xml").getPath().toString();
+        list.add(fileName);
+        
+        cmd.run(ctxt);
+        
+        String expected = "Validation successful for file " + fileName + "\n\n";
+        String actual = new String(outputBaos.toByteArray());
+        assertEquals(expected, actual);
+        
+        assertEquals("", new String(errorBaos.toByteArray()));
+    }
+    
+    @Test
+    public void validateNonExistingFile() throws CommandException, MissingArgumentException {
+        fileName = "/nonExistingFile.xml";
+        list.add(fileName);
+        
+        try {
+            cmd.run(ctxt);    
+        } catch(CommandLineArgumentParseException clpae) {
+            // pass
+        }
+    }
+    
+    @Test
+    public void missingFileAsArgument() throws CommandException, MissingArgumentException {
+        
+        try {
+            cmd.run(ctxt);    
+        } catch(CommandLineArgumentParseException clpae) {
+            // pass
+        }
+    }
+    
+    @Test
+    public void testStorageRequired() {
+        assertFalse(cmd.isStorageRequired());
+    }
+    
+    private String buildErrorMessage() {
+        String LS = System.getProperty("line.separator");
+        StringBuilder builder = new StringBuilder();
+        
+        
+        builder.append("Error in file ").append(fileName).append(":10.60").append(LS);
+        builder.append("cvc-complex-type.2.4.b: The content of element 'bundle' is not complete. One of '{version}' is expected.").append(LS).append(LS);
+
+        builder.append("      <name>test</name>").append(LS);
+        builder.append("      <bundles>").append(LS);
+        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
+        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
+        builder.append("                                                          ^").append(LS);
+        builder.append("Error in file ").append(fileName).append(":11.29").append(LS);
+        builder.append("cvc-complex-type.2.3: Element 'bundle' cannot have character [children], because the type's content type is element-only.").append(LS).append(LS);
+
+        builder.append("      <bundles>").append(LS);
+        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
+        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
+        builder.append("        <bundle>baz</bundle>").append(LS);
+        builder.append("                           ^").append(LS);
+        builder.append("Error in file ").append(fileName).append(":11.29").append(LS);
+        builder.append("cvc-complex-type.2.4.b: The content of element 'bundle' is not complete. One of '{symbolic-name}' is expected.").append(LS).append(LS);
+
+        builder.append("      <bundles>").append(LS);
+        builder.append("        <bundle><symbolic-name>foo</symbolic-name><version>1</version></bundle>").append(LS);
+        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
+        builder.append("        <bundle>baz</bundle>").append(LS);
+        builder.append("                           ^").append(LS);
+        builder.append("Error in file ").append(fileName).append(":13.21").append(LS);
+        builder.append("cvc-complex-type.2.4.d: Invalid content was found starting with element 'dependencies'. No child element is expected at this point.").append(LS).append(LS);
+
+        builder.append("        <bundle><symbolic-name>bar</symbolic-name></bundle>").append(LS);
+        builder.append("        <bundle>baz</bundle>").append(LS);
+        builder.append("      </bundles>").append(LS);
+        builder.append("      <dependencies>").append(LS);
+        builder.append("                   ^").append(LS).append(LS);
+        builder.append("Validation failed for file ").append(fileName).append(LS).append(LS);
+
+        return builder.toString();
+    }
+
+}
+
--- a/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.validate.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/vm-classstat/client-swing/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/vm-classstat/client-swing/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -54,8 +54,8 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package>com.redhat.thermostat.vm.classstat.client.swing</Private-Package>
-            <Bundle-Activator>com.redhat.thermostat.vm.classstat.client.swing.Activator</Bundle-Activator>
+            <Private-Package>com.redhat.thermostat.vm.classstat.internal.client.swing</Private-Package>
+            <Bundle-Activator>com.redhat.thermostat.vm.classstat.internal.client.swing.Activator</Bundle-Activator>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.classstat.client.swing</Bundle-SymbolicName>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012-2016 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.classstat.client.swing;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
-
-public class Activator implements BundleActivator {
-
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        VmClassStatViewProvider viewProvider = new SwingVmClassStatViewProvider();
-        // Unregistered on Activator.stop
-        context.registerService(VmClassStatViewProvider.class.getName(), viewProvider, null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-    }
-}
-
--- a/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/SwingVmClassStatViewProvider.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012-2016 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.classstat.client.swing;
-
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
-
-
-public class SwingVmClassStatViewProvider implements VmClassStatViewProvider {
-
-    @Override
-    public VmClassStatView createView() {
-        return new VmClassStatPanel();
-    }
-}
-
--- a/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanel.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright 2012-2016 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.classstat.client.swing;
-
-import java.awt.Component;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import javax.swing.SwingUtilities;
-
-import com.redhat.thermostat.client.swing.EdtHelper;
-import com.redhat.thermostat.client.swing.SwingComponent;
-import com.redhat.thermostat.client.swing.components.HeaderPanel;
-import com.redhat.thermostat.client.swing.components.MultiChartPanel;
-import com.redhat.thermostat.client.swing.components.MultiChartPanel.DataGroup;
-import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier;
-import com.redhat.thermostat.common.Duration;
-import com.redhat.thermostat.common.model.Range;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
-import com.redhat.thermostat.vm.classstat.client.locale.LocaleResources;
-
-public class VmClassStatPanel extends VmClassStatView implements SwingComponent {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private final HeaderPanel visiblePanel;
-
-    private final MultiChartPanel multiChartPanel;
-
-    private DataGroup GROUP_NUMBER;
-    private DataGroup GROUP_SIZE;
-
-    public VmClassStatPanel() {
-        visiblePanel = new HeaderPanel();
-
-        visiblePanel.setHeader(t.localize(LocaleResources.VM_CLASSES_HEADER));
-
-        String xAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_TIME_LABEL).getContents();
-        String classesAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_CLASSES_LABEL).getContents();
-        String sizeAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_SIZE_LABEL).getContents();
-
-        multiChartPanel = new MultiChartPanel();
-
-        GROUP_NUMBER = multiChartPanel.createGroup();
-        GROUP_SIZE = multiChartPanel.createGroup();
-
-        multiChartPanel.setDomainAxisLabel(xAxisLabel);
-
-        multiChartPanel.getRangeAxis(GROUP_NUMBER).setLabel(classesAxisLabel);
-        multiChartPanel.getRangeAxis(GROUP_SIZE).setLabel(sizeAxisLabel);
-
-        visiblePanel.setContent(multiChartPanel);
-
-        new ComponentVisibilityNotifier().initialize(visiblePanel, notifier);
-    }
-
-    @Override
-    public void addClassChart(final Group group, final String tag, final LocalizedString name) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                multiChartPanel.addChart(getGroup(group), tag, name);
-                multiChartPanel.showChart(getGroup(group), tag);
-            }
-        });
-    }
-    @Override
-    public void removeClassChart(final Group group, final String tag) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                multiChartPanel.hideChart(getGroup(group), tag);
-                multiChartPanel.removeChart(getGroup(group), tag);
-            }
-        });
-    }
-
-    private MultiChartPanel.DataGroup getGroup(Group group) {
-        switch (group) {
-        case NUMBER:
-            return GROUP_NUMBER;
-        case SIZE:
-            return GROUP_SIZE;
-        default:
-            throw new AssertionError("Unknown data group");
-        }
-    }
-
-    @Override
-    public void addClassData(final String tag, final List<DiscreteTimeData<? extends Number>> data) {
-        final List<DiscreteTimeData<? extends Number>> copy = new ArrayList<>(data);
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                multiChartPanel.addData(tag, copy);
-            }
-        });
-    }
-
-    @Override
-    public void clearClassData(final String tag) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                multiChartPanel.clearData(tag);
-            }
-        });
-    }
-
-    @Override
-    public Duration getUserDesiredDuration() {
-        try {
-            return new EdtHelper().callAndWait(new Callable<Duration>() {
-                @Override
-                public Duration call() throws Exception {
-                    return multiChartPanel.getUserDesiredDuration();
-                }
-            });
-        } catch (InvocationTargetException | InterruptedException e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public void setAvailableDataRange(final Range<Long> availableDataRange) {
-        // FIXME indicate the total data range to the user somehow
-    }
-
-    @Override
-    public Component getUiComponent() {
-        return visiblePanel;
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2016 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.classstat.internal.client.swing;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
+
+public class Activator implements BundleActivator {
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        VmClassStatViewProvider viewProvider = new SwingVmClassStatViewProvider();
+        // Unregistered on Activator.stop
+        context.registerService(VmClassStatViewProvider.class.getName(), viewProvider, null);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/SwingVmClassStatViewProvider.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-2016 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.classstat.internal.client.swing;
+
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
+
+
+public class SwingVmClassStatViewProvider implements VmClassStatViewProvider {
+
+    @Override
+    public VmClassStatView createView() {
+        return new VmClassStatPanel();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/internal/client/swing/VmClassStatPanel.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012-2016 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.classstat.internal.client.swing;
+
+import java.awt.Component;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.swing.SwingUtilities;
+
+import com.redhat.thermostat.client.swing.EdtHelper;
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.HeaderPanel;
+import com.redhat.thermostat.client.swing.components.MultiChartPanel;
+import com.redhat.thermostat.client.swing.components.MultiChartPanel.DataGroup;
+import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier;
+import com.redhat.thermostat.common.Duration;
+import com.redhat.thermostat.common.model.Range;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
+import com.redhat.thermostat.vm.classstat.client.locale.LocaleResources;
+
+public class VmClassStatPanel extends VmClassStatView implements SwingComponent {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private final HeaderPanel visiblePanel;
+
+    private final MultiChartPanel multiChartPanel;
+
+    private DataGroup GROUP_NUMBER;
+    private DataGroup GROUP_SIZE;
+
+    public VmClassStatPanel() {
+        visiblePanel = new HeaderPanel();
+
+        visiblePanel.setHeader(t.localize(LocaleResources.VM_CLASSES_HEADER));
+
+        String xAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_TIME_LABEL).getContents();
+        String classesAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_CLASSES_LABEL).getContents();
+        String sizeAxisLabel = t.localize(LocaleResources.VM_CLASSES_CHART_SIZE_LABEL).getContents();
+
+        multiChartPanel = new MultiChartPanel();
+
+        GROUP_NUMBER = multiChartPanel.createGroup();
+        GROUP_SIZE = multiChartPanel.createGroup();
+
+        multiChartPanel.setDomainAxisLabel(xAxisLabel);
+
+        multiChartPanel.getRangeAxis(GROUP_NUMBER).setLabel(classesAxisLabel);
+        multiChartPanel.getRangeAxis(GROUP_SIZE).setLabel(sizeAxisLabel);
+
+        visiblePanel.setContent(multiChartPanel);
+
+        new ComponentVisibilityNotifier().initialize(visiblePanel, notifier);
+    }
+
+    @Override
+    public void addClassChart(final Group group, final String tag, final LocalizedString name) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                multiChartPanel.addChart(getGroup(group), tag, name);
+                multiChartPanel.showChart(getGroup(group), tag);
+            }
+        });
+    }
+    @Override
+    public void removeClassChart(final Group group, final String tag) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                multiChartPanel.hideChart(getGroup(group), tag);
+                multiChartPanel.removeChart(getGroup(group), tag);
+            }
+        });
+    }
+
+    private MultiChartPanel.DataGroup getGroup(Group group) {
+        switch (group) {
+        case NUMBER:
+            return GROUP_NUMBER;
+        case SIZE:
+            return GROUP_SIZE;
+        default:
+            throw new AssertionError("Unknown data group");
+        }
+    }
+
+    @Override
+    public void addClassData(final String tag, final List<DiscreteTimeData<? extends Number>> data) {
+        final List<DiscreteTimeData<? extends Number>> copy = new ArrayList<>(data);
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                multiChartPanel.addData(tag, copy);
+            }
+        });
+    }
+
+    @Override
+    public void clearClassData(final String tag) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                multiChartPanel.clearData(tag);
+            }
+        });
+    }
+
+    @Override
+    public Duration getUserDesiredDuration() {
+        try {
+            return new EdtHelper().callAndWait(new Callable<Duration>() {
+                @Override
+                public Duration call() throws Exception {
+                    return multiChartPanel.getUserDesiredDuration();
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public void setAvailableDataRange(final Range<Long> availableDataRange) {
+        // FIXME indicate the total data range to the user somehow
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return visiblePanel;
+    }
+}
+
--- a/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/ActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012-2016 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.classstat.client.swing;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
-
-public class ActivatorTest {
-
-    @Test
-    public void verifyStartRegistersViewProvider() throws Exception {
-        StubBundleContext ctx = new StubBundleContext();
-        Activator activator = new Activator();
-        activator.start(ctx);
-        assertTrue(ctx.isServiceRegistered(VmClassStatViewProvider.class.getName(), SwingVmClassStatViewProvider.class));
-        assertEquals(1, ctx.getAllServices().size());
-    }
-}
-
--- a/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanelTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012-2016 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.classstat.client.swing;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
-
-public class VmClassStatPanelTest {
-
-    public static void main(String[] args) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                JFrame frame = new JFrame("Test");
-
-                VmClassStatPanel classPanel = new VmClassStatPanel();
-
-                List<DiscreteTimeData<? extends Number>> data = new ArrayList<DiscreteTimeData<? extends Number>>();
-                data.add(new DiscreteTimeData<>(new Date().getTime(), 10l));
-                data.add(new DiscreteTimeData<>(new Date().getTime() + TimeUnit.MINUTES.toMillis(1), 1000l));
-
-                classPanel.addClassChart(VmClassStatView.Group.NUMBER, "classes", new LocalizedString("classes"));
-                classPanel.addClassData("classes", data);
-
-                List<DiscreteTimeData<? extends Number>> data2 = new ArrayList<DiscreteTimeData<? extends Number>>();
-                data2.add(new DiscreteTimeData<Number>(new Date().getTime(), 10));
-                data2.add(new DiscreteTimeData<Number>(new Date().getTime() + TimeUnit.MINUTES.toMillis(1), 20));
-                classPanel.addClassChart(VmClassStatView.Group.SIZE, "size", new LocalizedString("size"));
-                classPanel.addClassData("size", data2);
-
-                frame.add(classPanel.getUiComponent());
-                frame.pack();
-                frame.setVisible(true);
-                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-            }
-        });
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/internal/client/swing/ActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-2016 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.classstat.internal.client.swing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.StubBundleContext;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
+
+public class ActivatorTest {
+
+    @Test
+    public void verifyStartRegistersViewProvider() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        Activator activator = new Activator();
+        activator.start(ctx);
+        assertTrue(ctx.isServiceRegistered(VmClassStatViewProvider.class.getName(), SwingVmClassStatViewProvider.class));
+        assertEquals(1, ctx.getAllServices().size());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/internal/client/swing/VmClassStatPanelTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-2016 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.classstat.internal.client.swing;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
+
+public class VmClassStatPanelTest {
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                JFrame frame = new JFrame("Test");
+
+                VmClassStatPanel classPanel = new VmClassStatPanel();
+
+                List<DiscreteTimeData<? extends Number>> data = new ArrayList<DiscreteTimeData<? extends Number>>();
+                data.add(new DiscreteTimeData<>(new Date().getTime(), 10l));
+                data.add(new DiscreteTimeData<>(new Date().getTime() + TimeUnit.MINUTES.toMillis(1), 1000l));
+
+                classPanel.addClassChart(VmClassStatView.Group.NUMBER, "classes", new LocalizedString("classes"));
+                classPanel.addClassData("classes", data);
+
+                List<DiscreteTimeData<? extends Number>> data2 = new ArrayList<DiscreteTimeData<? extends Number>>();
+                data2.add(new DiscreteTimeData<Number>(new Date().getTime(), 10));
+                data2.add(new DiscreteTimeData<Number>(new Date().getTime() + TimeUnit.MINUTES.toMillis(1), 20));
+                classPanel.addClassChart(VmClassStatView.Group.SIZE, "size", new LocalizedString("size"));
+                classPanel.addClassData("size", data2);
+
+                frame.add(classPanel.getUiComponent());
+                frame.pack();
+                frame.setVisible(true);
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+            }
+        });
+    }
+}
+
--- a/vm-compiler/client-swing/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/vm-compiler/client-swing/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -54,8 +54,8 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package>com.redhat.thermostat.vm.compiler.client.swing</Private-Package>
-            <Bundle-Activator>com.redhat.thermostat.vm.compiler.client.swing.Activator</Bundle-Activator>
+            <Private-Package>com.redhat.thermostat.vm.compiler.client.swing.internal</Private-Package>
+            <Bundle-Activator>com.redhat.thermostat.vm.compiler.client.swing.internal.Activator</Bundle-Activator>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.compiler.client.swing</Bundle-SymbolicName>
             <!-- Do not autogenerate uses clauses in Manifests -->
--- a/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/Activator.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012-2016 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.compiler.client.swing;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
-
-public class Activator implements BundleActivator {
-
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        VmCompilerStatViewProvider viewProvider = new SwingVmCompilerStatViewProvider();
-        // Unregistered on Activator.stop
-        context.registerService(VmCompilerStatViewProvider.class.getName(), viewProvider, null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-    }
-}
-
--- a/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatView.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
- * Copyright 2012-2016 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.compiler.client.swing;
-
-import java.awt.Component;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import javax.swing.JSplitPane;
-import javax.swing.SwingUtilities;
-import javax.swing.table.DefaultTableModel;
-
-import com.redhat.thermostat.client.swing.EdtHelper;
-import com.redhat.thermostat.client.swing.NonEditableTableModel;
-import com.redhat.thermostat.client.swing.SwingComponent;
-import com.redhat.thermostat.client.swing.components.HeaderPanel;
-import com.redhat.thermostat.client.swing.components.MultiChartPanel;
-import com.redhat.thermostat.client.swing.components.MultiChartPanel.DataGroup;
-import com.redhat.thermostat.client.swing.components.ThermostatScrollPane;
-import com.redhat.thermostat.client.swing.components.ThermostatTable;
-import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier;
-import com.redhat.thermostat.common.Duration;
-import com.redhat.thermostat.common.model.Range;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView;
-import com.redhat.thermostat.vm.compiler.client.locale.LocaleResources;
-
-public class SwingVmCompilerStatView extends VmCompilerStatView implements SwingComponent {
-
-    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
-
-    private final HeaderPanel visiblePanel;
-
-    private DefaultTableModel model;
-    private MultiChartPanel multiChart;
-
-    private DataGroup numberGroup;
-    private DataGroup timeGroup;
-
-    public SwingVmCompilerStatView() {
-        visiblePanel = new HeaderPanel();
-
-        visiblePanel.setHeader(t.localize(LocaleResources.VM_COMPILER_HEADER));
-
-        JSplitPane splitPane = new JSplitPane();
-        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
-        splitPane.setOneTouchExpandable(true);
-
-        visiblePanel.setContent(splitPane);
-
-        model = createTableModel();
-
-        ThermostatTable table = new ThermostatTable(model);
-        ThermostatScrollPane tablePane = new ThermostatScrollPane(table);
-
-        splitPane.setTopComponent(tablePane);
-
-        multiChart = new MultiChartPanel();
-        numberGroup = multiChart.createGroup();
-        timeGroup = multiChart.createGroup();
-
-        splitPane.setBottomComponent(multiChart);
-        splitPane.setResizeWeight(0.5);
-
-        new ComponentVisibilityNotifier().initialize(visiblePanel, notifier);
-
-        addChartTypes();
-    }
-
-    private DefaultTableModel createTableModel() {
-        DefaultTableModel model = new NonEditableTableModel(11, 2);
-        Object[] columnIdentifiers = new Object[] {
-                t.localize(LocaleResources.STATS_TABLE_COLUMN_NAME).getContents(),
-                t.localize(LocaleResources.STATS_TABLE_COLUMN_VALUE).getContents()
-        };
-        Object[][] dataVector = new Object[][] {
-            new Object[] { t.localize(LocaleResources.STATS_TOTAL_COMPILES).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_TOTAL_BAILOUTS).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_TOTAL_INVALIDATES).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_COMPILATION_TIME).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_LAST_SIZE).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_LAST_TYPE).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_LAST_METHOD).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_LAST_FAILED_TYPE).getContents(), 0 },
-            new Object[] { t.localize(LocaleResources.STATS_LAST_FAILED_METHOD).getContents(), 0 },
-        };
-        model.setDataVector(dataVector, columnIdentifiers);
-        return model;
-    }
-
-    private void addChartTypes() {
-        for (Type type : Type.values()) {
-            DataGroup group = getGroup(type);
-            String tag = getTag(type);
-            multiChart.addChart(group, tag, type.getLabel());
-            multiChart.showChart(group, tag);
-        }
-
-        multiChart.getRangeAxis(numberGroup).setLabel(
-                t.localize(LocaleResources.STAT_CHART_NUMBER_AXIS).getContents());
-        multiChart.getRangeAxis(timeGroup).setLabel(
-                t.localize(LocaleResources.STAT_CHART_TIME_AXIS).getContents());
-    }
-
-    @Override
-    public void setCurrentDisplay(final ViewData data) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                final int VALUE_COLUMN = 1;
-
-                String[] values = {
-                        data.totalCompiles,
-                        data.totalBailouts,
-                        data.totalInvalidates,
-                        data.compilationTime,
-                        data.lastSize,
-                        data.lastType,
-                        data.lastMethod,
-                        data.lastFailedType,
-                        data.lastFailedMethod,
-                };
-
-                int row = 0;
-                for (String value : values) {
-                    model.setValueAt(value, row, VALUE_COLUMN);
-                    row++;
-                }
-            }
-
-        });
-    }
-
-    @Override
-    public Duration getUserDesiredDuration() {
-        try {
-            return new EdtHelper().callAndWait(new Callable<Duration>(){
-                public Duration call() {
-                    return multiChart.getUserDesiredDuration();
-                }
-            });
-        } catch (InvocationTargetException | InterruptedException e) {
-            return null;
-        }
-    }
-
-    @Override
-    public void setAvailableDataRange(Range<Long> availableDataRange) {
-        // TODO
-    }
-
-    @Override
-    public void addCompilerData(final Type type, final List<DiscreteTimeData<? extends Number>> data) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                String tag = getTag(type);
-                multiChart.addData(tag, data);
-            }
-        });
-    }
-
-    @Override
-    public void clearCompilerData(final Type type) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                String tag = getTag(type);
-                multiChart.clearData(tag);
-            }
-        });
-    }
-
-    private DataGroup getGroup(final Type type) {
-        final DataGroup group;
-        if (type == Type.TOTAL_BAILOUTS || type == Type.TOTAL_COMPILES || type == Type.TOTAL_INVALIDATES) {
-            group = numberGroup;
-        } else {
-            group = timeGroup;
-        }
-        return group;
-    }
-
-    private String getTag(final Type type) {
-        return type.name();
-    }
-
-    @Override
-    public Component getUiComponent() {
-        return visiblePanel;
-    }
-
-}
--- a/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatViewProvider.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012-2016 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.compiler.client.swing;
-
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView;
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
-
-
-public class SwingVmCompilerStatViewProvider implements VmCompilerStatViewProvider {
-
-    @Override
-    public VmCompilerStatView createView() {
-        return new SwingVmCompilerStatView();
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/Activator.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2016 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.compiler.client.swing.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
+
+public class Activator implements BundleActivator {
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        VmCompilerStatViewProvider viewProvider = new SwingVmCompilerStatViewProvider();
+        // Unregistered on Activator.stop
+        context.registerService(VmCompilerStatViewProvider.class.getName(), viewProvider, null);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatView.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2012-2016 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.compiler.client.swing.internal;
+
+import java.awt.Component;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.swing.JSplitPane;
+import javax.swing.SwingUtilities;
+import javax.swing.table.DefaultTableModel;
+
+import com.redhat.thermostat.client.swing.EdtHelper;
+import com.redhat.thermostat.client.swing.NonEditableTableModel;
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.HeaderPanel;
+import com.redhat.thermostat.client.swing.components.MultiChartPanel;
+import com.redhat.thermostat.client.swing.components.MultiChartPanel.DataGroup;
+import com.redhat.thermostat.client.swing.components.ThermostatScrollPane;
+import com.redhat.thermostat.client.swing.components.ThermostatTable;
+import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier;
+import com.redhat.thermostat.common.Duration;
+import com.redhat.thermostat.common.model.Range;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView;
+import com.redhat.thermostat.vm.compiler.client.locale.LocaleResources;
+
+public class SwingVmCompilerStatView extends VmCompilerStatView implements SwingComponent {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+
+    private final HeaderPanel visiblePanel;
+
+    private DefaultTableModel model;
+    private MultiChartPanel multiChart;
+
+    private DataGroup numberGroup;
+    private DataGroup timeGroup;
+
+    public SwingVmCompilerStatView() {
+        visiblePanel = new HeaderPanel();
+
+        visiblePanel.setHeader(t.localize(LocaleResources.VM_COMPILER_HEADER));
+
+        JSplitPane splitPane = new JSplitPane();
+        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
+        splitPane.setOneTouchExpandable(true);
+
+        visiblePanel.setContent(splitPane);
+
+        model = createTableModel();
+
+        ThermostatTable table = new ThermostatTable(model);
+        ThermostatScrollPane tablePane = new ThermostatScrollPane(table);
+
+        splitPane.setTopComponent(tablePane);
+
+        multiChart = new MultiChartPanel();
+        numberGroup = multiChart.createGroup();
+        timeGroup = multiChart.createGroup();
+
+        splitPane.setBottomComponent(multiChart);
+        splitPane.setResizeWeight(0.5);
+
+        new ComponentVisibilityNotifier().initialize(visiblePanel, notifier);
+
+        addChartTypes();
+    }
+
+    private DefaultTableModel createTableModel() {
+        DefaultTableModel model = new NonEditableTableModel(11, 2);
+        Object[] columnIdentifiers = new Object[] {
+                t.localize(LocaleResources.STATS_TABLE_COLUMN_NAME).getContents(),
+                t.localize(LocaleResources.STATS_TABLE_COLUMN_VALUE).getContents()
+        };
+        Object[][] dataVector = new Object[][] {
+            new Object[] { t.localize(LocaleResources.STATS_TOTAL_COMPILES).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_TOTAL_BAILOUTS).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_TOTAL_INVALIDATES).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_COMPILATION_TIME).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_LAST_SIZE).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_LAST_TYPE).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_LAST_METHOD).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_LAST_FAILED_TYPE).getContents(), 0 },
+            new Object[] { t.localize(LocaleResources.STATS_LAST_FAILED_METHOD).getContents(), 0 },
+        };
+        model.setDataVector(dataVector, columnIdentifiers);
+        return model;
+    }
+
+    private void addChartTypes() {
+        for (Type type : Type.values()) {
+            DataGroup group = getGroup(type);
+            String tag = getTag(type);
+            multiChart.addChart(group, tag, type.getLabel());
+            multiChart.showChart(group, tag);
+        }
+
+        multiChart.getRangeAxis(numberGroup).setLabel(
+                t.localize(LocaleResources.STAT_CHART_NUMBER_AXIS).getContents());
+        multiChart.getRangeAxis(timeGroup).setLabel(
+                t.localize(LocaleResources.STAT_CHART_TIME_AXIS).getContents());
+    }
+
+    @Override
+    public void setCurrentDisplay(final ViewData data) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                final int VALUE_COLUMN = 1;
+
+                String[] values = {
+                        data.totalCompiles,
+                        data.totalBailouts,
+                        data.totalInvalidates,
+                        data.compilationTime,
+                        data.lastSize,
+                        data.lastType,
+                        data.lastMethod,
+                        data.lastFailedType,
+                        data.lastFailedMethod,
+                };
+
+                int row = 0;
+                for (String value : values) {
+                    model.setValueAt(value, row, VALUE_COLUMN);
+                    row++;
+                }
+            }
+
+        });
+    }
+
+    @Override
+    public Duration getUserDesiredDuration() {
+        try {
+            return new EdtHelper().callAndWait(new Callable<Duration>(){
+                public Duration call() {
+                    return multiChart.getUserDesiredDuration();
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public void setAvailableDataRange(Range<Long> availableDataRange) {
+        // TODO
+    }
+
+    @Override
+    public void addCompilerData(final Type type, final List<DiscreteTimeData<? extends Number>> data) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                String tag = getTag(type);
+                multiChart.addData(tag, data);
+            }
+        });
+    }
+
+    @Override
+    public void clearCompilerData(final Type type) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                String tag = getTag(type);
+                multiChart.clearData(tag);
+            }
+        });
+    }
+
+    private DataGroup getGroup(final Type type) {
+        final DataGroup group;
+        if (type == Type.TOTAL_BAILOUTS || type == Type.TOTAL_COMPILES || type == Type.TOTAL_INVALIDATES) {
+            group = numberGroup;
+        } else {
+            group = timeGroup;
+        }
+        return group;
+    }
+
+    private String getTag(final Type type) {
+        return type.name();
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return visiblePanel;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-compiler/client-swing/src/main/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatViewProvider.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-2016 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.compiler.client.swing.internal;
+
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView;
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
+
+
+public class SwingVmCompilerStatViewProvider implements VmCompilerStatViewProvider {
+
+    @Override
+    public VmCompilerStatView createView() {
+        return new SwingVmCompilerStatView();
+    }
+}
+
--- a/vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/ActivatorTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012-2016 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.compiler.client.swing;
-
-import static com.redhat.thermostat.testutils.Asserts.assertServiceIsRegistered;
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
-import com.redhat.thermostat.vm.compiler.client.swing.Activator;
-import com.redhat.thermostat.vm.compiler.client.swing.SwingVmCompilerStatViewProvider;
-
-public class ActivatorTest {
-
-    @Test
-    public void verifyStartRegistersViewProvider() throws Exception {
-        StubBundleContext ctx = new StubBundleContext();
-        Activator activator = new Activator();
-        activator.start(ctx);
-
-        assertServiceIsRegistered(ctx, VmCompilerStatViewProvider.class, SwingVmCompilerStatViewProvider.class);
-
-        assertEquals(1, ctx.getAllServices().size());
-    }
-}
-
--- a/vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/SwingVmCompilerStatViewTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright 2012-2016 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.compiler.client.swing;
-
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-
-import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView.ViewData;
-
-public class SwingVmCompilerStatViewTest {
-
-    public static void main(String[] args) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-
-                JFrame frame = new JFrame("Test");
-
-                SwingVmCompilerStatView compilerPanel = new SwingVmCompilerStatView();
-
-                int totalCompiles = 200;
-                int totalBailouts = 10;
-                int totalInvalidates = 5;
-
-                String compilationTime = "12.3 s";
-
-                String lastSize = "10 bytes";
-                String lastType = "OSR Compile";
-                String lastMethod = "org.foo.Bar.lastMethod()";
-
-                String lastFailedType = "Native Compile";
-                String lastFailedMethod = "org.Baz.lastFailedMethod()";
-
-                ViewData data = new ViewData();
-                data.totalCompiles = String.valueOf(totalCompiles);
-                data.totalBailouts = String.valueOf(totalBailouts);
-                data.totalInvalidates = String.valueOf(totalInvalidates);
-                data.compilationTime = compilationTime;
-                data.lastSize = lastSize;
-                data.lastType = lastType;
-                data.lastMethod = lastMethod;
-                data.lastFailedType = lastFailedType;
-                data.lastFailedType = lastFailedMethod;
-
-                compilerPanel.setCurrentDisplay(data);
-
-                frame.add(compilerPanel.getUiComponent());
-                frame.pack();
-                frame.setVisible(true);
-                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-            }
-        });
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/internal/ActivatorTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-2016 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.compiler.client.swing.internal;
+
+import static com.redhat.thermostat.testutils.Asserts.assertServiceIsRegistered;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.StubBundleContext;
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatViewProvider;
+
+public class ActivatorTest {
+
+    @Test
+    public void verifyStartRegistersViewProvider() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        Activator activator = new Activator();
+        activator.start(ctx);
+
+        assertServiceIsRegistered(ctx, VmCompilerStatViewProvider.class, SwingVmCompilerStatViewProvider.class);
+
+        assertEquals(1, ctx.getAllServices().size());
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-compiler/client-swing/src/test/java/com/redhat/thermostat/vm/compiler/client/swing/internal/SwingVmCompilerStatViewTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012-2016 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.compiler.client.swing.internal;
+
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import com.redhat.thermostat.vm.compiler.client.core.VmCompilerStatView.ViewData;
+
+public class SwingVmCompilerStatViewTest {
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+
+                JFrame frame = new JFrame("Test");
+
+                SwingVmCompilerStatView compilerPanel = new SwingVmCompilerStatView();
+
+                int totalCompiles = 200;
+                int totalBailouts = 10;
+                int totalInvalidates = 5;
+
+                String compilationTime = "12.3 s";
+
+                String lastSize = "10 bytes";
+                String lastType = "OSR Compile";
+                String lastMethod = "org.foo.Bar.lastMethod()";
+
+                String lastFailedType = "Native Compile";
+                String lastFailedMethod = "org.Baz.lastFailedMethod()";
+
+                ViewData data = new ViewData();
+                data.totalCompiles = String.valueOf(totalCompiles);
+                data.totalBailouts = String.valueOf(totalBailouts);
+                data.totalInvalidates = String.valueOf(totalInvalidates);
+                data.compilationTime = compilationTime;
+                data.lastSize = lastSize;
+                data.lastType = lastType;
+                data.lastMethod = lastMethod;
+                data.lastFailedType = lastFailedType;
+                data.lastFailedType = lastFailedMethod;
+
+                compilerPanel.setCurrentDisplay(data);
+
+                frame.add(compilerPanel.getUiComponent());
+                frame.pack();
+                frame.setVisible(true);
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+            }
+        });
+    }
+}
+
--- a/vm-cpu/agent/src/test/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuStatBuilderTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-cpu/agent/src/test/java/com/redhat/thermostat/vm/cpu/agent/internal/VmCpuStatBuilderTest.java	Tue May 03 15:49:54 2016 +0200
@@ -48,8 +48,8 @@
 import org.junit.Test;
 
 import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.internal.test.Bug;
 import com.redhat.thermostat.storage.core.WriterID;
-import com.redhat.thermostat.test.Bug;
 import com.redhat.thermostat.vm.cpu.common.model.VmCpuStat;
 
 public class VmCpuStatBuilderTest {
--- a/vm-find/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/vm-find/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -119,7 +119,6 @@
             <Export-Package/>
             <Private-Package>
               com.redhat.thermostat.vm.find.command.internal,
-              com.redhat.thermostat.vm.find.command.locale
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -57,7 +57,6 @@
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.HostInfo;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.vm.find.command.locale.LocaleResources;
 
 public class FindVmCommand extends AbstractCommand {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-2016 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.find.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    COMMAND_INTERRUPTED,
+    AGENT_SERVICE_UNAVAILABLE,
+    HOST_SERVICE_UNAVAILABLE,
+    VM_SERVICE_UNAVAILABLE,
+    NO_CRITERIA_GIVEN,
+    AGENT_FLAGS_CLASH,
+    UNRECOGNIZED_ARGUMENT,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.vm.find.command.locale.strings";
+
+    public static Translate<LocaleResources> createTranslator() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
--- a/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/UnrecognizedArgumentException.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/UnrecognizedArgumentException.java	Tue May 03 15:49:54 2016 +0200
@@ -38,7 +38,6 @@
 
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.vm.find.command.locale.LocaleResources;
 
 import java.util.Collection;
 
--- a/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/VmCriterion.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/internal/VmCriterion.java	Tue May 03 15:49:54 2016 +0200
@@ -37,7 +37,6 @@
 package com.redhat.thermostat.vm.find.command.internal;
 
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.vm.find.command.locale.LocaleResources;
 
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
--- a/vm-find/command/src/main/java/com/redhat/thermostat/vm/find/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012-2016 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.find.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    COMMAND_INTERRUPTED,
-    AGENT_SERVICE_UNAVAILABLE,
-    HOST_SERVICE_UNAVAILABLE,
-    VM_SERVICE_UNAVAILABLE,
-    NO_CRITERIA_GIVEN,
-    AGENT_FLAGS_CLASH,
-    UNRECOGNIZED_ARGUMENT,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.vm.find.command.locale.strings";
-
-    public static Translate<LocaleResources> createTranslator() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
--- a/vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/internal/FindVmCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -60,6 +60,7 @@
 import com.redhat.thermostat.client.cli.AgentArgument;
 import com.redhat.thermostat.common.cli.Arguments;
 import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
@@ -68,7 +69,6 @@
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.HostInfo;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 
 public class FindVmCommandTest {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012-2016 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.find.command.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+}
--- a/vm-find/command/src/test/java/com/redhat/thermostat/vm/find/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012-2016 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.find.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-}
--- a/vm-gc/command/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -128,7 +128,6 @@
             <Export-Package/>
             <Private-Package>
               com.redhat.thermostat.vm.gc.command.internal,
-              com.redhat.thermostat.vm.gc.command.locale,
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- a/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -54,7 +54,6 @@
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.VmInfo;
 import com.redhat.thermostat.storage.model.VmInfo.AliveStatus;
-import com.redhat.thermostat.vm.gc.command.locale.LocaleResources;
 
 public class GCCommand extends AbstractCommand {
 
--- a/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListener.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandListener.java	Tue May 03 15:49:54 2016 +0200
@@ -47,7 +47,6 @@
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.vm.gc.command.locale.LocaleResources;
 
 public class GCCommandListener implements RequestResponseListener {
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012-2016 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.gc.command.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    GCREQUEST_SERVICE_UNAVAILABLE,
+    GC_FAILED,
+    AGENT_SERVICE_UNAVAILABLE,
+    VM_SERVICE_UNAVAILABLE,
+    LISTENER_UNAVAILABLE,
+    VM_NOT_FOUND,
+    VM_NOT_ALIVE,
+    COMMAND_INTERRUPTED,
+    GC_ERROR_RESULT,
+    GC_SUCCESS_RESULT,
+    GC_UNKNOWN_RESULT,
+    GC_STAT_DAO_SERVICE_UNAVAILABLE,
+    GC_COMMON_NAME_SUCCESS_MSG,
+    GC_PARAMS_MESSAGE,
+    GC_PARAMS_FAILURE_MESSAGE,
+    GC_PARAMS_HEADER_FLAG,
+    GC_PARAMS_HEADER_DESC,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.gc.command.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
--- a/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java	Tue May 03 15:49:54 2016 +0200
@@ -56,7 +56,6 @@
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.vm.gc.command.locale.LocaleResources;
 import com.redhat.thermostat.vm.gc.common.GcCommonNameMapper;
 import com.redhat.thermostat.vm.gc.common.GcCommonNameMapper.CollectorCommonName;
 import com.redhat.thermostat.vm.gc.common.params.GcParamsMapper;
--- a/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2012-2016 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.gc.command.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    GCREQUEST_SERVICE_UNAVAILABLE,
-    GC_FAILED,
-    AGENT_SERVICE_UNAVAILABLE,
-    VM_SERVICE_UNAVAILABLE,
-    LISTENER_UNAVAILABLE,
-    VM_NOT_FOUND,
-    VM_NOT_ALIVE,
-    COMMAND_INTERRUPTED,
-    GC_ERROR_RESULT,
-    GC_SUCCESS_RESULT,
-    GC_UNKNOWN_RESULT,
-    GC_STAT_DAO_SERVICE_UNAVAILABLE,
-    GC_COMMON_NAME_SUCCESS_MSG,
-    GC_PARAMS_MESSAGE,
-    GC_PARAMS_FAILURE_MESSAGE,
-    GC_PARAMS_HEADER_FLAG,
-    GC_PARAMS_HEADER_DESC,
-    ;
-
-    static final String RESOURCE_BUNDLE =
-            "com.redhat.thermostat.gc.command.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
--- a/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/GCCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -52,6 +52,7 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.gc.remote.common.GCRequest;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmId;
@@ -60,7 +61,6 @@
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 
 public class GCCommandTest {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-2016 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.gc.command.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+}
--- a/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,10 +53,10 @@
 import com.redhat.thermostat.client.cli.VmArgument;
 import com.redhat.thermostat.common.cli.Arguments;
 import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.vm.gc.common.GcCommonNameMapper;
 import com.redhat.thermostat.vm.gc.common.VmGcStatDAO;
 import com.redhat.thermostat.vm.gc.common.params.GcParam;
--- a/vm-gc/command/src/test/java/com/redhat/thermostat/vm/gc/command/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012-2016 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.gc.command.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-}
--- a/vm-gc/common/pom.xml	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/common/pom.xml	Tue May 03 15:49:54 2016 +0200
@@ -84,7 +84,6 @@
             </Export-Package>
             <Private-Package>
               com.redhat.thermostat.vm.gc.common.internal,
-              com.redhat.thermostat.vm.gc.common.locale
             </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/LocaleResources.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012-2016 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.gc.common.internal;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+public enum LocaleResources {
+
+    VALIDATION_FAILED,
+    VALIDATION_WARNING,
+    VALIDATION_ERROR,
+    VALIDATION_FATAL_ERROR,
+    ;
+
+    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.vm.gc.common.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
--- a/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/locale/LocaleResources.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.gc.common.locale;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-public enum LocaleResources {
-
-    VALIDATION_FAILED,
-    VALIDATION_WARNING,
-    VALIDATION_ERROR,
-    VALIDATION_FATAL_ERROR,
-    ;
-
-    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.vm.gc.common.locale.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
--- a/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/GcParamsMapper.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/GcParamsMapper.java	Tue May 03 15:49:54 2016 +0200
@@ -39,7 +39,7 @@
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.vm.gc.common.GcCommonNameMapper;
-import com.redhat.thermostat.vm.gc.common.locale.LocaleResources;
+import com.redhat.thermostat.vm.gc.common.internal.LocaleResources;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
--- a/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/ValidationErrorsFormatter.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/params/ValidationErrorsFormatter.java	Tue May 03 15:49:54 2016 +0200
@@ -37,7 +37,7 @@
 package com.redhat.thermostat.vm.gc.common.params;
 
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.vm.gc.common.locale.LocaleResources;
+import com.redhat.thermostat.vm.gc.common.internal.LocaleResources;
 
 import java.io.BufferedReader;
 import java.io.FileReader;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/LocaleResourcesTest.java	Tue May 03 15:49:54 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2016 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.gc.common.internal;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+import com.redhat.thermostat.vm.gc.common.internal.LocaleResources;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
+
--- a/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/locale/LocaleResourcesTest.java	Mon May 02 18:43:01 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2016 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.gc.common.locale;
-
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-
-}
-
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -61,13 +61,13 @@
 import com.redhat.thermostat.client.command.RequestQueue;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
 
 import java.util.Arrays;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindObjectsCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindObjectsCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -51,7 +51,7 @@
 
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindRootCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/FindRootCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,7 +53,7 @@
 
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ListHeapDumpsCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ListHeapDumpsCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -56,12 +56,12 @@
 import com.redhat.thermostat.common.cli.Command;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
 import com.redhat.thermostat.vm.heap.analysis.common.model.HeapInfo;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ObjectInfoCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ObjectInfoCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -55,8 +55,8 @@
 
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/SaveHeapDumpToFileCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/SaveHeapDumpToFileCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -55,8 +55,8 @@
 import com.redhat.thermostat.common.cli.Command;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.command.internal.SaveHeapDumpToFileCommand.FileStreamCreator;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ShowHeapHistogramCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/ShowHeapHistogramCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -47,8 +47,8 @@
 import com.redhat.thermostat.common.cli.Command;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
--- a/vm-profiler/client-cli/src/test/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommandTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/vm-profiler/client-cli/src/test/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommandTest.java	Tue May 03 15:49:54 2016 +0200
@@ -53,6 +53,7 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.internal.test.TestCommandContextFactory;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.AgentId;
 import com.redhat.thermostat.storage.core.VmId;
@@ -60,7 +61,6 @@
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
 import com.redhat.thermostat.storage.model.VmInfo;
-import com.redhat.thermostat.test.TestCommandContextFactory;
 import com.redhat.thermostat.vm.profiler.common.ProfileDAO;
 import com.redhat.thermostat.vm.profiler.common.ProfileStatusChange;
 
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java	Tue May 03 15:49:54 2016 +0200
@@ -91,6 +91,8 @@
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.redhat.thermostat.common.internal.test.FreePortFinder;
+import com.redhat.thermostat.common.internal.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.shared.config.SSLConfiguration;
 import com.redhat.thermostat.storage.core.AuthToken;
 import com.redhat.thermostat.storage.core.BackingStorage;
@@ -114,8 +116,6 @@
 import com.redhat.thermostat.storage.core.StorageException;
 import com.redhat.thermostat.storage.model.AggregateResult;
 import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.test.FreePortFinder;
-import com.redhat.thermostat.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
 import com.redhat.thermostat.web.common.SharedStateId;
 import com.redhat.thermostat.web.common.WebPreparedStatement;
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Mon May 02 18:43:01 2016 +0200
+++ b/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Tue May 03 15:49:54 2016 +0200
@@ -104,6 +104,8 @@
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.reflect.TypeToken;
+import com.redhat.thermostat.common.internal.test.FreePortFinder;
+import com.redhat.thermostat.common.internal.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.storage.core.Add;
 import com.redhat.thermostat.storage.core.AggregateQuery;
 import com.redhat.thermostat.storage.core.AggregateQuery.AggregateFunction;
@@ -130,8 +132,6 @@
 import com.redhat.thermostat.storage.query.BinarySetMembershipExpression;
 import com.redhat.thermostat.storage.query.Expression;
 import com.redhat.thermostat.storage.query.ExpressionFactory;
-import com.redhat.thermostat.test.FreePortFinder;
-import com.redhat.thermostat.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
 import com.redhat.thermostat.web.common.SharedStateId;
 import com.redhat.thermostat.web.common.WebPreparedStatement;