changeset 366:7c12420ae95a

Command channel framework reviewed-by: omajid review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-June/001720.html PR 924
author Jon VanAlten <jon.vanalten@redhat.com>
date Tue, 12 Jun 2012 14:02:16 -0400
parents a3f0ba8b7f92
children 5b8da5a49f21
files agent/command/pom.xml agent/command/src/main/java/com/redhat/thermostat/agent/command/ConfigurationServer.java agent/command/src/main/java/com/redhat/thermostat/agent/command/ConfigurationServerContext.java agent/command/src/main/java/com/redhat/thermostat/agent/command/RequestDecoder.java agent/command/src/main/java/com/redhat/thermostat/agent/command/ResponseEncoder.java agent/command/src/main/java/com/redhat/thermostat/agent/command/ServerHandler.java agent/command/src/main/java/com/redhat/thermostat/agent/command/osgi/Activator.java agent/command/src/test/java/com/redhat/thermostat/agent/command/ConfigurationServerContextTest.java agent/command/src/test/java/com/redhat/thermostat/agent/command/ConfigurationServerTest.java agent/command/src/test/java/com/redhat/thermostat/agent/command/RequestDecoderTest.java agent/command/src/test/java/com/redhat/thermostat/agent/command/ResponseEncoderTest.java agent/core/pom.xml agent/core/src/main/java/com/redhat/thermostat/agent/Activator.java agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java agent/core/src/main/java/com/redhat/thermostat/agent/AgentApplication.java agent/core/src/main/java/com/redhat/thermostat/agent/JvmStatusListener.java agent/core/src/main/java/com/redhat/thermostat/agent/JvmStatusNotifier.java agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java agent/core/src/main/java/com/redhat/thermostat/agent/config/ConfigurationWatcher.java agent/core/src/main/java/com/redhat/thermostat/backend/Backend.java agent/core/src/main/java/com/redhat/thermostat/backend/BackendConfigurationLoader.java agent/core/src/main/java/com/redhat/thermostat/backend/BackendID.java agent/core/src/main/java/com/redhat/thermostat/backend/BackendLoadException.java agent/core/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java agent/core/src/main/java/com/redhat/thermostat/backend/BackendsProperties.java agent/core/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java agent/core/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java agent/core/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java agent/core/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java agent/core/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java agent/core/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcDataSource.java agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java agent/core/src/main/java/com/redhat/thermostat/backend/system/SysConf.java agent/core/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java agent/core/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java agent/core/src/test/java/com/redhat/thermostat/agent/AgentApplicationTest.java agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java agent/core/src/test/java/com/redhat/thermostat/agent/TestUtils.java agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java agent/core/src/test/java/com/redhat/thermostat/backend/BackendConfigurationLoaderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java agent/core/src/test/java/com/redhat/thermostat/backend/sample/SampleBackendTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcDataSourceTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java agent/core/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java agent/pom.xml agent/src/main/java/com/redhat/thermostat/agent/Activator.java agent/src/main/java/com/redhat/thermostat/agent/Agent.java agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java agent/src/main/java/com/redhat/thermostat/agent/JvmStatusListener.java agent/src/main/java/com/redhat/thermostat/agent/JvmStatusNotifier.java agent/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java agent/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java agent/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java agent/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java agent/src/main/java/com/redhat/thermostat/agent/config/ConfigurationWatcher.java agent/src/main/java/com/redhat/thermostat/backend/Backend.java agent/src/main/java/com/redhat/thermostat/backend/BackendConfigurationLoader.java agent/src/main/java/com/redhat/thermostat/backend/BackendID.java agent/src/main/java/com/redhat/thermostat/backend/BackendLoadException.java agent/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java agent/src/main/java/com/redhat/thermostat/backend/BackendsProperties.java agent/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java agent/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java agent/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java agent/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java agent/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java agent/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java agent/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/ProcDataSource.java agent/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/SysConf.java agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java agent/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java agent/src/test/java/com/redhat/thermostat/agent/AgentApplicationTest.java agent/src/test/java/com/redhat/thermostat/agent/AgentTest.java agent/src/test/java/com/redhat/thermostat/agent/TestUtils.java agent/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java agent/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java agent/src/test/java/com/redhat/thermostat/backend/BackendConfigurationLoaderTest.java agent/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java agent/src/test/java/com/redhat/thermostat/backend/sample/SampleBackendTest.java agent/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java agent/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java agent/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java agent/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java agent/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/ProcDataSourceTest.java agent/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java agent/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java agent/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java agent/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java client/command/pom.xml client/command/src/main/java/com/redhat/thermostat/client/command/ConfigurationRequestContext.java client/command/src/main/java/com/redhat/thermostat/client/command/RequestEncoder.java client/command/src/main/java/com/redhat/thermostat/client/command/RequestQueue.java client/command/src/main/java/com/redhat/thermostat/client/command/ResponseDecoder.java client/command/src/main/java/com/redhat/thermostat/client/command/ResponseHandler.java client/core/pom.xml client/killvm/pom.xml client/living-vm-filter/pom.xml client/memory-stats-panel/pom.xml client/pom.xml client/vmclassstat/pom.xml common/command/pom.xml common/command/src/main/java/com/redhat/thermostat/common/command/ConfigurationCommandContext.java common/command/src/main/java/com/redhat/thermostat/common/command/DecodingHelper.java common/command/src/main/java/com/redhat/thermostat/common/command/EncodingHelper.java common/command/src/main/java/com/redhat/thermostat/common/command/Message.java common/command/src/main/java/com/redhat/thermostat/common/command/MessageDecoder.java common/command/src/main/java/com/redhat/thermostat/common/command/MessageEncoder.java common/command/src/main/java/com/redhat/thermostat/common/command/Request.java common/command/src/main/java/com/redhat/thermostat/common/command/RequestResponseListener.java common/command/src/main/java/com/redhat/thermostat/common/command/Response.java common/command/src/test/java/com/redhat/thermostat/common/command/ConfigurationContextTest.java common/command/src/test/java/com/redhat/thermostat/common/command/DecodingHelperTest.java common/command/src/test/java/com/redhat/thermostat/common/command/EncodingHelperTest.java common/command/src/test/java/com/redhat/thermostat/common/command/RequestTest.java common/command/src/test/java/com/redhat/thermostat/common/command/ResponseTest.java common/core/pom.xml common/core/src/main/java/com/redhat/thermostat/common/ActionEvent.java common/core/src/main/java/com/redhat/thermostat/common/ActionListener.java common/core/src/main/java/com/redhat/thermostat/common/ActionNotifier.java common/core/src/main/java/com/redhat/thermostat/common/Activator.java common/core/src/main/java/com/redhat/thermostat/common/Clock.java common/core/src/main/java/com/redhat/thermostat/common/Constants.java common/core/src/main/java/com/redhat/thermostat/common/LaunchException.java common/core/src/main/java/com/redhat/thermostat/common/LogFormatter.java common/core/src/main/java/com/redhat/thermostat/common/NotImplementedException.java common/core/src/main/java/com/redhat/thermostat/common/SystemClock.java common/core/src/main/java/com/redhat/thermostat/common/ThreadPoolTimerFactory.java common/core/src/main/java/com/redhat/thermostat/common/Timer.java common/core/src/main/java/com/redhat/thermostat/common/TimerFactory.java common/core/src/main/java/com/redhat/thermostat/common/View.java common/core/src/main/java/com/redhat/thermostat/common/ViewFactory.java common/core/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java common/core/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContextUtil.java common/core/src/main/java/com/redhat/thermostat/common/cli/AppContextSetup.java common/core/src/main/java/com/redhat/thermostat/common/cli/AppContextSetupImpl.java common/core/src/main/java/com/redhat/thermostat/common/cli/ArgumentSpec.java common/core/src/main/java/com/redhat/thermostat/common/cli/Arguments.java common/core/src/main/java/com/redhat/thermostat/common/cli/BaseCommandRegistry.java common/core/src/main/java/com/redhat/thermostat/common/cli/Command.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContext.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContextFactory.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContextImpl.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandException.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArguments.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParser.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistry.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommonCommandOptions.java common/core/src/main/java/com/redhat/thermostat/common/cli/ConnectionConfiguration.java common/core/src/main/java/com/redhat/thermostat/common/cli/Console.java common/core/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java common/core/src/main/java/com/redhat/thermostat/common/cli/Launcher.java common/core/src/main/java/com/redhat/thermostat/common/cli/LauncherImpl.java common/core/src/main/java/com/redhat/thermostat/common/cli/SimpleArgumentSpec.java common/core/src/main/java/com/redhat/thermostat/common/cli/SimpleArguments.java common/core/src/main/java/com/redhat/thermostat/common/cli/SystemConsole.java common/core/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java common/core/src/main/java/com/redhat/thermostat/common/config/ConfigUtils.java common/core/src/main/java/com/redhat/thermostat/common/config/Defaults.java common/core/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java common/core/src/main/java/com/redhat/thermostat/common/config/StartupConfiguration.java common/core/src/main/java/com/redhat/thermostat/common/config/ThermostatOptionParser.java common/core/src/main/java/com/redhat/thermostat/common/dao/Converter.java common/core/src/main/java/com/redhat/thermostat/common/dao/Countable.java common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/DAOException.java common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostRef.java common/core/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/Ref.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/VmRef.java common/core/src/main/java/com/redhat/thermostat/common/model/CpuStat.java common/core/src/main/java/com/redhat/thermostat/common/model/DiscreteTimeData.java common/core/src/main/java/com/redhat/thermostat/common/model/HostInfo.java common/core/src/main/java/com/redhat/thermostat/common/model/IntervalTimeData.java common/core/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java common/core/src/main/java/com/redhat/thermostat/common/model/MemoryType.java common/core/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java common/core/src/main/java/com/redhat/thermostat/common/model/Pojo.java common/core/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java common/core/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelator.java common/core/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java common/core/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java common/core/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java common/core/src/main/java/com/redhat/thermostat/common/model/VmInfo.java common/core/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java common/core/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java common/core/src/main/java/com/redhat/thermostat/common/storage/BackendInformation.java common/core/src/main/java/com/redhat/thermostat/common/storage/Category.java common/core/src/main/java/com/redhat/thermostat/common/storage/Chunk.java common/core/src/main/java/com/redhat/thermostat/common/storage/ChunkConverter.java common/core/src/main/java/com/redhat/thermostat/common/storage/Connection.java common/core/src/main/java/com/redhat/thermostat/common/storage/ConnectionException.java common/core/src/main/java/com/redhat/thermostat/common/storage/ConnectionKey.java common/core/src/main/java/com/redhat/thermostat/common/storage/Cursor.java common/core/src/main/java/com/redhat/thermostat/common/storage/Key.java common/core/src/main/java/com/redhat/thermostat/common/storage/MongoConnection.java common/core/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorageProvider.java common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java common/core/src/main/java/com/redhat/thermostat/common/storage/StorageConstants.java common/core/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java common/core/src/main/java/com/redhat/thermostat/common/tools/ApplicationException.java common/core/src/main/java/com/redhat/thermostat/common/tools/ApplicationState.java common/core/src/main/java/com/redhat/thermostat/common/tools/BasicCommand.java common/core/src/main/java/com/redhat/thermostat/common/tools/ProcessStartException.java common/core/src/main/java/com/redhat/thermostat/common/utils/DisplayableValues.java common/core/src/main/java/com/redhat/thermostat/common/utils/LoggedExternalProcess.java common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java common/core/src/main/java/com/redhat/thermostat/common/utils/StringUtils.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/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/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command common/core/src/test/java/com/redhat/thermostat/common/ActionEventTest.java common/core/src/test/java/com/redhat/thermostat/common/ActionNotifierTest.java common/core/src/test/java/com/redhat/thermostat/common/ActivatorTest.java common/core/src/test/java/com/redhat/thermostat/common/TestUtils.java common/core/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/appctx/ApplicationContextTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/CommandContextFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/CommandExceptionTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParserTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/CommandRegistryImplTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/CommonCommandOptionsTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/HelpCommandTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/LauncherTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentSpecTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentsTest.java common/core/src/test/java/com/redhat/thermostat/common/cli/TestCommand.java common/core/src/test/java/com/redhat/thermostat/common/config/ClientPreferencesTest.java common/core/src/test/java/com/redhat/thermostat/common/config/ConfigUtilsTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelatorTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/BackendInformationTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/CategoryTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/ChunkConverterTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/ChunkTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/KeyTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java common/core/src/test/java/com/redhat/thermostat/common/storage/StorageTest.java common/core/src/test/java/com/redhat/thermostat/common/tools/BasicCommandTest.java common/core/src/test/java/com/redhat/thermostat/common/utils/DisplayableValuesTest.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 common/pom.xml common/src/main/java/com/redhat/thermostat/common/ActionEvent.java common/src/main/java/com/redhat/thermostat/common/ActionListener.java common/src/main/java/com/redhat/thermostat/common/ActionNotifier.java common/src/main/java/com/redhat/thermostat/common/Activator.java common/src/main/java/com/redhat/thermostat/common/Clock.java common/src/main/java/com/redhat/thermostat/common/Constants.java common/src/main/java/com/redhat/thermostat/common/LaunchException.java common/src/main/java/com/redhat/thermostat/common/LogFormatter.java common/src/main/java/com/redhat/thermostat/common/NotImplementedException.java common/src/main/java/com/redhat/thermostat/common/SystemClock.java common/src/main/java/com/redhat/thermostat/common/ThreadPoolTimerFactory.java common/src/main/java/com/redhat/thermostat/common/Timer.java common/src/main/java/com/redhat/thermostat/common/TimerFactory.java common/src/main/java/com/redhat/thermostat/common/View.java common/src/main/java/com/redhat/thermostat/common/ViewFactory.java common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContextUtil.java common/src/main/java/com/redhat/thermostat/common/cli/AppContextSetup.java common/src/main/java/com/redhat/thermostat/common/cli/AppContextSetupImpl.java common/src/main/java/com/redhat/thermostat/common/cli/ArgumentSpec.java common/src/main/java/com/redhat/thermostat/common/cli/Arguments.java common/src/main/java/com/redhat/thermostat/common/cli/BaseCommandRegistry.java common/src/main/java/com/redhat/thermostat/common/cli/Command.java common/src/main/java/com/redhat/thermostat/common/cli/CommandContext.java common/src/main/java/com/redhat/thermostat/common/cli/CommandContextFactory.java common/src/main/java/com/redhat/thermostat/common/cli/CommandContextImpl.java common/src/main/java/com/redhat/thermostat/common/cli/CommandException.java common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArguments.java common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParser.java common/src/main/java/com/redhat/thermostat/common/cli/CommandRegistry.java common/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java common/src/main/java/com/redhat/thermostat/common/cli/CommonCommandOptions.java common/src/main/java/com/redhat/thermostat/common/cli/ConnectionConfiguration.java common/src/main/java/com/redhat/thermostat/common/cli/Console.java common/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java common/src/main/java/com/redhat/thermostat/common/cli/Launcher.java common/src/main/java/com/redhat/thermostat/common/cli/LauncherImpl.java common/src/main/java/com/redhat/thermostat/common/cli/SimpleArgumentSpec.java common/src/main/java/com/redhat/thermostat/common/cli/SimpleArguments.java common/src/main/java/com/redhat/thermostat/common/cli/SystemConsole.java common/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java common/src/main/java/com/redhat/thermostat/common/config/ConfigUtils.java common/src/main/java/com/redhat/thermostat/common/config/Defaults.java common/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java common/src/main/java/com/redhat/thermostat/common/config/StartupConfiguration.java common/src/main/java/com/redhat/thermostat/common/config/ThermostatOptionParser.java common/src/main/java/com/redhat/thermostat/common/dao/Converter.java common/src/main/java/com/redhat/thermostat/common/dao/Countable.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/DAOException.java common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/HostRef.java common/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/Ref.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmRef.java common/src/main/java/com/redhat/thermostat/common/model/CpuStat.java common/src/main/java/com/redhat/thermostat/common/model/DiscreteTimeData.java common/src/main/java/com/redhat/thermostat/common/model/HostInfo.java common/src/main/java/com/redhat/thermostat/common/model/IntervalTimeData.java common/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java common/src/main/java/com/redhat/thermostat/common/model/MemoryType.java common/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java common/src/main/java/com/redhat/thermostat/common/model/Pojo.java common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelator.java common/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java common/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java common/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java common/src/main/java/com/redhat/thermostat/common/model/VmInfo.java common/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java common/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java common/src/main/java/com/redhat/thermostat/common/storage/BackendInformation.java common/src/main/java/com/redhat/thermostat/common/storage/Category.java common/src/main/java/com/redhat/thermostat/common/storage/Chunk.java common/src/main/java/com/redhat/thermostat/common/storage/ChunkConverter.java common/src/main/java/com/redhat/thermostat/common/storage/Connection.java common/src/main/java/com/redhat/thermostat/common/storage/ConnectionException.java common/src/main/java/com/redhat/thermostat/common/storage/ConnectionKey.java common/src/main/java/com/redhat/thermostat/common/storage/Cursor.java common/src/main/java/com/redhat/thermostat/common/storage/Key.java common/src/main/java/com/redhat/thermostat/common/storage/MongoConnection.java common/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java common/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java common/src/main/java/com/redhat/thermostat/common/storage/MongoStorageProvider.java common/src/main/java/com/redhat/thermostat/common/storage/Storage.java common/src/main/java/com/redhat/thermostat/common/storage/StorageConstants.java common/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java common/src/main/java/com/redhat/thermostat/common/tools/ApplicationException.java common/src/main/java/com/redhat/thermostat/common/tools/ApplicationState.java common/src/main/java/com/redhat/thermostat/common/tools/BasicCommand.java common/src/main/java/com/redhat/thermostat/common/tools/ProcessStartException.java common/src/main/java/com/redhat/thermostat/common/utils/DisplayableValues.java common/src/main/java/com/redhat/thermostat/common/utils/LoggedExternalProcess.java common/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java common/src/main/java/com/redhat/thermostat/common/utils/StringUtils.java common/src/main/java/com/redhat/thermostat/test/Bug.java common/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java common/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java common/src/main/java/com/redhat/thermostat/test/TestCommandRegistry.java common/src/main/java/com/redhat/thermostat/test/TestTimerFactory.java common/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command common/src/test/java/com/redhat/thermostat/common/ActionEventTest.java common/src/test/java/com/redhat/thermostat/common/ActionNotifierTest.java common/src/test/java/com/redhat/thermostat/common/ActivatorTest.java common/src/test/java/com/redhat/thermostat/common/TestUtils.java common/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java common/src/test/java/com/redhat/thermostat/common/appctx/ApplicationContextTest.java common/src/test/java/com/redhat/thermostat/common/cli/CommandContextFactoryTest.java common/src/test/java/com/redhat/thermostat/common/cli/CommandExceptionTest.java common/src/test/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParserTest.java common/src/test/java/com/redhat/thermostat/common/cli/CommandRegistryImplTest.java common/src/test/java/com/redhat/thermostat/common/cli/CommonCommandOptionsTest.java common/src/test/java/com/redhat/thermostat/common/cli/HelpCommandTest.java common/src/test/java/com/redhat/thermostat/common/cli/LauncherTest.java common/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentSpecTest.java common/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentsTest.java common/src/test/java/com/redhat/thermostat/common/cli/TestCommand.java common/src/test/java/com/redhat/thermostat/common/config/ClientPreferencesTest.java common/src/test/java/com/redhat/thermostat/common/config/ConfigUtilsTest.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelatorTest.java common/src/test/java/com/redhat/thermostat/common/storage/BackendInformationTest.java common/src/test/java/com/redhat/thermostat/common/storage/CategoryTest.java common/src/test/java/com/redhat/thermostat/common/storage/ChunkConverterTest.java common/src/test/java/com/redhat/thermostat/common/storage/ChunkTest.java common/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java common/src/test/java/com/redhat/thermostat/common/storage/KeyTest.java common/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java common/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java common/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java common/src/test/java/com/redhat/thermostat/common/storage/StorageTest.java common/src/test/java/com/redhat/thermostat/common/tools/BasicCommandTest.java common/src/test/java/com/redhat/thermostat/common/utils/DisplayableValuesTest.java common/src/test/java/com/redhat/thermostat/test/ExceptionThrowingInputStreamTest.java common/src/test/java/com/redhat/thermostat/test/TestCommandContextFactoryTest.java common/src/test/java/com/redhat/thermostat/test/TestTimerFactoryTest.java distribution/config/osgi-export.properties distribution/pom.xml distribution/scripts/thermostat pom.xml tools/pom.xml unix-process-handler/pom.xml
diffstat 540 files changed, 28084 insertions(+), 25544 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-agent</artifactId>
+    <version>0.3-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-agent-command</artifactId>
+  <packaging>jar</packaging>
+
+  <name>Thermostat Command Channel Server</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>${powermock.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${powermock.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-command</artifactId>
+      <version>${project.version}</version>
+      <type>jar</type>
+    </dependency>
+    
+  </dependencies>
+
+  <!-- build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.agent.config.command.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.agent.command
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.agent.command.osgi
+            </Private-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build -->
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/ConfigurationServer.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+
+public class ConfigurationServer {
+
+    private final ConfigurationServerContext ctx;
+
+    public ConfigurationServer(ConfigurationServerContext ctx) {
+        this.ctx = ctx;
+    }
+
+    public void startup() {
+
+        ServerBootstrap bootstrap = (ServerBootstrap) ctx.getBootstrap();
+
+        // Bind and start to accept incoming connections.
+        bootstrap.bind(ctx.getAddress());
+    }
+
+    public void shutdown() {
+        ctx.getChannelGroup().close().awaitUninterruptibly();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/ConfigurationServerContext.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.Bootstrap;
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+
+import com.redhat.thermostat.common.command.ConfigurationCommandContext;
+
+public class ConfigurationServerContext extends ConfigurationCommandContext {
+
+    final ServerBootstrap bootstrap;
+    final ChannelGroup channels;
+
+    public ConfigurationServerContext() {
+        bootstrap = createBootstrap();
+        channels = createChannelGroup();
+    }
+
+    @Override
+    public Bootstrap getBootstrap() {
+        return bootstrap;
+    }
+
+    private ChannelGroup createChannelGroup() {
+        return new DefaultChannelGroup(ConfigurationServer.class.getName());
+    }
+
+    private ServerBootstrap createBootstrap() {
+        ServerBootstrap bootstrap = new ServerBootstrap(
+                new NioServerSocketChannelFactory(
+                        Executors.newCachedThreadPool(),
+                        Executors.newCachedThreadPool()));
+
+        // Set up the pipeline factory.
+        bootstrap.setPipelineFactory(new ServerPipelineFactory());
+
+        bootstrap.setOption("child.tcpNoDelay", true);
+        bootstrap.setOption("child.keepAlive", true);
+        bootstrap.setOption("child.reuseAddress", true);
+        bootstrap.setOption("child.connectTimeoutMillis", 100);
+        bootstrap.setOption("child.readWriteFair", true);
+        
+        return bootstrap;
+    }
+
+    private class ServerPipelineFactory implements ChannelPipelineFactory {
+
+        @Override
+        public ChannelPipeline getPipeline() throws Exception {
+            ChannelPipeline pipeline = Channels.pipeline();
+            pipeline.addLast("decoder", new RequestDecoder());
+            pipeline.addLast("encoder", new ResponseEncoder());
+            pipeline.addLast("handler", new ServerHandler());
+            return pipeline;
+        }
+        
+    }
+
+    public ChannelGroup getChannelGroup() {
+        return channels;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/RequestDecoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+
+import com.redhat.thermostat.common.command.DecodingHelper;
+import com.redhat.thermostat.common.command.MessageDecoder;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Request.RequestType;
+
+class RequestDecoder extends MessageDecoder {
+
+    @Override
+    protected Object decode(ChannelHandlerContext ctx, Channel channel,
+            ChannelBuffer buffer) {
+        String typeAsString = DecodingHelper.decodeString(buffer);
+        if (typeAsString == null) {
+            return null;
+        }
+        return new Request(RequestType.valueOf(typeAsString), channel.getRemoteAddress());
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/ResponseEncoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import static org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+
+import com.redhat.thermostat.common.command.EncodingHelper;
+import com.redhat.thermostat.common.command.MessageEncoder;
+import com.redhat.thermostat.common.command.Response;
+
+
+class ResponseEncoder extends MessageEncoder {
+
+    @Override
+    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
+
+        Response response = (Response) e.getMessage();
+
+        // Response Type
+        String responseType = EncodingHelper.trimType(response.getType().toString());
+        byte[] message = responseType.getBytes();
+        ChannelBuffer typeBuffer = EncodingHelper.encode(message);
+
+        // Compose the full message.
+        ChannelBuffer buf = wrappedBuffer(typeBuffer);
+        Channels.write(ctx, e.getFuture(), buf);
+        
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/ServerHandler.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelFutureListener;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelHandler;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Request.RequestType;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+
+public class ServerHandler extends SimpleChannelHandler {
+
+    private static final Logger logger = Logger.getLogger(ServerHandler.class.getName());
+
+    @Override
+    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
+        Request request = (Request) e.getMessage();
+        logger.info("Request received: " + request.getType().toString());
+        Response response = doRequest(request);
+        Channel channel = ctx.getChannel();
+        if (channel.isConnected()) {
+            logger.info("Sending response: " + response.getType().toString());
+            ChannelFuture f = channel.write(response);
+
+            f.addListener(ChannelFutureListener.CLOSE);
+        } else {
+            logger.warning("Channel not connected.");
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
+        logger.log(Level.WARNING, "Unexpected exception from downstream.", e.getCause());
+        e.getChannel().close();
+    }
+
+    private Response doRequest(Request request) {
+        Response response = new Response(ResponseType.ERROR);
+        switch ((RequestType) request.getType()) {
+        case PING:
+            response = new Response(ResponseType.PONG);
+            break;
+        default:
+        }
+        return response;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/osgi/Activator.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command.osgi;
+
+import java.util.Hashtable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.agent.command.ConfigurationServer;
+import com.redhat.thermostat.agent.command.ConfigurationServerContext;
+
+public class Activator implements BundleActivator {
+
+    private static final Logger logger = Logger.getLogger(Activator.class.getSimpleName());
+    private static final String SERVICE_NAME = "com.redhat.thermostat.agent.config.netty.ConfigurationServer";
+
+    private ConfigurationServer confServer;
+
+    public Activator() {
+        confServer = new ConfigurationServer(new ConfigurationServerContext());
+    }
+
+    @Override
+    public void start(BundleContext context) throws Exception {    
+        logger.log(Level.INFO, "activating thermostat-agent-confserver");
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put(SERVICE_NAME, SERVICE_NAME);
+        context.registerService(ConfigurationServer.class.getName(), confServer, props);
+        confServer.startup();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        confServer.shutdown();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/ConfigurationServerContextTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.jboss.netty.bootstrap.Bootstrap;
+import org.jboss.netty.channel.ChannelHandler;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.command.ConfigurationServer;
+import com.redhat.thermostat.agent.command.ConfigurationServerContext;
+import com.redhat.thermostat.agent.command.RequestDecoder;
+import com.redhat.thermostat.agent.command.ResponseEncoder;
+import com.redhat.thermostat.agent.command.ServerHandler;
+
+public class ConfigurationServerContextTest {
+
+    ConfigurationServerContext ctx;
+
+    @Before
+    public void setUp() {
+        ctx = new ConfigurationServerContext();
+    }
+
+    @Test
+    public void testBootstrap() {
+        Bootstrap bootstrap = ctx.getBootstrap();
+        assertNotNull(bootstrap);
+
+        assertTrue((Boolean) bootstrap.getOption("child.tcpNoDelay"));
+        assertTrue((Boolean) bootstrap.getOption("child.keepAlive"));
+        assertTrue((Boolean) bootstrap.getOption("child.reuseAddress"));
+        assertEquals(100, bootstrap.getOption("child.connectTimeoutMillis"));
+        assertTrue((Boolean) bootstrap.getOption("child.readWriteFair"));
+
+        ChannelPipelineFactory pf = bootstrap.getPipelineFactory();
+        assertNotNull(pf);
+
+        ChannelPipeline p = null;
+        try {
+            p = pf.getPipeline();
+        } catch (Exception e) {
+            // Do nothing
+        }
+        assertNotNull(p);
+
+        ChannelHandler encoder = p.get("encoder");
+        assertNotNull(encoder);
+        assertTrue(encoder instanceof ResponseEncoder);
+
+        ChannelHandler decoder = p.get("decoder");
+        assertNotNull(decoder);
+        assertTrue(decoder instanceof RequestDecoder);
+
+        ChannelHandler handler = p.get("handler");
+        assertNotNull(handler);
+        assertTrue(handler instanceof ServerHandler);
+    }
+
+    @Test
+    public void testChannelGroup() {
+        ChannelGroup cg = ctx.getChannelGroup();
+        assertNotNull(cg);
+        assertEquals(ConfigurationServer.class.getName(), cg.getName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/ConfigurationServerTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import java.net.InetSocketAddress;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.ChannelGroupFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.command.ConfigurationServer;
+import com.redhat.thermostat.agent.command.ConfigurationServerContext;
+
+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 ConfigurationServerTest {
+
+    private ConfigurationServerContext ctx;
+    ChannelGroup cg;
+    ServerBootstrap bootstrap;
+    InetSocketAddress addr;
+
+    @Before
+    public void setUp() {
+        cg = mock(ChannelGroup.class);
+        ChannelGroupFuture future = mock(ChannelGroupFuture.class);
+        when(cg.close()).thenReturn(future);
+        bootstrap = mock(ServerBootstrap.class);
+        addr = new InetSocketAddress(123);
+        ctx = mock(ConfigurationServerContext.class);
+        when(ctx.getBootstrap()).thenReturn(bootstrap);
+        when(ctx.getChannelGroup()).thenReturn(cg);
+        when(ctx.getAddress()).thenReturn(addr);
+    }
+
+    @Test
+    public void testStartup() {
+        ConfigurationServer server = new ConfigurationServer(ctx);
+        server.startup();
+
+
+        ArgumentCaptor<InetSocketAddress> argument = ArgumentCaptor.forClass(InetSocketAddress.class);
+        verify(bootstrap).bind(argument.capture());
+        assertEquals(addr, argument.getValue());
+    }
+
+    @Test
+    public void testShutdown() {
+        ConfigurationServer server = new ConfigurationServer(ctx);
+        server.shutdown();
+
+        verify(cg).close();
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/RequestDecoderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.command.RequestDecoder;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Request.RequestType;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class RequestDecoderTest {
+    private static final byte[] PING = "PING".getBytes();
+
+    private ChannelBuffer buffer;
+    private Channel channel;
+
+    @Before
+    public void setUp() {
+        channel = mock(Channel.class);
+        
+        buffer = ChannelBuffers.dynamicBuffer();
+        buffer.writeInt(PING.length);
+        buffer.writeBytes(PING);
+    }
+
+    @Test
+    public void testDecode() {
+        RequestDecoder decoder = new RequestDecoder();
+        Request request = (Request) decoder.decode(null, channel, buffer);
+
+        assertTrue(RequestType.PING == (RequestType) request.getType());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/ResponseEncoderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import java.nio.ByteBuffer;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.redhat.thermostat.agent.command.ResponseEncoder;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Channels.class)
+public class ResponseEncoderTest {
+
+    private MessageEvent e;
+
+    @Before
+    public void setUp() {
+        Response r = new Response(ResponseType.PONG);
+        e = mock(MessageEvent.class);
+        when(e.getMessage()).thenReturn(r);
+        when(e.getFuture()).thenReturn(null);
+        
+    }
+
+    @Test
+    public void testWriteRequested() {
+        PowerMockito.mockStatic(Channels.class);
+        ArgumentCaptor<Object> argument = ArgumentCaptor.forClass(Object.class);
+
+        ResponseEncoder encoder = new ResponseEncoder();
+        ChannelHandlerContext ctx = mock(ChannelHandlerContext.class);
+        encoder.writeRequested(ctx, e);
+        
+        PowerMockito.verifyStatic();
+        Channels.write(any(ChannelHandlerContext.class), any(ChannelFuture.class), argument.capture());
+
+        ChannelBuffer buf = (ChannelBuffer) argument.getValue();
+        int messageLength = buf.readInt();
+        assertEquals(4, messageLength);
+        ByteBuffer bbuf = ByteBuffer.allocate(buf.readableBytes());
+        buf.readBytes(bbuf);
+        String message = new String(bbuf.array());
+        assertEquals("PONG", message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-agent</artifactId>
+    <version>0.3-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-agent-core</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat Agent Core</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.sun</groupId>
+      <artifactId>tools</artifactId>
+      <scope>system</scope>
+      <systemPath>${java.home}/../lib/tools.jar</systemPath>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.agent.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.agent,
+              com.redhat.thermostat.backend,
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat,
+              com.redhat.thermostat.agent.config,
+              com.redhat.thermostat.backend.sample,
+              com.redhat.thermostat.backend.system,
+            </Private-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/Activator.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import java.util.Arrays;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.CommandRegistryImpl;
+
+public class Activator implements BundleActivator {
+
+    private CommandRegistry reg;
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        reg = new CommandRegistryImpl(context);
+        reg.registerCommands(Arrays.asList(new AgentApplication()));
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        reg.unregisterCommands();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/Agent.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.agent.config.ConfigurationWatcher;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.LaunchException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.AgentInformation;
+import com.redhat.thermostat.common.storage.BackendInformation;
+import com.redhat.thermostat.common.storage.Storage;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * Represents the Agent running on a host.
+ */
+public class Agent {
+
+    private static final Logger logger = LoggingUtils.getLogger(Agent.class);
+
+    private final UUID id;
+    private final BackendRegistry backendRegistry;
+    private final AgentStartupConfiguration config;
+
+    private AgentInformation agentInfo;
+    
+    private Storage storage;
+    private Thread configWatcherThread = null;
+
+    public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, DAOFactory daos) {
+        this(backendRegistry, UUID.randomUUID(), config, daos);
+    }
+
+    public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, DAOFactory daos) {
+        this.id = agentId;
+        this.backendRegistry = registry;
+        this.config = config;
+        this.storage = daos.getStorage();
+        this.storage.setAgentId(agentId);
+    }
+
+    private void startBackends() throws LaunchException {
+        for (Backend be : backendRegistry.getAll()) {
+            logger.fine("Attempting to start backend: " + be.getName());
+            if (!be.activate()) {
+                logger.warning("Issue while starting backend: " + be.getName());
+                // When encountering issues during startup, we should not attempt to continue activating.
+                stopBackends();
+                throw new LaunchException("Could not activate backend: " + be.getName());
+            }
+        }
+    }
+
+    private void stopBackends() {
+        for (Backend be : backendRegistry.getAll()) {
+            logger.fine("Attempting to stop backend: " +be.getName());
+            if (!be.deactivate()) {
+                // When encountering issues during shutdown, we should attempt to shut down remaining backends.
+                logger.warning("Issue while deactivating backend: " + be.getName());
+            }
+        }
+    }
+
+    public synchronized void start() throws LaunchException {
+        if (configWatcherThread == null) {
+            startBackends();
+            agentInfo = createAgentInformation();
+            storage.addAgentInformation(agentInfo);
+            configWatcherThread = new Thread(new ConfigurationWatcher(storage, backendRegistry), "Configuration Watcher");
+            configWatcherThread.start();
+        } else {
+            logger.warning("Attempt to start agent when already started.");
+        }
+    }
+
+    private AgentInformation createAgentInformation() {
+        AgentInformation agentInfo = new AgentInformation();
+        agentInfo.setStartTime(config.getStartTime());
+        for (Backend backend : backendRegistry.getAll()) {
+            BackendInformation backendInfo = new BackendInformation();
+            backendInfo.setName(backend.getName());
+            backendInfo.setDescription(backend.getDescription());
+            backendInfo.setObserveNewJvm(backend.getObserveNewJvm());
+            agentInfo.addBackend(backendInfo);
+        }
+        agentInfo.setAlive(true);
+        return agentInfo;
+    }
+
+    public synchronized void stop() {
+        if (configWatcherThread != null) {
+            configWatcherThread.interrupt(); // This thread checks for its own interrupted state and ends if interrupted.
+            while (configWatcherThread.isAlive()) {
+                try {
+                    configWatcherThread.join();
+                } catch (InterruptedException e) {
+                    logger.fine("Interrupted while waiting for ConfigurationWatcher to die.");
+                }
+            }
+            configWatcherThread = null;
+
+            stopBackends();
+            if (config.purge()) {
+                System.out.println("purging database");
+                logger.info("purging database");
+                storage.removeAgentInformation();
+                storage.purge();
+            } else {
+                agentInfo.setStopTime(System.currentTimeMillis());
+                agentInfo.setAlive(false);
+                storage.updateAgentInformation(agentInfo);
+            }
+            
+        } else {
+            logger.warning("Attempt to stop agent which is not active");
+        }
+    }
+
+    public UUID getId() {
+        return id;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/AgentApplication.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.config.AgentConfigsUtils;
+import com.redhat.thermostat.agent.config.AgentOptionParser;
+import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.backend.BackendLoadException;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.Constants;
+import com.redhat.thermostat.common.LaunchException;
+import com.redhat.thermostat.common.ThreadPoolTimerFactory;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.cli.ArgumentSpec;
+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.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.MongoDAOFactory;
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+import com.redhat.thermostat.common.storage.MongoStorageProvider;
+import com.redhat.thermostat.common.storage.StorageProvider;
+import com.redhat.thermostat.common.tools.BasicCommand;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
+
+@SuppressWarnings("restriction")
+public final class AgentApplication extends BasicCommand {
+
+    private static final String NAME = "agent";
+
+    // TODO: Use LocaleResources for i18n-ized strings.
+    private static final String DESCRIPTION = "starts and stops the thermostat agent";
+
+    private static final String USAGE = DESCRIPTION;
+
+    private AgentStartupConfiguration configuration;
+    private AgentOptionParser parser;
+    
+    private void parseArguments(Arguments args) throws InvalidConfigurationException {
+        configuration = AgentConfigsUtils.createAgentConfigs();
+        parser = new AgentOptionParser(configuration, args);
+        parser.parse();
+    }
+
+    @Override
+    public AgentStartupConfiguration getConfiguration() {
+        return configuration;
+    }
+    
+    private void runAgent(CommandContext ctx) {
+        long startTime = System.currentTimeMillis();
+        configuration.setStartTime(startTime);
+        
+        if (configuration.isDebugConsole()) {
+            LoggingUtils.useDevelConsole();
+        }
+        final Logger logger = LoggingUtils.getLogger(AgentApplication.class);
+
+        StorageProvider connProv = new MongoStorageProvider(configuration);
+        DAOFactory daoFactory = new MongoDAOFactory(connProv);
+        ApplicationContext.getInstance().setDAOFactory(daoFactory);
+        TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
+        ApplicationContext.getInstance().setTimerFactory(timerFactory);
+
+        Connection connection = daoFactory.getConnection();
+        ConnectionListener connectionListener = new ConnectionListener() {
+            @Override
+            public void changed(ConnectionStatus newStatus) {
+                switch (newStatus) {
+                case DISCONNECTED:
+                    logger.warning("Unexpected disconnect event.");
+                    break;
+                case CONNECTING:
+                    logger.fine("Connecting to storage.");
+                    break;
+                case CONNECTED:
+                    logger.fine("Connected to storage.");
+                    break;
+                case FAILED_TO_CONNECT:
+                    logger.warning("Could not connect to storage.");
+                    System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
+                default:
+                    logger.warning("Unfamiliar ConnectionStatus value");
+                }
+            }
+        };
+
+        connection.addListener(connectionListener);
+        connection.connect();
+        logger.fine("Connecting to storage...");
+
+        BackendRegistry backendRegistry = null;
+        try {
+            backendRegistry = new BackendRegistry(configuration);
+        } catch (BackendLoadException ble) {
+            logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble);
+            System.exit(Constants.EXIT_BACKEND_LOAD_ERROR);
+        }
+
+        final Agent agent = new Agent(backendRegistry, configuration, daoFactory);
+        try {
+            logger.fine("Starting agent.");
+            agent.start();
+        } catch (LaunchException le) {
+            logger.log(Level.SEVERE,
+                    "Agent could not start, probably because a configured backend could not be activated.",
+                    le);
+            System.exit(Constants.EXIT_BACKEND_START_ERROR);
+        }
+        logger.fine("Agent started.");
+
+        ctx.getConsole().getOutput().println("Agent id: " + agent.getId());
+        ctx.getConsole().getOutput().println("agent started.");
+        logger.fine("Agent id: " + agent.getId());
+
+        final CountDownLatch shutdownLatch = new CountDownLatch(1);
+        Signal.handle(new Signal("INT"), new SignalHandler() {
+            public void handle(sun.misc.Signal sig) {
+                agent.stop();
+                logger.fine("Agent stopped.");       
+                shutdownLatch.countDown();
+            }
+        });
+        try {
+            shutdownLatch.await();
+            logger.fine("terimating agent cmd");
+        } catch (InterruptedException e) {
+            return;
+        }
+    }
+    
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        try {
+            parseArguments(ctx.getArguments());
+            if (!parser.isHelp()) {
+                runAgent(ctx);
+            }
+        } catch (InvalidConfigurationException ex) {
+            throw new CommandException(ex);
+        }
+    }
+
+    @Override
+    public void disable() {
+        /* NO-OP */
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return DESCRIPTION;
+    }
+
+    @Override
+    public String getUsage() {
+        return USAGE;
+    }
+
+    @Override
+    public Collection<ArgumentSpec> getAcceptedArguments() {
+        return AgentOptionParser.getAcceptedArguments();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/JvmStatusListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+public interface JvmStatusListener {
+
+    public void jvmStarted(int pid);
+
+    public void jvmStopped(int pid);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/JvmStatusNotifier.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+public interface JvmStatusNotifier {
+
+    /**
+     * Request to be informed when JVM processes are started or stopped.
+     * 
+     * @param listener the receiver of future {@link JvmStatusListener.jvmStarted()}
+     * and {@link JvmStatusListener.jvmStopped()} calls
+     */
+    public void addJvmStatusListener(JvmStatusListener listener);
+
+    /**
+     * Request to no longer be informed when JVM processes are started or stopped.
+     * @param listener the {@link JvmStatusListener} to be unregistered.
+     */
+    public void removeJvmStatusListener(JvmStatusListener listener);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import com.redhat.thermostat.common.config.ConfigUtils;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+public class AgentConfigsUtils {
+
+    public static AgentStartupConfiguration createAgentConfigs() throws InvalidConfigurationException {
+        
+        AgentStartupConfiguration config = new AgentStartupConfiguration();
+        
+        File propertyFile = ConfigUtils.getAgentConfigurationFile();
+        readAndSetProperties(propertyFile, config);
+        
+        return config;
+    }
+    
+    private static void readAndSetProperties(File propertyFile, AgentStartupConfiguration configuration)
+            throws InvalidConfigurationException
+    {
+        Properties properties = new Properties();
+        try {
+            properties.load(new FileInputStream(propertyFile));
+            
+        } catch (IOException e) {
+            throw new InvalidConfigurationException(e);
+        }
+        
+        if (properties.containsKey(AgentProperties.BACKENDS.name())) {
+            // this is a command separated list of backends
+            String backends = properties.getProperty(AgentProperties.BACKENDS.name());
+            configuration.parseBackends(backends.split(","));
+            
+        } else {
+            throw new InvalidConfigurationException(AgentProperties.BACKENDS + " property missing");
+        }
+        
+        if (properties.containsKey(AgentProperties.DB_URL.name())) {
+            String db = properties.getProperty(AgentProperties.DB_URL.name());
+            configuration.setDatabaseURL(db);
+        }
+        
+        configuration.setPurge(true);
+        if (properties.containsKey(AgentProperties.SAVE_ON_EXIT.name())) {
+            String purge = (String) properties.get(AgentProperties.SAVE_ON_EXIT.name());
+            configuration.setPurge(!Boolean.parseBoolean(purge));
+        }
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import com.redhat.thermostat.common.cli.ArgumentSpec;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.SimpleArgumentSpec;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.config.ThermostatOptionParser;
+
+public class AgentOptionParser implements ThermostatOptionParser {
+
+    private AgentStartupConfiguration configuration;
+    private Arguments args;
+    
+    private boolean isHelp;
+    
+    public AgentOptionParser(AgentStartupConfiguration configuration, Arguments args) {
+        this.configuration = configuration;
+        this.args = args;
+        isHelp = false;
+    }
+    
+    @Override
+    public void parse() throws InvalidConfigurationException {
+
+        if (args.hasArgument(Args.SAVE_ON_EXIT.option)) {
+            configuration.setPurge(false);
+        }
+
+        configuration.setDebugConsole(args.hasArgument(Args.DEBUG.option));
+        
+        if (args.hasArgument(Args.DB.option)) {
+            String url = args.getArgument(Args.DB.option);
+            configuration.setDatabaseURL(url);
+        } else {
+            if (configuration.getDBConnectionString() == null) {
+                System.err.println("database url not specified... must be " +
+                                   "either set in config or passed on " +
+                                   "the command line");
+                isHelp = true;
+            }
+        }
+    }
+    
+    public boolean isHelp() {
+        return isHelp;
+    }
+    
+    private static enum Args {
+        
+        // TODO: localize
+        SAVE_ON_EXIT("saveOnExit", "save the data on exit"),
+        DB("dbUrl", "connect to the given url"),
+        DEBUG("debug", "launch with debug console enabled"),
+        HELP("help", "print this help and exit");
+        
+        private String option;
+        private String description;
+        
+        Args(String option, String description) {
+            this.option = option;
+            this.description = description;
+        }
+    }
+
+    public static Collection<ArgumentSpec> getAcceptedArguments() {
+        ArgumentSpec saveOnExit = new SimpleArgumentSpec(Args.SAVE_ON_EXIT.option, "s", Args.SAVE_ON_EXIT.description, false, false);
+        ArgumentSpec db = new SimpleArgumentSpec(Args.DB.option, "d",  Args.DB.description, true, true);
+        ArgumentSpec debug = new SimpleArgumentSpec(Args.DEBUG.option, Args.DEBUG.description);
+        return Arrays.asList(saveOnExit, db, debug);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+public enum AgentProperties {
+
+    // backend list, comma separated
+    BACKENDS,
+    DEBUG_CONSOLE,
+    DB_URL,
+    SAVE_ON_EXIT
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import com.redhat.thermostat.backend.BackendID;
+import com.redhat.thermostat.backend.BackendsProperties;
+import com.redhat.thermostat.common.config.ConfigUtils;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+public class AgentStartupConfiguration implements StartupConfiguration {
+
+    private List<BackendID> backends;
+    
+    private boolean debugConsole;
+    private boolean purge;
+    
+    private String url;
+    
+    private long startTime;
+    
+    AgentStartupConfiguration() {
+        this.backends = new ArrayList<>();
+    }
+    
+    @Override
+    public String getDBConnectionString() {
+        return url;
+    }
+
+    void parseBackends(String[] backendsList) throws InvalidConfigurationException {
+        backends.clear();
+        
+        for (String simpleName : backendsList) {
+            String backendName = simpleName.trim();
+            
+            // a file must exist, at least with the class name
+            File backendSettings = ConfigUtils.getBackendPropertyFile(backendName);
+            if (!backendSettings.exists())
+                throw new InvalidConfigurationException("backends configuration " +
+                                                        "directory doesn't exist: " +
+                                                        backendSettings);
+            Properties backendProps = new Properties();
+            try {
+                backendProps.load(new FileInputStream(backendSettings));
+                
+            } catch (IOException e) {
+                throw new InvalidConfigurationException(e);
+            }
+            
+            String backendClass = backendProps.getProperty(BackendsProperties.BACKEND_CLASS.name());
+            if (backendClass == null) {
+                throw new InvalidConfigurationException("Class name not found for backend: " +
+                                                        backendName);
+            }
+            
+            BackendID backend = new BackendID(backendName, backendClass);
+            backends.add(backend);
+        }
+    }
+    
+    public List<BackendID> getBackends() {
+        return backends;
+    }
+
+    void setDebugConsole(boolean debugConsole) {
+        this.debugConsole = debugConsole;
+    }
+    
+    public boolean isDebugConsole() {
+        return debugConsole;
+    }
+
+    public void setDatabaseURL(String url) {
+        this.url = url;
+    }
+    
+    // TODO: that should be a friend, we only want the Service to set this value
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+    
+    public long getStartTime() {
+        return startTime;
+    }
+
+    void setPurge(boolean purge) {
+        this.purge = purge;
+    }
+    
+    public boolean purge() {
+        return purge;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/config/ConfigurationWatcher.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.storage.Storage;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class ConfigurationWatcher implements Runnable {
+
+    private static final Logger logger = LoggingUtils.getLogger(ConfigurationWatcher.class);
+
+    private Storage storage;
+    private BackendRegistry backends;
+
+    public ConfigurationWatcher(Storage storage, BackendRegistry backends) {
+        this.storage = storage;
+        this.backends = backends;
+    }
+
+    @Override
+    public void run() {
+        logger.fine("Watching for configuration changes.");
+        while (!Thread.interrupted()) {
+            checkConfigUpdates();
+        }
+        logger.fine("No longer watching for configuration changes.");
+    }
+
+    // TODO It would be best to develop this algorithm when we have a client that can initiate changes, so that it can be tested.
+    private void checkConfigUpdates() {
+        try { // THIS IS ONLY TEMPORARY.  Until we do implement this algorithm, we don't want this thread busy hogging CPU.
+            Thread.sleep(2000);
+        } catch (InterruptedException ignore) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/Backend.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.redhat.thermostat.common.LaunchException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Storage;
+
+/**
+ * Represents a monitoring back-end. All the {@link Backend}s should be
+ * registered with the {@link BackendRegistry}.
+ */
+public abstract class Backend {
+
+    private boolean initialConfigurationComplete = false;
+    protected DAOFactory df = null;
+    private Storage storage = null;
+    private boolean observeNewJvm = attachToNewProcessByDefault();
+
+    private String version;
+    private String vendor;
+    private String description;
+    
+    private BackendID id;
+
+    /**
+     * 
+     * @param configMap a map containing the settings that this backend has been configured with.
+     * @throws LaunchException if map contains values that this backend does not accept.
+     */
+    protected final void setInitialConfiguration(Map<String, String> configMap) throws BackendLoadException {
+        if (initialConfigurationComplete) {
+            throw new BackendLoadException("A backend may only receive initial configuration once.");
+        }
+        for (Entry<String, String> e : configMap.entrySet()) {
+            String key = e.getKey();
+            String value = e.getValue();
+            try {
+                setConfigurationValue(key, value);
+            } catch (IllegalArgumentException iae) {
+                throw new BackendLoadException("Attempt to set invalid backend configuration for " + getName()
+                        + " backend.  Key: " + key + "   Value: " + value, iae);
+            }
+        }
+        initialConfigurationComplete = true;
+    }
+
+    public final void setDAOFactory(DAOFactory df) {
+        this.df = df;
+        this.storage = df.getStorage();
+        for (Category cat : getCategories()) {
+            storage.registerCategory(cat);
+        }
+        setDAOFactoryAction();
+    }
+
+    protected abstract void setDAOFactoryAction();
+
+    protected abstract Collection<Category> getCategories();
+
+    /**
+     * Set the named configuration to the given value.
+     * The basic special properties {@code name}, {@code version} and
+     * {@code description} are parsed here.
+     * 
+     * <br /><br />
+     * 
+     * Subclasses can just override the
+     * {@link #setConfigurationValueImpl(String, String)}
+     * method if they are not interested in parsing and setting those
+     * properties directly.
+     * 
+     * @param name
+     * @param value
+     * @throws IllegalArgumentException if either the key does not refer to a valid configuration option
+     *                                  for this backend or the value is not valid for the key
+     */
+    protected void setConfigurationValue(String name, String value) {
+        
+        if (name.equals(BackendsProperties.DESCRIPTION.name())) {
+            this.description = value;
+        } else if (name.equals(BackendsProperties.VERSION.name())) {
+            this.version = value;
+        } else if (name.equals(BackendsProperties.VENDOR.name())) {
+            this.vendor = value;
+        } else {
+            setConfigurationValueImpl(name, value);
+        }
+    }
+    
+    /**
+     * Set the named configuration to the given value.
+     * By default, does nothing.
+     */
+    protected void setConfigurationValueImpl(String name, String value) {}
+    
+    /**
+     * @return the name of the {@link Backend}
+     */
+    public String getName() {
+        return id.getSimpleName();
+    }
+
+    /**
+     * @returns the description of the {@link Backend}
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the vendor of the {@link Backend}
+     */
+    public String getVendor() {
+        return vendor;
+    }
+
+    /** 
+     * @return the version of the {@link Backend}
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /** Get a map containing the current settings of this backend.
+     * Implementors of this abstract class which have some settings that
+     * are be configurable by the client must override this method
+     * to provide an appropriate map.
+     * 
+     * @return a map containing the settings of this backend
+     */
+    public Map<String, String> getConfigurationMap() {
+        return new HashMap<String, String>();
+    }
+
+    /**
+     * 
+     * @param key The constant key that corresponds to the desired configuration value
+     * @return The current value of the configuration value corresponding to the key given.
+     * @throws IllegalArgumentException if the key does not refer to a valid configuration option for
+     *                                  this backend
+     */
+    public abstract String getConfigurationValue(String key);
+
+    /**
+     * Activate the {@link Backend}.  Based on the current configuration,
+     * begin pushing data to the {@link Storage} layer.  If the {@link Backend} is
+     * already active, this method should have no effect
+     *
+     * @return true on success, false if there was an error
+     */
+    public abstract boolean activate();
+
+    /**
+     * Deactivate the {@link Backend}. The backend should release any
+     * resources that were obtained as a direct result of a call to
+     * {@link #activate()}.  If the {@link Backend} is not active, this
+     * method should have no effect
+     *
+     * @return true on success
+     */
+    public abstract boolean deactivate();
+
+    /**
+     * @return a boolean indicating whether the backend is currently active on this host
+     */
+    public abstract boolean isActive();
+
+    /**
+     * A {@link Backend} may be configured to automatically begin collecting from new Java
+     * processes.  This method determines whether this will be the case when the backend
+     * is initially started.
+     * 
+     * @return true if the initial backend behaviour is to attach to new java processes, false otherwise.
+     */
+    public abstract boolean attachToNewProcessByDefault();
+
+    /**
+     * Indicate whether this backend will attach to new java processes.
+     * 
+     * @return true if this backend will attach to new java processes, false otherwise.
+     */
+    public boolean getObserveNewJvm() {
+        return observeNewJvm;
+    }
+
+    /**
+     * Set whether this backend will attach to new java processes.
+     * 
+     * @param newValue
+     */
+    public void setObserveNewJvm(boolean newValue) {
+        observeNewJvm = newValue;
+    }
+
+    void setID(BackendID backendID) {
+        this.id = backendID;
+    }
+    
+    public BackendID getID() {
+        return id;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendConfigurationLoader.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import com.redhat.thermostat.common.config.ConfigUtils;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+class BackendConfigurationLoader {
+
+    public Map<String, String> retrieveBackendConfigs(String name) throws InvalidConfigurationException {
+        
+        // reads the backend
+        File backend = new File(ConfigUtils.getBackendsBaseDirectory(), name);
+        backend = new File(backend, BackendsProperties.PROPERTY_FILE);
+        if (!backend.isFile() || !backend.canRead()) {
+            throw new InvalidConfigurationException("invalid backend configuration file: " + backend);
+        }
+        
+        Properties props = new Properties();
+        try {
+            props.load(new FileInputStream(backend));
+        } catch (IOException e) {
+            throw new InvalidConfigurationException("invalid backend configuration file", e);
+        }
+        
+        return toMap(props);
+    }
+
+    private static Map<String, String> toMap(Properties props) {
+
+        Map<String, String> configMap = new HashMap<>();
+        for (Entry<Object, Object> e : props.entrySet()) {
+            String key = (String) e.getKey();
+            String value = (String) e.getValue();
+            
+            configMap.put(key, value);
+        }
+        return configMap;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendID.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public class BackendID {
+
+    private String simpleName;
+    private String className;
+    
+    public BackendID(String simpleName, String className) {
+        this.simpleName = simpleName;
+        this.className = className;
+    }
+    
+    public String getSimpleName() {
+        return simpleName;
+    }
+    
+    public String getClassName() {
+        return className;
+    }
+    
+    @Override
+    public String toString() {
+        return simpleName + " = " + className;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendLoadException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public class BackendLoadException extends Exception {
+
+    private static final long serialVersionUID = 4057881401012295723L;
+
+    public BackendLoadException(String message) {
+        super(message);
+    }
+
+    public BackendLoadException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+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.config.AgentStartupConfiguration;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * A registry for {@link Backend}s. Each {@link Backend} should call
+ * {@link #register(Backend)} to register itself.
+ */
+public class BackendRegistry {
+
+    private static final Logger logger = LoggingUtils.getLogger(BackendRegistry.class);
+
+    private final Map<String, Backend> registeredBackends;
+
+    public BackendRegistry(AgentStartupConfiguration config) throws BackendLoadException {
+        this(config, new BackendConfigurationLoader());
+    }
+
+    public BackendRegistry(AgentStartupConfiguration config, BackendConfigurationLoader backendConfigLoader) throws BackendLoadException {
+
+        registeredBackends = new HashMap<String, Backend>();
+        
+        List<BackendID> backends = config.getBackends();
+
+        DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
+        
+        /*
+         * Configure the dynamic/custom backends
+         */
+        for (BackendID backendID : backends) {
+            logger.log(Level.FINE, "Initializing backend: \"" + backendID.getClassName() + "\"");
+            Backend backend = null;
+            try {
+                Class<? > c = Class.forName(backendID.getClassName());
+                Class<? extends Backend> narrowed = c.asSubclass(Backend.class);
+                Constructor<? extends Backend> backendConstructor = narrowed.getConstructor();
+                backend = backendConstructor.newInstance();
+
+                backend.setDAOFactory(df);
+                backend.setID(backendID);
+                
+                backend.setInitialConfiguration(backendConfigLoader.retrieveBackendConfigs(backend.getName()));
+            } catch (Exception e) {
+                throw new BackendLoadException("Could not instantiate configured backend class: " + backendID.getClassName(), e);
+            }
+            register(backend);
+        }
+    }
+
+    private synchronized void register(Backend backend) throws BackendLoadException {
+        if (registeredBackends.containsKey(backend.getName())) {
+            throw new BackendLoadException("Attempt to register two backends with the same name: " + backend.getName());
+        }
+        registeredBackends.put(backend.getName(), backend);
+    }
+
+    private synchronized void unregister(Backend backend) {
+        registeredBackends.remove(backend.getName());
+    }
+
+    public synchronized Collection<Backend> getAll() {
+        return registeredBackends.values();
+    }
+
+    public synchronized Backend getByName(String name) {
+        for (Backend backend : registeredBackends.values()) {
+            if (backend.getName().equals((name))) {
+                return backend;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/BackendsProperties.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+/**
+ * Properties that any Backend needs to have, at minimum.
+ */
+public enum BackendsProperties {
+    
+    DESCRIPTION,
+    VENDOR,
+    VERSION,
+    BACKEND_CLASS;
+    
+    public static final String PROPERTY_FILE = "backend.properties";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.sample;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * Just an example backend implementation.  This is really just to test the loading and configuration mechanisms
+ */
+public class SampleBackend extends Backend {
+    private final String NAME = "sample-backend";
+    private final String DESCRIPTION = "A backend which does nothing at all.";
+    private final String VENDOR = "Nobody";
+    private final String VERSION = "0.1";
+    private boolean currentlyActive = false;
+
+    private Logger logger = LoggingUtils.getLogger(SampleBackend.class);
+
+    private final Map<String, String> config = new HashMap<>();
+
+    public SampleBackend() {
+        super();
+    }
+
+    @Override
+    protected void setConfigurationValue(String name, String value) {
+        logger.log(Level.FINE, "Setting configuration value for backend: " + this.NAME);
+        logger.log(Level.FINE, "key: " + name + "    value: " + value);
+        config.put(name, value);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return DESCRIPTION;
+    }
+
+    @Override
+    public String getVendor() {
+        return VENDOR;
+    }
+
+    @Override
+    public String getVersion() {
+        return VERSION;
+    }
+
+    @Override
+    public Map<String, String> getConfigurationMap() {
+        return Collections.unmodifiableMap(config);
+    }
+
+    @Override
+    public String getConfigurationValue(String key) {
+        return config.get(key);
+    }
+
+    @Override
+    public boolean activate() {
+        currentlyActive = true;
+        return true;
+    }
+
+    @Override
+    public boolean deactivate() {
+        currentlyActive = false;
+        return true;
+    }
+
+    @Override
+    public boolean isActive() {
+        return currentlyActive;
+    }
+
+    @Override
+    protected Collection<Category> getCategories() {
+        return new HashSet<Category>();
+    }
+
+    @Override
+    public boolean attachToNewProcessByDefault() {
+        return false;
+    }
+
+    @Override
+    protected void setDAOFactoryAction() {
+        // TODO Auto-generated method stub
+        
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class CpuStatBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class);
+
+    private final ProcDataSource dataSource;
+
+    public CpuStatBuilder(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public CpuStat build() {
+        try (BufferedReader reader = new BufferedReader(dataSource.getCpuLoadReader())) {
+            return build(reader);
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "unable to read data source for cpu info");
+        }
+        return new CpuStat(System.currentTimeMillis(),
+                CpuStat.INVALID_LOAD, CpuStat.INVALID_LOAD, CpuStat.INVALID_LOAD);
+    }
+
+    private CpuStat build(BufferedReader reader) throws IOException {
+        long timestamp = System.currentTimeMillis();
+        double load5 = CpuStat.INVALID_LOAD;
+        double load10 = CpuStat.INVALID_LOAD;
+        double load15 = CpuStat.INVALID_LOAD;
+        String[] loadAvgParts = reader.readLine().split(" +");
+        if (loadAvgParts.length >= 3) {
+            try {
+                load5 = Double.valueOf(loadAvgParts[0]);
+                load10 = Double.valueOf(loadAvgParts[1]);
+                load15 = Double.valueOf(loadAvgParts[2]);
+            } catch (NumberFormatException nfe) {
+                logger.log(Level.WARNING, "error extracting load");
+            }
+        }
+        return new CpuStat(timestamp, load5, load10, load15);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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() {
+        try {
+            return new EtcOsRelease().getDistributionInformation();
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "unable to use os-release", e);
+        }
+        try {
+            return new LsbRelease().getDistributionInformation();
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "unable to use lsb_release", e);
+        }
+        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;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.FileReader;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class EtcOsRelease implements DistributionInformationSource {
+
+    private static final Logger logger = LoggingUtils.getLogger(EtcOsRelease.class);
+
+    private static final String OS_RELEASE = "/etc/os-release";
+
+    @Override
+    public DistributionInformation getDistributionInformation() throws IOException {
+        return getFromOsRelease();
+    }
+
+    public DistributionInformation getFromOsRelease() throws IOException {
+        return getFromOsRelease(OS_RELEASE);
+    }
+
+    public DistributionInformation getFromOsRelease(String releaseFile) throws IOException {
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(releaseFile));
+            return getFromOsRelease(reader);
+        } finally {
+            try {
+                if (reader != null) {
+                    reader.close();
+                }
+            } catch (IOException e) {
+                logger.log(Level.WARNING, "unable to close input stream", e);
+            }
+        }
+    }
+
+    public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException {
+        String name = "Linux";
+        String version = DistributionInformation.UNKNOWN_VERSION;
+        String line = null;
+        while ((line = reader.readLine()) != null) {
+            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/agent/core/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.common.Constants;
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class HostInfoBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class);
+
+    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 long totalMemory;
+
+        public HostMemoryInfo(long totalMemory) {
+            this.totalMemory = totalMemory;
+        }
+    }
+
+    private final ProcDataSource dataSource;
+
+    public HostInfoBuilder(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public HostInfo build() {
+        String hostname = getHostName();
+        HostCpuInfo cpuInfo = getCpuInfo();
+        HostMemoryInfo memoryInfo = getMemoryInfo();
+        HostOsInfo osInfo = getOsInfo();
+
+        return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, memoryInfo.totalMemory);
+    }
+
+    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() {
+        long totalMemory = -1;
+        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 = data * Constants.KILOBYTES_TO_BYTES;
+            }
+        } catch (IOException ioe) {
+            logger.log(Level.WARNING, "unable to read memory info");
+        }
+
+        logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes");
+        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() {
+        try {
+            InetAddress localAddress = null;
+            localAddress = InetAddress.getLocalHost();
+            return getHostName(localAddress);
+        } catch (UnknownHostException uhe) {
+            logger.log(Level.WARNING, "unable to get hostname", uhe);
+        }
+
+        return Constants.AGENT_LOCAL_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/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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 com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+
+import sun.jvmstat.monitor.Monitor;
+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);
+    }
+
+    public long getTotalCollectors() throws MonitorException {
+        return (Long) vm.findByName("sun.gc.policy.collectors").getValue();
+    }
+
+    public String getCollectorName(long collector) throws MonitorException {
+        return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue();
+    }
+
+    public long getCollectorTime(long collector) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue();
+    }
+
+    public long getCollectorInvocations(long collector) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue();
+    }
+
+    public long getTotalGcGenerations() throws MonitorException {
+        return (Long) vm.findByName("sun.gc.policy.generations").getValue();
+    }
+
+    public String getGenerationName(long generation) throws MonitorException {
+        return (String) vm.findByName("sun.gc.generation." + generation + ".name").getValue();
+    }
+
+    public long getGenerationCapacity(long generation) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".capacity").getValue();
+    }
+
+    public long getGenerationMaxCapacity(long generation) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".maxCapacity").getValue();
+    }
+
+    public String getGenerationCollector(long generation) throws MonitorException {
+        // this is just re-implementing getCollectorName()
+        // TODO check generation number and collector number are always associated
+        Monitor m = vm.findByName("sun.gc.collector." + generation + ".name");
+        if (m == null) {
+            return Generation.COLLECTOR_NONE;
+        }
+        return (String) m.getValue();
+    }
+
+    public long getTotalSpaces(long generation) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".spaces").getValue();
+    }
+
+    public String getSpaceName(long generation, long space) throws MonitorException {
+        return (String) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".name").getValue();
+    }
+
+    public long getSpaceCapacity(long generation, long space) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".capacity").getValue();
+    }
+
+    public long getSpaceMaxCapacity(long generation, long space) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".maxCapacity").getValue();
+    }
+
+    public long getSpaceUsed(long generation, long space) throws MonitorException {
+        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".used").getValue();
+    }
+
+    public long getLoadedClasses() throws MonitorException {
+        return (Long) vm.findByName("java.cls.loadedClasses").getValue();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+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.JvmStatusListener;
+import com.redhat.thermostat.agent.JvmStatusNotifier;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class JvmStatHostListener implements HostListener, JvmStatusNotifier {
+
+    private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class);
+
+    private boolean attachNew;
+    private final DAOFactory df;
+    private final VmInfoDAO vmInfoDAO;
+
+    private Map<Integer, MonitoredVm> monitoredVms  = new HashMap<>();
+
+    private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>();
+
+    JvmStatHostListener(DAOFactory df, boolean attachNew) {
+        this.df = df;
+        this.vmInfoDAO = df.getVmInfoDAO();
+        this.attachNew = attachNew;
+    }
+
+    @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 vmId, MonitoredHost host)
+            throws MonitorException, URISyntaxException {
+        MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve(
+                new VmIdentifier(vmId.toString())));
+        if (vm != null) {
+            VmInfo info = null;
+            try {
+                long startTime = System.currentTimeMillis();
+                long stopTime = Long.MIN_VALUE;
+                JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+                Map<String, String> properties = new HashMap<String, String>();
+                ProcDataSource dataSource = new ProcDataSource();
+                Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmId);
+                // TODO actually figure out the loaded libraries.
+                List<String> loadedNativeLibraries = new ArrayList<String>();
+                info = new VmInfo(vmId, startTime, stopTime,
+                        extractor.getJavaVersion(), extractor.getJavaHome(),
+                        extractor.getMainClass(), extractor.getCommandLine(),
+                        extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(),
+                        properties, environment, loadedNativeLibraries);
+                vmInfoDAO.putVmInfo(info);
+                logger.finer("Sent VM_STARTED messsage");
+            } catch (MonitorException me) {
+                logger.log(Level.WARNING, "error getting vm info for " + vmId, me);
+            }
+
+            if (attachNew) {
+                vm.addVmListener(new JvmStatVmListener(df, vmId));
+                vm.addVmListener(new JvmStatVmClassListener(df, vmId));
+            } else {
+                logger.log(Level.FINE, "skipping new vm " + vmId);
+            }
+            for (JvmStatusListener statusListener : statusListeners) {
+                statusListener.jvmStarted(vmId);
+            }
+
+            monitoredVms.put(vmId, vm);
+        }
+    }
+
+    private void sendStoppedVM(Integer vmId, MonitoredHost host)
+            throws URISyntaxException, MonitorException {
+        VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(
+                new VmIdentifier(vmId.toString()));
+        if (resolvedVmID != null) {
+            long stopTime = System.currentTimeMillis();
+            for (JvmStatusListener statusListener : statusListeners) {
+                statusListener.jvmStopped(vmId);
+            }
+            vmInfoDAO.putVmStoppedTime(vmId, stopTime);
+
+            monitoredVms.remove(vmId).detach();
+        }
+    }
+
+    @Override
+    public void addJvmStatusListener(JvmStatusListener listener) {
+        statusListeners.add(listener);
+    }
+
+    @Override
+    public void removeJvmStatusListener(JvmStatusListener listener) {
+        statusListeners.remove(listener);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Level;
+import java.util.logging.Logger;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.event.MonitorStatusChangeEvent;
+import sun.jvmstat.monitor.event.VmEvent;
+import sun.jvmstat.monitor.event.VmListener;
+
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+class JvmStatVmClassListener implements VmListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(JvmStatVmClassListener.class);
+
+    private VmClassStatDAO dao;
+    private int vmId;
+
+    JvmStatVmClassListener(DAOFactory df, int vmId) {
+        this.dao = df.getVmClassStatsDAO();
+        this.vmId = vmId;
+    }
+
+    @Override
+    public void disconnected(VmEvent vmEvent) {
+        /* nothing to do here */
+    }
+
+    @Override
+    public void monitorStatusChanged(MonitorStatusChangeEvent vmEvent) {
+        /* nothing to do here */
+    }
+
+    @Override
+    public void monitorsUpdated(VmEvent vmEvent) {
+        MonitoredVm vm = vmEvent.getMonitoredVm();
+        try {
+            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+            long loadedClasses = extractor.getLoadedClasses();
+            long timestamp = System.currentTimeMillis();
+            VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses);
+            dao.putVmClassStat(stat);
+        } catch (MonitorException e) {
+            logger.log(Level.WARNING, "error gathering class info for vm " + vmId, e);
+        }
+
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.event.MonitorStatusChangeEvent;
+import sun.jvmstat.monitor.event.VmEvent;
+import sun.jvmstat.monitor.event.VmListener;
+
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class JvmStatVmListener implements VmListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class);
+
+    private final int vmId;
+    private final VmGcStatDAO gcDAO;
+    private final VmMemoryStatDAO memDAO;
+
+    public JvmStatVmListener(DAOFactory df, int vmId) {
+        gcDAO = df.getVmGcStatDAO();
+        memDAO = df.getVmMemoryStatDAO();
+        this.vmId = vmId;
+    }
+
+    @Override
+    public void disconnected(VmEvent event) {
+        /* nothing to do here */
+    }
+
+    @Override
+    public void monitorStatusChanged(MonitorStatusChangeEvent event) {
+        /* nothing to do here */
+    }
+
+    @Override
+    public void monitorsUpdated(VmEvent event) {
+        MonitoredVm vm = event.getMonitoredVm();
+        if (vm == null) {
+            throw new NullPointerException();
+        }
+        recordMemoryStat(vm);
+        recordGcStat(vm);
+    }
+
+    private void recordGcStat(MonitoredVm vm) {
+        try {
+            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+            long collectors = extractor.getTotalCollectors();
+            for (int i = 0; i < collectors; i++) {
+                long timestamp = System.currentTimeMillis();
+                VmGcStat stat = new VmGcStat(vmId, timestamp,
+                        extractor.getCollectorName(i),
+                        extractor.getCollectorInvocations(i),
+                        extractor.getCollectorTime(i));
+                gcDAO.putVmGcStat(stat);
+            }
+        } catch (MonitorException e) {
+            logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e);
+        }
+
+    }
+
+    private void recordMemoryStat(MonitoredVm vm) {
+        try {
+            long timestamp = System.currentTimeMillis();
+            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+            long maxGenerations = extractor.getTotalGcGenerations();
+            List<Generation> generations = new ArrayList<Generation>();
+            VmMemoryStat stat = new VmMemoryStat(timestamp, vmId, generations);
+            for (long generation = 0; generation < maxGenerations; generation++) {
+                Generation g = new Generation();
+                generations.add(g);
+                g.name = extractor.getGenerationName(generation);
+                g.capacity = extractor.getGenerationCapacity(generation);
+                g.maxCapacity = extractor.getGenerationMaxCapacity(generation);
+                g.collector = extractor.getGenerationCollector(generation);
+                long maxSpaces = extractor.getTotalSpaces(generation);
+                List<Space> spaces = new ArrayList<Space>();
+                g.spaces = spaces;
+                for (long space = 0; space < maxSpaces; space++) {
+                    Space s = new Space();
+                    spaces.add(s);
+                    s.index = (int) space;
+                    s.name = extractor.getSpaceName(generation, space);
+                    s.capacity = extractor.getSpaceCapacity(generation, space);
+                    s.maxCapacity = extractor.getSpaceMaxCapacity(generation, space);
+                    s.used = extractor.getSpaceUsed(generation, space);
+                }
+            }
+            memDAO.putVmMemoryStat(stat);
+        } catch (MonitorException e) {
+            logger.log(Level.WARNING, "error gathering memory info for vm " + vmId, e);
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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";
+
+    @Override
+    public DistributionInformation getDistributionInformation()
+            throws IOException {
+        return getFromLsbRelease();
+    }
+
+    public DistributionInformation getFromLsbRelease() throws IOException {
+
+        BufferedReader reader = null;
+        try {
+            Process lsbProc = Runtime.getRuntime().exec(new String[] { "lsb_release", "-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/agent/core/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.Constants;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * Implementation note: uses information from /proc/
+ */
+public class MemoryStatBuilder {
+
+    private static final long UNAVAILABLE = -1;
+
+    private static final String KEY_MEMORY_TOTAL = "MemTotal";
+    private static final String KEY_MEMORY_FREE = "MemFree";
+    private static final String KEY_BUFFERS = "Buffers";
+    private static final String KEY_CACHED = "Cached";
+    private static final String KEY_SWAP_TOTAL = "SwapTotal";
+    private static final String KEY_SWAP_FREE = "SwapFree";
+    private static final String KEY_COMMIT_LIMIT = "CommitLimit";
+
+    private static final Logger logger = LoggingUtils.getLogger(MemoryStatBuilder.class);
+
+    private final ProcDataSource dataSource;
+
+    public MemoryStatBuilder(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    protected MemoryStat build() {
+        long timestamp = System.currentTimeMillis();
+
+        long total = UNAVAILABLE;
+        long free = UNAVAILABLE;
+        long swapTotal = UNAVAILABLE;
+        long swapFree = UNAVAILABLE;
+        long buffers = UNAVAILABLE;
+        long cached = UNAVAILABLE;
+        long commitLimit = UNAVAILABLE;
+
+        try (BufferedReader reader = new BufferedReader(dataSource.getMemInfoReader())) {
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                String[] parts = line.split(":");
+                if (parts.length == 2) {
+                    String key = parts[0].trim();
+                    long value = getValue(parts[1].trim());
+                    if (key.equals(KEY_MEMORY_TOTAL)) {
+                        total = value;
+                    } else if (key.equals(KEY_MEMORY_FREE)) {
+                        free = value;
+                    } else if (key.equals(KEY_SWAP_TOTAL)) {
+                        swapTotal = value;
+                    } else if (key.equals(KEY_SWAP_FREE)) {
+                        swapFree = value;
+                    } else if (key.equals(KEY_BUFFERS)) {
+                        buffers = value;
+                    } else if (key.equals(KEY_CACHED)) {
+                        cached = value;
+                    } else if (key.equals(KEY_COMMIT_LIMIT)) {
+                        commitLimit = value;
+                    }
+                }
+            }
+        } catch (IOException ioe) {
+            logger.log(Level.WARNING, "unable to read memory info");
+        }
+
+        return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit);
+    }
+
+    private long getValue(String rawValue) {
+        String[] parts = rawValue.split(" +");
+        String value = rawValue;
+        String units = null;
+        if (parts.length > 1) {
+            value = parts[0];
+            units = parts[1];
+        }
+
+        long result = UNAVAILABLE;
+        try {
+            result = Long.parseLong(value);
+            if (units != null) {
+                if (units.equals("kB") || units.equals("KB")) {
+                    result = result * Constants.KILOBYTES_TO_BYTES;
+                } else {
+                    throw new NotImplementedException("unit conversion from " + units + " not implemented");
+                }
+            }
+        } catch (NumberFormatException nfe) {
+            logger.log(Level.WARNING, "error extracting memory info");
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class NetworkInfoBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class);
+
+    public static List<NetworkInterfaceInfo> build() {
+        List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>();
+        try {
+            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+            for (NetworkInterface iface : Collections.list(ifaces)) {
+                NetworkInterfaceInfo info = new NetworkInterfaceInfo(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/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcDataSource.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+
+public class ProcDataSource {
+
+    private static final String LOAD_FILE = "/proc/loadavg";
+    private static final String MEMINFO_FILE = "/proc/meminfo";
+    private static final String CPUINFO_FILE = "/proc/cpuinfo";
+
+    private static final String PID_STAT_FILE = "/proc/${pid}/stat";
+    private static final String PID_ENVIRON_FILE = "/proc/${pid}/environ";
+
+    /**
+     * Returns a reader for /proc/cpuinfo
+     */
+    public Reader getCpuInfoReader() throws IOException {
+        return new FileReader(CPUINFO_FILE);
+    }
+
+    /**
+     * Returns a reader for /proc/loadavg
+     */
+    public Reader getCpuLoadReader() throws IOException {
+        return new FileReader(LOAD_FILE);
+    }
+
+    /**
+     * Returns a reader for /proc/meminfo
+     */
+    public Reader getMemInfoReader() throws IOException {
+        return new FileReader(MEMINFO_FILE);
+    }
+
+    /**
+     * Returns a reader for /proc/$PID/stat
+     */
+    public Reader getStatReader(int pid) throws IOException {
+        return new FileReader(getPidFile(PID_STAT_FILE, pid));
+    }
+
+    /**
+     * Returns a reader for /proc/$PID/environ
+     */
+    public Reader getEnvironReader(int pid) throws IOException {
+        return new FileReader(getPidFile(PID_ENVIRON_FILE, pid));
+    }
+
+    private String getPidFile(String fileName, int pid) {
+        return fileName.replace("${pid}", Integer.toString(pid));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.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/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public class ProcessStatusInfo {
+
+    /* All times are measured in clock ticks */
+
+    private final int pid;
+    private final long userTime;
+    private final long kernelTime;
+
+    public ProcessStatusInfo(int pid, long userTime, long kernelTime) {
+        this.pid = pid;
+        this.userTime = userTime;
+        this.kernelTime = kernelTime;
+    }
+
+    public int getPid() {
+        return pid;
+    }
+
+    /**
+     * @return the time this process has spent in user-mode as a number of
+     * kernel ticks
+     */
+    public long getUserTime() {
+        return userTime;
+    }
+
+    /**
+     * @return the time this process spent in kernel-mode as a number of kernel
+     * ticks
+     */
+    public long getKernelTime() {
+        return kernelTime;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/**
+ * Extract status information about the process from /proc/. This is what tools
+ * like {@code ps} and {@code top} use.
+ *
+ * @see {@code proc(5)}
+ */
+public class ProcessStatusInfoBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(ProcessStatusInfoBuilder.class);
+
+    private final ProcDataSource dataSource;
+
+    public ProcessStatusInfoBuilder(ProcDataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public ProcessStatusInfo build(int pid) {
+        try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) {
+            return build(reader);
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "unable to read stat info for " + pid);
+        }
+
+        return null;
+    }
+
+    private ProcessStatusInfo build(Reader r) throws IOException {
+
+        int pid = -1;
+        long utime = -1;
+        long stime = -1;
+
+        Scanner scanner = null;
+
+        /* TODO map these (effectively c) data types to java types more sanely */
+
+        try (BufferedReader reader = new BufferedReader(r)) {
+            String statusLine = reader.readLine();
+
+            /* be prepared for process names like '1 ) 2 3 4 foo 5' */
+
+            scanner = new Scanner(statusLine);
+            pid = scanner.nextInt();
+            scanner.close();
+
+            int execEndNamePos = statusLine.lastIndexOf(')');
+
+            String cleanStatusLine = statusLine.substring(execEndNamePos + 1);
+
+            scanner = new Scanner(cleanStatusLine);
+            /* state = */scanner.next();
+            /* ppid = */scanner.nextInt();
+            /* pgrp = */scanner.nextInt();
+            /* session = */scanner.nextInt();
+            /* tty_nr = */scanner.nextInt();
+            /* tpgid = */scanner.nextInt();
+            /* flags = */scanner.nextInt();
+            /* minflt = */scanner.nextLong();
+            /* cminflt = */scanner.nextLong();
+            /* majflt = */scanner.nextLong();
+            /* cmajflt = */scanner.nextLong();
+            utime = scanner.nextLong();
+            stime = scanner.nextLong();
+            scanner.close();
+        }
+
+        return new ProcessStatusInfo(pid, utime, stime);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/SysConf.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.InputStreamReader;
+
+/**
+ * A wrapper over POSIX's sysconf.
+ * <p>
+ * Implementation notes: uses {@code getconf(1)}
+ */
+public class SysConf {
+
+    private SysConf() {
+        /* do not initialize */
+    }
+
+    public static long getClockTicksPerSecond() {
+        String ticks = sysConf("CLK_TCK");
+        try {
+            return Long.valueOf(ticks);
+        } catch (NumberFormatException nfe) {
+            return 0;
+        }
+    }
+
+    private static String sysConf(String arg) {
+        BufferedReader reader = null;
+        try {
+            Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg });
+            int result = process.waitFor();
+            if (result != 0) {
+                return null;
+            }
+            reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            return reader.readLine();
+        } catch (IOException e) {
+            return null;
+        } catch (InterruptedException e) {
+            return null;
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    // TODO
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.CopyOnWriteArraySet;
+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.JvmStatusListener;
+import com.redhat.thermostat.agent.JvmStatusNotifier;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.SystemClock;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class SystemBackend extends Backend implements JvmStatusNotifier, JvmStatusListener {
+
+    private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class);
+
+    private CpuStatDAO cpuStats;
+    private HostInfoDAO hostInfos;
+    private MemoryStatDAO memoryStats;
+    private VmCpuStatDAO vmCpuStats;
+    private NetworkInterfaceInfoDAO networkInterfaces;
+
+    private final List<Category> categories = new ArrayList<Category>();
+
+    private final Set<Integer> pidsToMonitor = new CopyOnWriteArraySet<Integer>();
+
+    private long procCheckInterval = 1000; // TODO make this configurable.
+
+    private Timer timer = null;
+
+    private HostIdentifier hostId = null;
+    private MonitoredHost host = null;
+    private JvmStatHostListener hostListener;
+
+    private final VmCpuStatBuilder vmCpuBuilder;
+    private final HostInfoBuilder hostInfoBuilder;
+    private final CpuStatBuilder cpuStatBuilder;
+    private final MemoryStatBuilder memoryStatBuilder;
+
+    public SystemBackend() {
+        super();
+
+        // Set up categories that will later be registered.
+        categories.add(CpuStatDAO.cpuStatCategory);
+        categories.add(HostInfoDAO.hostInfoCategory);
+        categories.add(MemoryStatDAO.memoryStatCategory);
+        categories.add(NetworkInterfaceInfoDAO.networkInfoCategory);
+        categories.add(VmClassStatDAO.vmClassStatsCategory);
+        categories.add(VmCpuStatDAO.vmCpuStatCategory);
+        categories.add(VmGcStatDAO.vmGcStatCategory);
+        categories.add(VmInfoDAO.vmInfoCategory);
+        categories.add(VmMemoryStatDAO.vmMemoryStatsCategory);
+
+        Clock clock = new SystemClock();
+        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource());
+        long ticksPerSecond = SysConf.getClockTicksPerSecond();
+        ProcDataSource source = new ProcDataSource();
+        hostInfoBuilder = new HostInfoBuilder(source);
+        cpuStatBuilder = new CpuStatBuilder(source);
+        memoryStatBuilder = new MemoryStatBuilder(source);
+
+        int cpuCount = hostInfoBuilder.getCpuInfo().count;
+        vmCpuBuilder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, builder);
+    }
+
+    @Override
+    protected void setDAOFactoryAction() {
+        cpuStats = df.getCpuStatDAO();
+        hostInfos = df.getHostInfoDAO();
+        memoryStats = df.getMemoryStatDAO();
+        vmCpuStats = df.getVmCpuStatDAO();
+        networkInterfaces = df.getNetworkInterfaceInfoDAO();
+        hostListener = new JvmStatHostListener(df, getObserveNewJvm());
+    }
+
+    @Override
+    public synchronized boolean activate() {
+        if (timer != null) {
+            return true;
+        }
+        if (df == null) {
+            throw new IllegalStateException("Cannot activate backend without DAOFactory.");
+        }
+
+        addJvmStatusListener(this);
+
+        if (!getObserveNewJvm()) {
+            logger.fine("not monitoring new vms");
+        }
+        hostInfos.putHostInfo(hostInfoBuilder.build());
+
+        timer = new Timer();
+        timer.scheduleAtFixedRate(new TimerTask() {
+            @Override
+            public void run() {
+                cpuStats.putCpuStat(cpuStatBuilder.build());
+                for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) {
+                    networkInterfaces.putNetworkInterfaceInfo(info);
+                }
+                memoryStats.putMemoryStat(memoryStatBuilder.build());
+
+                for (Integer pid : pidsToMonitor) {
+                    if (vmCpuBuilder.knowsAbout(pid)) {
+                        VmCpuStat dataBuilt = vmCpuBuilder.build(pid);
+                        if (dataBuilt != null) {
+                            vmCpuStats.putVmCpuStat(dataBuilt);
+                        }
+                    } else {
+                        vmCpuBuilder.learnAbout(pid);
+                    }
+                }
+            }
+        }, 0, procCheckInterval);
+
+        try {
+            hostId = new HostIdentifier((String) null);
+            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;
+
+        removeJvmStatusListener(this);
+
+        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 String getConfigurationValue(String key) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    protected Collection<Category> getCategories() {
+        return Collections.unmodifiableCollection(categories);
+    }
+
+    @Override
+    public boolean attachToNewProcessByDefault() {
+        return true;
+    }
+
+    @Override
+    public void addJvmStatusListener(JvmStatusListener listener) {
+        hostListener.addJvmStatusListener(listener);
+    }
+
+    @Override
+    public void removeJvmStatusListener(JvmStatusListener listener) {
+        hostListener.removeJvmStatusListener(listener);
+    }
+
+    @Override
+    public void jvmStarted(int vmId) {
+        if (getObserveNewJvm()) {
+            pidsToMonitor.add(vmId);
+        }
+    }
+
+    @Override
+    public void jvmStopped(int vmId) {
+        pidsToMonitor.remove(vmId);
+        vmCpuBuilder.forgetAbout(vmId);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class VmCpuStatBuilder {
+
+    private static final Logger logger = LoggingUtils.getLogger(VmCpuStatBuilder.class);
+
+    // pid -> ticks
+    private final Map<Integer, Long> lastProcessTicks = new HashMap<Integer, Long>();
+    // pid -> last time the ticks were updated
+    private final Map<Integer, Long> lastProcessTickTime = new HashMap<Integer, Long>();
+
+    private final Clock clock;
+    private final int cpuCount;
+    private final long ticksPerSecond;
+    private final ProcessStatusInfoBuilder statusBuilder;
+
+    public VmCpuStatBuilder(Clock clock, int cpuCount, long ticksPerSecond, ProcessStatusInfoBuilder statusBuilder) {
+        this.clock = clock;
+        this.cpuCount = cpuCount;
+        this.ticksPerSecond = ticksPerSecond;
+        this.statusBuilder = statusBuilder;
+    }
+
+    /**
+     * @param pid the process id
+     * @return an object representing the cpu usage of the process, or null if
+     * the information can not be found.
+     */
+    public synchronized VmCpuStat build(Integer pid) {
+        if (!lastProcessTicks.containsKey(pid) || !lastProcessTickTime.containsKey(pid)) {
+            throw new IllegalArgumentException("unknown pid");
+        }
+
+        ProcessStatusInfo info = statusBuilder.build(pid);
+        if (info == null) {
+            return null;
+        }
+        long miliTime = clock.getRealTimeMillis();
+        long time = clock.getMonotonicTimeNanos();
+        long programTicks = (info.getKernelTime() + info.getUserTime());
+        double cpuLoad = 0.0;
+
+        double timeDelta = (time - lastProcessTickTime.get(pid)) * 1E-9;
+        long programTicksDelta = programTicks - lastProcessTicks.get(pid);
+        // 100 as in 100 percent.
+        cpuLoad = programTicksDelta * (100.0 / timeDelta / ticksPerSecond / cpuCount);
+
+        if (cpuLoad < 0.0 || cpuLoad > 100.0) {
+            logger.log(Level.WARNING, "cpu load for " + pid + " is outside [0,100]: " + cpuLoad);
+            logger.log(Level.WARNING, "  (" + pid + ") programTicks: " + programTicks);
+            logger.log(Level.WARNING, "  (" + pid + ") programTicksDelta: " + programTicksDelta);
+            logger.log(Level.WARNING, "  (" + pid + ") time: " + time);
+            logger.log(Level.WARNING, "  (" + pid + ") timeDelta: " + timeDelta);
+            logger.log(Level.WARNING, "  (" + pid + ") ticksPerSecond: " + ticksPerSecond);
+            logger.log(Level.WARNING, "  (" + pid + ") cpuCount: " + cpuCount);
+        }
+
+        lastProcessTicks.put(pid, programTicks);
+        lastProcessTickTime.put(pid, time);
+
+        return new VmCpuStat(miliTime, pid, cpuLoad);
+    }
+
+    public synchronized boolean knowsAbout(int pid) {
+        return (lastProcessTickTime.containsKey(pid) && lastProcessTicks.containsKey(pid));
+    }
+
+    public synchronized void learnAbout(int pid) {
+        long time = clock.getMonotonicTimeNanos();
+        ProcessStatusInfo info = statusBuilder.build(pid);
+        if (info == null) {
+            logger.log(Level.WARNING, "can not learn about pid " + pid + " : statusBuilder returned null");
+        }
+
+        lastProcessTickTime.put(pid, time);
+        lastProcessTicks.put(pid, info.getUserTime()+ info.getKernelTime());
+    }
+
+    public synchronized void forgetAbout(int pid) {
+        lastProcessTicks.remove(pid);
+        lastProcessTickTime.remove(pid);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/AgentApplicationTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.ArgumentSpec;
+import com.redhat.thermostat.common.cli.SimpleArgumentSpec;
+
+public class AgentApplicationTest {
+
+    // TODO: Test i18nized versions when they come.
+
+    private AgentApplication agent;
+
+    @Before
+    public void setUp() {
+        agent = new AgentApplication();
+    }
+
+    @After
+    public void tearDown() {
+        agent = null;
+    }
+
+    @Test
+    public void testName() {
+        String name = agent.getName();
+        assertEquals("agent", name);
+    }
+
+    @Test
+    public void testDescription() {
+        String description = agent.getDescription();
+        assertEquals("starts and stops the thermostat agent", description);
+    }
+
+    @Test
+    public void testUsage() {
+        String usage = agent.getUsage();
+        assertEquals("starts and stops the thermostat agent", usage);
+    }
+
+    @Test
+    public void testAcceptedArguments() {
+        Collection<ArgumentSpec> args = agent.getAcceptedArguments();
+        assertNotNull(args);
+        assertEquals(3, args.size());
+        assertTrue(args.contains(new SimpleArgumentSpec("saveOnExit", "s", "save the data on exit", false, false)));
+        assertTrue(args.contains(new SimpleArgumentSpec("debug", "launch with debug console enabled")));
+        assertTrue(args.contains(new SimpleArgumentSpec("dbUrl", "d", "connect to the given url", true, true)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/AgentTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.AgentInformation;
+import com.redhat.thermostat.common.storage.BackendInformation;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class AgentTest {
+
+    private AgentStartupConfiguration config;
+    private Storage storage;
+    private BackendRegistry backendRegistry;
+    private Backend backend;
+    private DAOFactory daos;
+    
+    @Before
+    public void setUp() {
+        config = mock(AgentStartupConfiguration.class);
+        when(config.getStartTime()).thenReturn(123L);
+        when(config.purge()).thenReturn(true);
+        
+        storage = mock(Storage.class);
+        daos = mock(DAOFactory.class);
+        when(daos.getStorage()).thenReturn(storage);
+        
+        backend = mock(Backend.class);
+        when(backend.getName()).thenReturn("testname");
+        when(backend.getDescription()).thenReturn("testdesc");
+        when(backend.getObserveNewJvm()).thenReturn(true);
+        when(backend.activate()).thenReturn(true); // TODO: activate() should not return anything and throw exception in error case.
+        Collection<Backend> backends = new ArrayList<Backend>();
+        backends.add(backend);
+        
+        backendRegistry = mock(BackendRegistry.class);
+        when(backendRegistry.getAll()).thenReturn(backends);
+    }
+    
+    @Test
+    public void testStartAgent() throws Exception {
+        
+        // Start agent.
+        Agent agent = new Agent(backendRegistry, config, daos);
+        agent.start();
+
+        // Verify that backend has been activated and storage received the agent information.
+        verify(backend).activate();
+        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);
+        verify(storage).addAgentInformation(argument.capture());
+        assertEquals(123, argument.getValue().getStartTime());
+        List<BackendInformation> backendInfos = argument.getValue().getBackends();
+        assertEquals(1, backendInfos.size());
+        BackendInformation backend0 = backendInfos.get(0);
+        assertEquals("testname", backend0.getName());
+        assertEquals("testdesc", backend0.getDescription());
+        assertEquals(true, backend0.isObserveNewJvm());
+        // TODO: We should probably also test getPIDs() and getConfiguration(), but it's not clear to me at this point
+        // what those should really do (and it looks like they're not implemented yet).
+    }
+    
+    @Test
+    public void testStopAgentWithPurging() throws Exception {
+        Agent agent = new Agent(backendRegistry, config, daos);
+        agent.start();
+        
+        // stop agent
+        agent.stop();
+        
+        verify(backend).deactivate();
+
+        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);        
+        verify(storage, never()).updateAgentInformation(argument.capture());
+        verify(storage, times(1)).purge();
+    }
+    
+    @Test
+    public void testStopAgent() throws Exception {
+        
+        AgentStartupConfiguration config = mock(AgentStartupConfiguration.class);
+        when(config.getStartTime()).thenReturn(123L);
+        when(config.purge()).thenReturn(false);
+        
+        Agent agent = new Agent(backendRegistry, config, daos);
+        agent.start();
+        
+        // stop agent
+        agent.stop();
+        
+        verify(backend).deactivate();
+
+        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);        
+        verify(storage).updateAgentInformation(argument.capture());
+        verify(storage, times(0)).purge();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/TestUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.Properties;
+import java.util.Random;
+
+import com.redhat.thermostat.agent.config.AgentProperties;
+import com.redhat.thermostat.backend.BackendsProperties;
+
+public class TestUtils {
+
+    public static int getProcessId() {
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        String pidPart = name.split("@")[0];
+        return Integer.parseInt(pidPart);
+    }
+
+    public static boolean isLinux() {
+        return (System.getProperty("os.name").toLowerCase().contains("linux"));
+    }
+        
+    public static String setupAgentConfigs() throws IOException {
+        // need to create dummy config files for the tests
+        Random random = new Random();
+
+        String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar +
+                Math.abs(random.nextInt()) + File.separatorChar;
+
+        System.setProperty("THERMOSTAT_HOME", tmpDir);
+        File agent = new File(tmpDir, "agent");
+        agent.mkdirs();
+
+        File tmpConfigs = new File(agent, "agent.properties");
+
+        new File(agent, "run").mkdirs();
+        new File(agent, "logs").mkdirs();
+
+        File backends = new File(tmpDir, "backends");
+        File system = new File(backends, "system");
+        system.mkdirs();
+        
+        Properties props = new Properties();            
+
+        props.setProperty(AgentProperties.BACKENDS.name(), "system");
+        props.setProperty(AgentProperties.SAVE_ON_EXIT.name(), "false");
+
+        props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties");
+
+        // now write the configs for the backends
+        tmpConfigs = new File(system, "backend.properties");
+        props = new Properties();
+        props.setProperty(BackendsProperties.BACKEND_CLASS.name(),
+                          "com.redhat.thermostat.backend.system.SystemBackend");
+        props.setProperty(BackendsProperties.DESCRIPTION.name(),
+                          "fluff backend for tests");
+        props.setProperty(BackendsProperties.VENDOR.name(),
+                          "Red Hat, Inc.");
+        props.setProperty(BackendsProperties.VERSION.name(),
+                          "1.0");
+        props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties");
+        
+        return tmpDir;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.TestUtils;
+import com.redhat.thermostat.backend.BackendID;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+public class AgentConfigsUtilsTest {
+    
+    @Before
+    public void setUp() throws IOException, InvalidConfigurationException {
+        TestUtils.setupAgentConfigs();
+    }
+    
+    @Test
+    public void test() throws InvalidConfigurationException {
+        AgentStartupConfiguration config = AgentConfigsUtils.createAgentConfigs();        
+        List<BackendID> backends = config.getBackends();
+        
+        // the test property only define the system backend so far
+        Assert.assertEquals(1, backends.size());
+        Assert.assertEquals("system", backends.get(0).getSimpleName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.config;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.TestUtils;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+public class AgentOptionParserTest {
+    
+    private static File tmpFile;
+    
+    @BeforeClass
+    public static void setup() throws IOException {
+        tmpFile = new File(TestUtils.setupAgentConfigs());
+    }
+    
+    @AfterClass
+    public static void shutdown() {
+        tmpFile.delete();
+    }
+    
+    @Test
+    public void testConfigs1() throws IOException, InvalidConfigurationException {
+        
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("dbUrl", "testURL");
+        args.addArgument("debug", "--debug");
+        
+        AgentStartupConfiguration configs = AgentConfigsUtils.createAgentConfigs();
+        AgentOptionParser parser = new AgentOptionParser(configs, args);
+        parser.parse();
+        
+        Assert.assertEquals("testURL", configs.getDBConnectionString());
+        Assert.assertTrue(configs.isDebugConsole());
+        Assert.assertTrue(configs.purge());
+    }
+    
+    @Test
+    public void testConfigs2() throws IOException, InvalidConfigurationException {
+        
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("dbUrl", "testURL2");
+        args.addArgument("saveOnExit", "--saveOnExit");
+        
+        AgentStartupConfiguration configs = new AgentStartupConfiguration();
+        AgentOptionParser parser = new AgentOptionParser(configs, args);
+        parser.parse();
+        
+        Assert.assertEquals("testURL2", configs.getDBConnectionString());
+        Assert.assertFalse(configs.isDebugConsole());
+        Assert.assertFalse(configs.purge());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/BackendConfigurationLoaderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.io.IOException;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.TestUtils;
+import com.redhat.thermostat.backend.system.SystemBackend;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+public class BackendConfigurationLoaderTest {
+    
+    @Before
+    public void setUp() throws IOException {
+        TestUtils.setupAgentConfigs();
+    }
+    
+    @Test
+    public void test() throws InvalidConfigurationException {
+        Map<String, String> backendProps = new BackendConfigurationLoader().retrieveBackendConfigs("system");
+        Assert.assertTrue(backendProps.containsKey(BackendsProperties.BACKEND_CLASS.name()));
+        
+        String className = backendProps.get(BackendsProperties.BACKEND_CLASS.name());
+        Assert.assertEquals(SystemBackend.class.getCanonicalName(), className);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class BackendRegistryTest {
+
+    public static class MockBackend extends Backend {
+        public MockBackend() {
+            super();
+        }
+
+        @Override
+        protected Collection<Category> getCategories() {
+            return Collections.emptyList();
+        }
+        @Override
+        public String getConfigurationValue(String key) {
+            return null;
+        }
+        @Override
+        public boolean activate() {
+            return true;
+        }
+        @Override
+        public boolean deactivate() {
+            return false;
+        }
+        @Override
+        public boolean isActive() {
+            return false;
+        }
+        @Override
+        public boolean attachToNewProcessByDefault() {
+            return false;
+        }
+
+        @Override
+        protected void setDAOFactoryAction() {
+            // TODO Auto-generated method stub
+            
+        }
+    }
+
+    private List<BackendID> backends;
+    private AgentStartupConfiguration config;
+    private BackendConfigurationLoader configLoader;
+
+    @Before
+    public void setUp() throws InvalidConfigurationException {
+        backends = new ArrayList<>();
+
+        config = mock(AgentStartupConfiguration.class);
+        when(config.getBackends()).thenReturn(backends);
+
+        configLoader = mock(BackendConfigurationLoader.class);
+        when(configLoader.retrieveBackendConfigs(any(String.class))).thenReturn(new HashMap<String,String>());
+
+        Storage storage = mock(Storage.class);
+        DAOFactory df = mock(DAOFactory.class);
+        when(df.getStorage()).thenReturn(storage);
+        ApplicationContext.getInstance().setDAOFactory(df);
+    }
+
+    @After
+    public void tearDown() {
+        backends = null;
+        config = null;
+        configLoader = null;
+    }
+
+    @Test
+    public void testRegisterBackend() throws BackendLoadException, InvalidConfigurationException {
+        /* setup fake backend */
+        backends.add(new BackendID("mock", MockBackend.class.getName()));
+
+        BackendRegistry registry = new BackendRegistry(config, configLoader);
+        assertEquals(1, registry.getAll().size());
+        assertNotNull(registry.getByName("mock"));
+    }
+
+    @Test
+    public void testNoBackendsRegistered() throws InvalidConfigurationException, BackendLoadException {
+        BackendRegistry registry = new BackendRegistry(config, configLoader);
+        assertEquals(0, registry.getAll().size());
+        assertEquals(null, registry.getByName("system"));
+        assertEquals(null, registry.getByName("mock"));
+    }
+
+    @Test (expected=BackendLoadException.class)
+    public void testRegisterBackendTwice() throws BackendLoadException, InvalidConfigurationException {
+        /* setup fake backends */
+
+        backends.add(new BackendID("mock", MockBackend.class.getClass().getName()));
+        backends.add(new BackendID("mock", MockBackend.class.getClass().getName()));
+
+        /* load the backends */
+        new BackendRegistry(config, configLoader);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/sample/SampleBackendTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.sample;
+
+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 java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.storage.Category;
+
+public class SampleBackendTest {
+
+    private SampleBackend b;
+
+    @Before
+    public void setUp() {
+        b = new SampleBackend();
+    }
+
+    @Test
+    public void testBackendInfo() {
+        assertNotNull(b.getName());
+        assertNotNull(b.getVersion());
+        assertNotNull(b.getVendor());
+        assertNotNull(b.getDescription());
+    }
+
+    @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 testCategoriesAreSane() {
+        Collection<Category> categories = b.getCategories();
+        assertEquals(0, categories.size());
+    }
+
+    @Test
+    public void testDefaultConfiguration() {
+        assertTrue(b.getConfigurationMap().isEmpty());
+        assertTrue(b.getConfigurationValue("foo") == null);
+
+    }
+
+    @Test
+    public void testModifyConfiguration() {
+        b.setConfigurationValue("speed", "fast");
+        assertEquals("fast", b.getConfigurationValue("speed"));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.CpuStat;
+
+public class CpuStatBuilderTest {
+
+    @Test
+    public void testSimpleBuild() {
+        ProcDataSource dataSource = new ProcDataSource();
+        CpuStat stat = new CpuStatBuilder(dataSource).build();
+        assertNotNull(stat);
+    }
+
+    @Test
+    public void testBuildCpuStatFromFile() throws IOException {
+        String line = "0.05 0.08 0.06 1/368 16413";
+        BufferedReader reader = new BufferedReader(new StringReader(line));
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getCpuLoadReader()).thenReturn(reader);
+        CpuStat stat = new CpuStatBuilder(dataSource).build();
+
+        verify(dataSource).getCpuLoadReader();
+        assertEquals(0.05, stat.getLoad5(), 0.01);
+        assertEquals(0.08, stat.getLoad10(), 0.01);
+        assertEquals(0.06, stat.getLoad15(), 0.01);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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 org.junit.Test;
+
+import com.redhat.thermostat.agent.TestUtils;
+
+public class DistributionInformationTest {
+
+    @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/agent/core/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.test.Bug;
+
+public class EtcOsReleaseTest {
+
+    @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());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Test;
+
+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.Constants;
+import com.redhat.thermostat.common.model.HostInfo;
+
+public class HostInfoBuilderTest {
+
+    @Test
+    public void testSimpleBuild() {
+        HostInfo info = new HostInfoBuilder(new ProcDataSource()).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).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).getMemoryInfo();
+        assertNotNull(memoryInfo);
+        assertEquals(12345 * Constants.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).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).getHostName(address);
+        assertEquals("test-hostname", name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.LongMonitor;
+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;
+    }
+
+    private MonitoredVm buildLongMonitoredVm(String monitorName, Long monitorReturn) throws MonitorException {
+        final LongMonitor monitor = mock(LongMonitor.class);
+        when(monitor.longValue()).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);
+    }
+
+    @Test
+    public void testTotalCollectors() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.policy.collectors";
+        final Long MONITOR_VALUE = 9l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getTotalCollectors();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(MONITOR_VALUE, returned);
+    }
+
+    @Test
+    public void testCollectorName() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.collector.0.name";
+        final String COLLECTOR_NAME = "SomeMemoryCollector";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getCollectorName(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(COLLECTOR_NAME, returned);
+    }
+
+    @Test
+    public void testCollectorTime() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.collector.0.time";
+        final Long COLLECTOR_TIME = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getCollectorTime(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(COLLECTOR_TIME, returned);
+    }
+
+    @Test
+    public void testCollectorInvocations() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.collector.0.invocations";
+        final Long COLLECTOR_INVOCATIONS = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getCollectorInvocations(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(COLLECTOR_INVOCATIONS, returned);
+    }
+
+    @Test
+    public void testTotalGcGenerations() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.policy.generations";
+        final Long GC_GENERATIONS = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GC_GENERATIONS);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getTotalGcGenerations();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(GC_GENERATIONS, returned);
+    }
+
+    @Test
+    public void testGenerationName() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.name";
+        final String GENERATION_NAME = "Youth";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_NAME);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getGenerationName(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(GENERATION_NAME, returned);
+    }
+
+    @Test
+    public void testGenerationCapacity() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.capacity";
+        final Long GENERATION_CAPACITY = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_CAPACITY);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getGenerationCapacity(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(GENERATION_CAPACITY, returned);
+    }
+
+    @Test
+    public void testGenerationMaxCapacity() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.maxCapacity";
+        final Long GENERATION_MAX_CAPACITY = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_MAX_CAPACITY);
+
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getGenerationMaxCapacity(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(GENERATION_MAX_CAPACITY, returned);
+    }
+
+    @Test
+    public void testGenerationCollector() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.collector.0.name";
+        final String GENERATION_COLLECTOR = "generation collector";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_COLLECTOR);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getGenerationCollector(0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(GENERATION_COLLECTOR, returned);
+    }
+
+    @Test
+    public void testTotalSpaces() throws MonitorException {
+        final Long TOTAL_SPACES = 99l;
+        final LongMonitor monitor = mock(LongMonitor.class);
+        when(monitor.getValue()).thenReturn(TOTAL_SPACES);
+        MonitoredVm vm = mock(MonitoredVm.class);
+        when(vm.findByName("sun.gc.generation.0.spaces")).thenReturn(monitor);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getTotalSpaces(0);
+
+        verify(vm).findByName(eq("sun.gc.generation.0.spaces"));
+        assertEquals(TOTAL_SPACES, returned);
+    }
+
+
+    @Test
+    public void testSpaceName() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.space.0.name";
+        final String SPACE_NAME = "Hilbert";
+        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, SPACE_NAME);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        String returned = extractor.getSpaceName(0,0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(SPACE_NAME, returned);
+    }
+
+    @Test
+    public void testSpaceCapacity() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.space.0.capacity";
+        final Long SPACE_CAPACITY = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_CAPACITY);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getSpaceCapacity(0,0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(SPACE_CAPACITY, returned);
+    }
+
+    @Test
+    public void testSpaceMaxCapacity() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.space.0.maxCapacity";
+        final Long SPACE_MAX_CAPACITY = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_MAX_CAPACITY);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getSpaceMaxCapacity(0,0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(SPACE_MAX_CAPACITY, returned);
+    }
+
+    @Test
+    public void testSpaceUsed() throws MonitorException {
+        final String MONITOR_NAME = "sun.gc.generation.0.space.0.used";
+        final Long SPACE_USED = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_USED);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getSpaceUsed(0,0);
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(SPACE_USED, returned);
+    }
+
+    @Test
+    public void testLoadedClasses() throws MonitorException {
+        final String MONITOR_NAME = "java.cls.loadedClasses";
+        final Long LOADED_CLASSES = 99l;
+        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, LOADED_CLASSES);
+
+        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
+        Long returned = extractor.getLoadedClasses();
+
+        verify(vm).findByName(eq(MONITOR_NAME));
+        assertEquals(LOADED_CLASSES, returned);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.mockito.Matchers.any;
+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 java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+import org.mockito.Matchers;
+
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+
+import sun.jvmstat.monitor.HostIdentifier;
+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 {
+
+    @Test
+    public void testVmStatusChangedAddsVmClassListener() throws Exception {
+        VmStatusChangeEvent vmEvent = mock(VmStatusChangeEvent.class);
+        Set<Integer> startedVms = new HashSet<Integer>();
+        startedVms.add(123);
+        when(vmEvent.getStarted()).thenReturn(startedVms);
+
+        MonitoredVm vm = mock(MonitoredVm.class);
+        StringMonitor monitor = mock(StringMonitor.class);
+        when(monitor.stringValue()).thenReturn("test");
+        when(monitor.getValue()).thenReturn("test");
+        when(vm.findByName(anyString())).thenReturn(monitor);
+        MonitoredHost host = mock(MonitoredHost.class);
+        HostIdentifier hostId = mock(HostIdentifier.class);
+        when(host.getHostIdentifier()).thenReturn(hostId);
+        when(host.getMonitoredVm(any(VmIdentifier.class))).thenReturn(vm);
+        when(vmEvent.getMonitoredHost()).thenReturn(host);
+
+        VmClassStatDAO vmClassDAO = mock(VmClassStatDAO.class);
+        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
+        DAOFactory df = mock(DAOFactory.class);
+        when(df.getVmClassStatsDAO()).thenReturn(vmClassDAO);
+        when(df.getVmInfoDAO()).thenReturn(vmInfoDAO);
+        JvmStatHostListener l = new JvmStatHostListener(df, true);
+        SystemBackend backend = mock(SystemBackend.class);
+        when(backend.getObserveNewJvm()).thenReturn(true);
+
+        l.vmStatusChanged(vmEvent);
+
+        verify(vm).addVmListener(Matchers.isA(JvmStatVmClassListener.class));
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import sun.jvmstat.monitor.Monitor;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.event.VmEvent;
+
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.model.VmClassStat;
+
+public class JvmStatVmClassListenerTest {
+
+    private static final Integer VM_ID = 123;
+    private static final Long LOADED_CLASSES = 1234L;
+
+    @Test
+    public void testMonitorUpdatedClassStat() throws Exception {
+
+        VmClassStatDAO dao = mock(VmClassStatDAO.class);
+        DAOFactory df = mock(DAOFactory.class);
+        when(df.getVmClassStatsDAO()).thenReturn(dao);
+        JvmStatVmClassListener l = new JvmStatVmClassListener(df, VM_ID);
+        VmEvent vmEvent = mock(VmEvent.class);
+        MonitoredVm monitoredVm = mock(MonitoredVm.class);
+        Monitor m = mock(Monitor.class);
+        when(m.getValue()).thenReturn(LOADED_CLASSES);
+        when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m);
+        when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm);
+
+        l.monitorsUpdated(vmEvent);
+
+        ArgumentCaptor<VmClassStat> arg = ArgumentCaptor.forClass(VmClassStat.class);
+        verify(dao).putVmClassStat(arg.capture());
+        VmClassStat stat = arg.getValue();
+        assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+    }
+
+    @Test
+    public void testMonitorUpdatedClassStatTwice() throws Exception {
+
+        VmClassStatDAO dao = mock(VmClassStatDAO.class);
+        DAOFactory df = mock(DAOFactory.class);
+        when(df.getVmClassStatsDAO()).thenReturn(dao);
+        JvmStatVmClassListener l = new JvmStatVmClassListener(df, VM_ID);
+        VmEvent vmEvent = mock(VmEvent.class);
+        MonitoredVm monitoredVm = mock(MonitoredVm.class);
+        Monitor m = mock(Monitor.class);
+        when(m.getValue()).thenReturn(LOADED_CLASSES);
+        when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m);
+        when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm);
+
+        l.monitorsUpdated(vmEvent);
+        l.monitorsUpdated(vmEvent);
+
+        // This checks a bug where the Category threw an IllegalStateException because the DAO
+        // created a new one on each call, thus violating the unique guarantee of Category.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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 java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+public class LsbReleaseTest {
+
+    @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());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Constants;
+import com.redhat.thermostat.common.model.MemoryStat;
+
+public class MemoryStatBuilderTest {
+
+    @Test
+    public void testSimpleBuild() {
+        MemoryStat stat = new MemoryStatBuilder(new ProcDataSource()).build();
+        assertNotNull(stat);
+    }
+
+    @Test
+    public void testEmptyBuild() throws IOException {
+        String memory = "";
+        StringReader memoryReader = new StringReader(memory);
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getMemInfoReader()).thenReturn(memoryReader);
+
+        MemoryStat stat = new MemoryStatBuilder(dataSource).build();
+        assertNotNull(stat);
+        verify(dataSource).getMemInfoReader();
+    }
+
+    @Test
+    public void testBuild() throws IOException {
+        int i = 1;
+        final long TOTAL = i++;
+        final long FREE = i++;
+        final long BUFFERS = i++;
+        final long CACHED = i++;
+        final long COMMIT_LIMIT = i++;
+        final long SWAP_TOTAL = i++;
+        final long SWAP_FREE = i++;
+
+        String memory = "" +
+                "MemTotal: " + TOTAL + " kB\n" +
+                "MemFree:  " + FREE + " kB\n" +
+                "Buffers:" + BUFFERS + " kB\n" +
+                "Cached: " + CACHED + " kB\n" +
+                "CommitLimit: " + COMMIT_LIMIT + " kB\n" +
+                "SwapTotal: " + SWAP_TOTAL + " kB\n" +
+                "SwapFree: " + SWAP_FREE + " kB\n";
+
+        StringReader memoryReader = new StringReader(memory);
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getMemInfoReader()).thenReturn(memoryReader);
+
+        MemoryStat stat = new MemoryStatBuilder(dataSource).build();
+
+        assertEquals(BUFFERS * Constants.KILOBYTES_TO_BYTES, stat.getBuffers());
+        assertEquals(CACHED * Constants.KILOBYTES_TO_BYTES, stat.getCached());
+        assertEquals(COMMIT_LIMIT * Constants.KILOBYTES_TO_BYTES, stat.getCommitLimit());
+        assertEquals(FREE * Constants.KILOBYTES_TO_BYTES, stat.getFree());
+        assertEquals(SWAP_FREE * Constants.KILOBYTES_TO_BYTES, stat.getSwapFree());
+        assertEquals(SWAP_TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getSwapTotal());
+        assertEquals(TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getTotal());
+        assertTrue(stat.getTimeStamp() != 0 && stat.getTimeStamp() != Long.MIN_VALUE);
+        assertTrue(stat.getTimeStamp() <= System.currentTimeMillis());
+        verify(dataSource).getMemInfoReader();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+
+public class NetworkInfoBuilderTest {
+
+    @Test
+    public void testBuilder() {
+
+        List<NetworkInterfaceInfo> info = NetworkInfoBuilder.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}"));
+            }
+            // TODO check for sane ipv6 address
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcDataSourceTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.assertNotNull;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.agent.TestUtils;
+
+public class ProcDataSourceTest {
+
+    @Test
+    public void testGetCpuInfoReader() throws IOException {
+        Reader r = new ProcDataSource().getCpuInfoReader();
+        assertNotNull(r);
+    }
+
+    @Test
+    public void testGetCpuLoadReader() throws IOException {
+        Reader r = new ProcDataSource().getCpuLoadReader();
+        assertNotNull(r);
+    }
+
+    @Test
+    public void testGetMemInfoReader() throws IOException {
+        Reader r = new ProcDataSource().getMemInfoReader();
+        assertNotNull(r);
+    }
+
+    @Test
+    public void testGetStatReader() throws IOException {
+        int pid = TestUtils.getProcessId();
+        Reader r = new ProcDataSource().getStatReader(pid);
+        assertNotNull(r);
+    }
+
+
+    @Test
+    public void testGetEnvironReader() throws IOException {
+        int pid = TestUtils.getProcessId();
+        Reader r = new ProcDataSource().getEnvironReader(pid);
+        assertNotNull(r);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.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/agent/core/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.junit.Test;
+
+public class ProcessStatusInfoBuilderTest {
+
+    @Test
+    public void testSimpleProcessStatus() {
+        ProcDataSource dataSource = new ProcDataSource();
+        ProcessStatusInfo stat = new ProcessStatusInfoBuilder(dataSource).build(1);
+        assertNotNull(stat);
+    }
+
+    @Test
+    public void testKnownProcessStatus() throws IOException {
+        final int PID = 10363;
+        String PROCESS_NAME = "(bash)";
+        String STATE = "S";
+        String PPID = "1737";
+        String PROCESS_GROUP_ID = "10363";
+        String SESSION_ID = "10363";
+        String TTY_NUMBER = "34817";
+        String TTY_PROCESS_GROUP_ID = "11404";
+        String FLAGS_WORD = "4202496";
+        String MINOR_FAULTS = "8093";
+        String MINOR_FAULTS_CHILDREN = "607263";
+        String MAJOR_FAULTS = "1";
+        String MAJOR_FAULTS_CHILDREN = "251";
+        final long USER_TIME_TICKS = 21;
+        final long KERNEL_TIME_TICKS = 7;
+        final long USER_TIME_CHILDREN = 10;
+        String KERNEL_TIME_CHILDREN = "1000";
+        String PRIORITY = "20";
+        String statString = "" +
+                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
+                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
+                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
+                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
+                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
+                KERNEL_TIME_CHILDREN + " " + PRIORITY;
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
+        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource);
+        ProcessStatusInfo stat = builder.build(PID);
+
+        verify(dataSource).getStatReader(PID);
+        assertNotNull(stat);
+        assertEquals(PID, stat.getPid());
+        assertEquals(USER_TIME_TICKS, stat.getUserTime());
+        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
+    }
+
+    @Test
+    public void testBadProcessName() throws IOException {
+        final int PID = 10363;
+        String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)";
+        String STATE = "S";
+        String PPID = "1737";
+        String PROCESS_GROUP_ID = "10363";
+        String SESSION_ID = "10363";
+        String TTY_NUMBER = "34817";
+        String TTY_PROCESS_GROUP_ID = "11404";
+        String FLAGS_WORD = "4202496";
+        String MINOR_FAULTS = "8093";
+        String MINOR_FAULTS_CHILDREN = "607263";
+        String MAJOR_FAULTS = "1";
+        String MAJOR_FAULTS_CHILDREN = "251";
+        final long USER_TIME_TICKS = 21;
+        final long KERNEL_TIME_TICKS = 7;
+        final long USER_TIME_CHILDREN = 10;
+        String KERNEL_TIME_CHILDREN = "1000";
+        String PRIORITY = "20";
+        String statString = "" +
+                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
+                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
+                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
+                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
+                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
+                KERNEL_TIME_CHILDREN + " " + PRIORITY;
+
+        ProcDataSource dataSource = mock(ProcDataSource.class);
+        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
+        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource);
+        ProcessStatusInfo stat = builder.build(PID);
+
+        verify(dataSource).getStatReader(PID);
+        assertNotNull(stat);
+        assertEquals(PID, stat.getPid());
+        assertEquals(USER_TIME_TICKS, stat.getUserTime());
+        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.assertTrue;
+
+import org.junit.Test;
+
+public class SysConfTest {
+
+    @Test
+    public void test() {
+        long ticksPerSecond = SysConf.getClockTicksPerSecond();
+        assertTrue(ticksPerSecond >= 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class SystemBackendTest {
+
+    private SystemBackend b;
+
+    @Before
+    public void setUp() {
+        Storage s = mock(Storage.class);
+        CpuStatDAO cDAO = mock(CpuStatDAO.class);
+        HostInfoDAO hDAO = mock(HostInfoDAO.class);
+        MemoryStatDAO mDAO = mock(MemoryStatDAO.class);
+        VmCpuStatDAO vDAO = mock(VmCpuStatDAO.class);
+        NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class);
+        DAOFactory df = mock(DAOFactory.class);
+        when(df.getStorage()).thenReturn(s);
+        when(df.getCpuStatDAO()).thenReturn(cDAO);
+        when(df.getHostInfoDAO()).thenReturn(hDAO);
+        when(df.getMemoryStatDAO()).thenReturn(mDAO);
+        when(df.getVmCpuStatDAO()).thenReturn(vDAO);
+        when(df.getNetworkInterfaceInfoDAO()).thenReturn(nDAO);
+        b = new SystemBackend();
+        b.setDAOFactory(df);
+    }
+
+    @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 testCategoriesAreSane() {
+        Collection<Category> categories = b.getCategories();
+
+        assertTrue(categories.contains(CpuStatDAO.cpuStatCategory));
+        assertTrue(categories.contains(HostInfoDAO.hostInfoCategory));
+        assertTrue(categories.contains(MemoryStatDAO.memoryStatCategory));
+        assertTrue(categories.contains(NetworkInterfaceInfoDAO.networkInfoCategory));
+        assertTrue(categories.contains(VmClassStatDAO.vmClassStatsCategory));
+        assertTrue(categories.contains(VmCpuStatDAO.vmCpuStatCategory));
+        assertTrue(categories.contains(VmGcStatDAO.vmGcStatCategory));
+        assertTrue(categories.contains(VmInfoDAO.vmInfoCategory));
+        assertTrue(categories.contains(VmMemoryStatDAO.vmMemoryStatsCategory));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.Clock;
+import com.redhat.thermostat.common.model.VmCpuStat;
+
+public class VmCpuStatBuilderTest {
+
+    @Test
+    public void testBuilderKnowsNothing() {
+        Clock clock = mock(Clock.class);
+        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
+        int cpuCount = 0;
+        long ticksPerSecond = 0;
+        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
+
+        assertFalse(builder.knowsAbout(0));
+        assertFalse(builder.knowsAbout(1));
+        assertFalse(builder.knowsAbout(Integer.MIN_VALUE));
+        assertFalse(builder.knowsAbout(Integer.MAX_VALUE));
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBuilderThrowsOnBuildOfUnknownPid() {
+        Clock clock = mock(Clock.class);
+        int cpuCount = 0;
+        long ticksPerSecond = 0;
+        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
+        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
+        builder.build(0);
+    }
+
+    @Test
+    public void testBuildNullOnInsufficentInformation() {
+        int PID = 0;
+        int cpuCount = 0;
+        long ticksPerSecond = 0;
+        final long CLOCK1 = 10000;
+        final long CLOCK2 = 20000;
+        final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, 1, 2);
+        final ProcessStatusInfo laterInfo = null;
+
+        Clock clock = mock(Clock.class);
+        when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6));
+
+        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
+        when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null);
+
+        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
+
+        builder.learnAbout(PID);
+        assertEquals(null, builder.build(PID));
+    }
+
+    @Test
+    public void testSaneBuild() {
+        final int PID = 0;
+
+        final int CPU_COUNT = 3;
+
+        final long USER_INITIAL_TICKS = 1;
+        final long KERNEL_INITIAL_TICKS = 1;
+
+        final long USER_LATER_TICKS = 10;
+        final long KERNEL_LATER_TICKS = 10;
+
+        final long CLOCK1 = 10000;
+        final long CLOCK2 = 20000;
+
+        final long TICKS_PER_SECOND = 100;
+
+        final double CPU_LOAD_PERCENT =
+                100.0
+                * ((USER_LATER_TICKS + KERNEL_LATER_TICKS) - (USER_INITIAL_TICKS + KERNEL_INITIAL_TICKS))
+                / TICKS_PER_SECOND
+                / ((CLOCK2 - CLOCK1) * 1E-3 /* millis to seconds */)
+                / CPU_COUNT;
+
+        final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, USER_INITIAL_TICKS, KERNEL_INITIAL_TICKS);
+        final ProcessStatusInfo laterInfo = new ProcessStatusInfo(PID, USER_LATER_TICKS, KERNEL_LATER_TICKS);
+
+        Clock clock = mock(Clock.class);
+        when(clock.getRealTimeMillis()).thenReturn(CLOCK2);
+        when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6));
+
+        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
+        when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null);
+
+        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, CPU_COUNT, TICKS_PER_SECOND, statusBuilder);
+
+        builder.learnAbout(PID);
+        VmCpuStat stat = builder.build(PID);
+
+        assertNotNull(stat);
+        assertEquals(PID, stat.getVmId());
+        assertEquals(CLOCK2, stat.getTimeStamp());
+        assertEquals(CPU_LOAD_PERCENT, stat.getCpuLoad(), 0.0001);
+    }
+
+}
--- a/agent/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/agent/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -46,7 +46,7 @@
   </parent>
 
   <artifactId>thermostat-agent</artifactId>
-  <packaging>bundle</packaging>
+  <packaging>pom</packaging>
 
   <name>Thermostat Agent</name>
 
@@ -56,54 +56,11 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
-      <version>${project.version}</version>
-      <type>bundle</type>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.sun</groupId>
-      <artifactId>tools</artifactId>
-      <scope>system</scope>
-      <systemPath>${java.home}/../lib/tools.jar</systemPath>
-    </dependency>
   </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>1.4.0</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.agent.Activator</Bundle-Activator>
-            <Export-Package>
-              com.redhat.thermostat.agent,
-              com.redhat.thermostat.backend,
-            </Export-Package>
-            <Private-Package>
-              com.redhat.thermostat,
-              com.redhat.thermostat.agent.config,
-              com.redhat.thermostat.backend.sample,
-              com.redhat.thermostat.backend.system,
-            </Private-Package>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+  <modules>
+    <module>core</module>
+    <module>command</module>
+  </modules>
 
 </project>
--- a/agent/src/main/java/com/redhat/thermostat/agent/Activator.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import java.util.Arrays;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.common.cli.CommandRegistry;
-import com.redhat.thermostat.common.cli.CommandRegistryImpl;
-
-public class Activator implements BundleActivator {
-
-    private CommandRegistry reg;
-
-    @Override
-    public void start(BundleContext context) throws Exception {
-        reg = new CommandRegistryImpl(context);
-        reg.registerCommands(Arrays.asList(new AgentApplication()));
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        reg.unregisterCommands();
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/Agent.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import java.util.UUID;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
-import com.redhat.thermostat.agent.config.ConfigurationWatcher;
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.backend.BackendRegistry;
-import com.redhat.thermostat.common.LaunchException;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.storage.AgentInformation;
-import com.redhat.thermostat.common.storage.BackendInformation;
-import com.redhat.thermostat.common.storage.Storage;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * Represents the Agent running on a host.
- */
-public class Agent {
-
-    private static final Logger logger = LoggingUtils.getLogger(Agent.class);
-
-    private final UUID id;
-    private final BackendRegistry backendRegistry;
-    private final AgentStartupConfiguration config;
-
-    private AgentInformation agentInfo;
-    
-    private Storage storage;
-    private Thread configWatcherThread = null;
-
-    public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, DAOFactory daos) {
-        this(backendRegistry, UUID.randomUUID(), config, daos);
-    }
-
-    public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, DAOFactory daos) {
-        this.id = agentId;
-        this.backendRegistry = registry;
-        this.config = config;
-        this.storage = daos.getStorage();
-        this.storage.setAgentId(agentId);
-    }
-
-    private void startBackends() throws LaunchException {
-        for (Backend be : backendRegistry.getAll()) {
-            logger.fine("Attempting to start backend: " + be.getName());
-            if (!be.activate()) {
-                logger.warning("Issue while starting backend: " + be.getName());
-                // When encountering issues during startup, we should not attempt to continue activating.
-                stopBackends();
-                throw new LaunchException("Could not activate backend: " + be.getName());
-            }
-        }
-    }
-
-    private void stopBackends() {
-        for (Backend be : backendRegistry.getAll()) {
-            logger.fine("Attempting to stop backend: " +be.getName());
-            if (!be.deactivate()) {
-                // When encountering issues during shutdown, we should attempt to shut down remaining backends.
-                logger.warning("Issue while deactivating backend: " + be.getName());
-            }
-        }
-    }
-
-    public synchronized void start() throws LaunchException {
-        if (configWatcherThread == null) {
-            startBackends();
-            agentInfo = createAgentInformation();
-            storage.addAgentInformation(agentInfo);
-            configWatcherThread = new Thread(new ConfigurationWatcher(storage, backendRegistry), "Configuration Watcher");
-            configWatcherThread.start();
-        } else {
-            logger.warning("Attempt to start agent when already started.");
-        }
-    }
-
-    private AgentInformation createAgentInformation() {
-        AgentInformation agentInfo = new AgentInformation();
-        agentInfo.setStartTime(config.getStartTime());
-        for (Backend backend : backendRegistry.getAll()) {
-            BackendInformation backendInfo = new BackendInformation();
-            backendInfo.setName(backend.getName());
-            backendInfo.setDescription(backend.getDescription());
-            backendInfo.setObserveNewJvm(backend.getObserveNewJvm());
-            agentInfo.addBackend(backendInfo);
-        }
-        agentInfo.setAlive(true);
-        return agentInfo;
-    }
-
-    public synchronized void stop() {
-        if (configWatcherThread != null) {
-            configWatcherThread.interrupt(); // This thread checks for its own interrupted state and ends if interrupted.
-            while (configWatcherThread.isAlive()) {
-                try {
-                    configWatcherThread.join();
-                } catch (InterruptedException e) {
-                    logger.fine("Interrupted while waiting for ConfigurationWatcher to die.");
-                }
-            }
-            configWatcherThread = null;
-
-            stopBackends();
-            if (config.purge()) {
-                System.out.println("purging database");
-                logger.info("purging database");
-                storage.removeAgentInformation();
-                storage.purge();
-            } else {
-                agentInfo.setStopTime(System.currentTimeMillis());
-                agentInfo.setAlive(false);
-                storage.updateAgentInformation(agentInfo);
-            }
-            
-        } else {
-            logger.warning("Attempt to stop agent which is not active");
-        }
-    }
-
-    public UUID getId() {
-        return id;
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import java.util.Collection;
-import java.util.concurrent.CountDownLatch;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.agent.config.AgentConfigsUtils;
-import com.redhat.thermostat.agent.config.AgentOptionParser;
-import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
-import com.redhat.thermostat.backend.BackendLoadException;
-import com.redhat.thermostat.backend.BackendRegistry;
-import com.redhat.thermostat.common.Constants;
-import com.redhat.thermostat.common.LaunchException;
-import com.redhat.thermostat.common.ThreadPoolTimerFactory;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.cli.ArgumentSpec;
-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.config.InvalidConfigurationException;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.MongoDAOFactory;
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
-import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
-import com.redhat.thermostat.common.storage.MongoStorageProvider;
-import com.redhat.thermostat.common.storage.StorageProvider;
-import com.redhat.thermostat.common.tools.BasicCommand;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-import sun.misc.Signal;
-import sun.misc.SignalHandler;
-
-@SuppressWarnings("restriction")
-public final class AgentApplication extends BasicCommand {
-
-    private static final String NAME = "agent";
-
-    // TODO: Use LocaleResources for i18n-ized strings.
-    private static final String DESCRIPTION = "starts and stops the thermostat agent";
-
-    private static final String USAGE = DESCRIPTION;
-
-    private AgentStartupConfiguration configuration;
-    private AgentOptionParser parser;
-    
-    private void parseArguments(Arguments args) throws InvalidConfigurationException {
-        configuration = AgentConfigsUtils.createAgentConfigs();
-        parser = new AgentOptionParser(configuration, args);
-        parser.parse();
-    }
-
-    @Override
-    public AgentStartupConfiguration getConfiguration() {
-        return configuration;
-    }
-    
-    private void runAgent(CommandContext ctx) {
-        long startTime = System.currentTimeMillis();
-        configuration.setStartTime(startTime);
-        
-        if (configuration.isDebugConsole()) {
-            LoggingUtils.useDevelConsole();
-        }
-        final Logger logger = LoggingUtils.getLogger(AgentApplication.class);
-
-        StorageProvider connProv = new MongoStorageProvider(configuration);
-        DAOFactory daoFactory = new MongoDAOFactory(connProv);
-        ApplicationContext.getInstance().setDAOFactory(daoFactory);
-        TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
-        ApplicationContext.getInstance().setTimerFactory(timerFactory);
-
-        Connection connection = daoFactory.getConnection();
-        ConnectionListener connectionListener = new ConnectionListener() {
-            @Override
-            public void changed(ConnectionStatus newStatus) {
-                switch (newStatus) {
-                case DISCONNECTED:
-                    logger.warning("Unexpected disconnect event.");
-                    break;
-                case CONNECTING:
-                    logger.fine("Connecting to storage.");
-                    break;
-                case CONNECTED:
-                    logger.fine("Connected to storage.");
-                    break;
-                case FAILED_TO_CONNECT:
-                    logger.warning("Could not connect to storage.");
-                    System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
-                default:
-                    logger.warning("Unfamiliar ConnectionStatus value");
-                }
-            }
-        };
-
-        connection.addListener(connectionListener);
-        connection.connect();
-        logger.fine("Connecting to storage...");
-
-        BackendRegistry backendRegistry = null;
-        try {
-            backendRegistry = new BackendRegistry(configuration);
-        } catch (BackendLoadException ble) {
-            logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble);
-            System.exit(Constants.EXIT_BACKEND_LOAD_ERROR);
-        }
-
-        final Agent agent = new Agent(backendRegistry, configuration, daoFactory);
-        try {
-            logger.fine("Starting agent.");
-            agent.start();
-        } catch (LaunchException le) {
-            logger.log(Level.SEVERE,
-                    "Agent could not start, probably because a configured backend could not be activated.",
-                    le);
-            System.exit(Constants.EXIT_BACKEND_START_ERROR);
-        }
-        logger.fine("Agent started.");
-
-        ctx.getConsole().getOutput().println("Agent id: " + agent.getId());
-        ctx.getConsole().getOutput().println("agent started.");
-        logger.fine("Agent id: " + agent.getId());
-
-        final CountDownLatch shutdownLatch = new CountDownLatch(1);
-        Signal.handle(new Signal("INT"), new SignalHandler() {
-            public void handle(sun.misc.Signal sig) {
-                agent.stop();
-                logger.fine("Agent stopped.");       
-                shutdownLatch.countDown();
-            }
-        });
-        try {
-            shutdownLatch.await();
-            logger.fine("terimating agent cmd");
-        } catch (InterruptedException e) {
-            return;
-        }
-    }
-    
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        try {
-            parseArguments(ctx.getArguments());
-            if (!parser.isHelp()) {
-                runAgent(ctx);
-            }
-        } catch (InvalidConfigurationException ex) {
-            throw new CommandException(ex);
-        }
-    }
-
-    @Override
-    public void disable() {
-        /* NO-OP */
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public String getDescription() {
-        return DESCRIPTION;
-    }
-
-    @Override
-    public String getUsage() {
-        return USAGE;
-    }
-
-    @Override
-    public Collection<ArgumentSpec> getAcceptedArguments() {
-        return AgentOptionParser.getAcceptedArguments();
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/JvmStatusListener.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-public interface JvmStatusListener {
-
-    public void jvmStarted(int pid);
-
-    public void jvmStopped(int pid);
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/JvmStatusNotifier.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-public interface JvmStatusNotifier {
-
-    /**
-     * Request to be informed when JVM processes are started or stopped.
-     * 
-     * @param listener the receiver of future {@link JvmStatusListener.jvmStarted()}
-     * and {@link JvmStatusListener.jvmStopped()} calls
-     */
-    public void addJvmStatusListener(JvmStatusListener listener);
-
-    /**
-     * Request to no longer be informed when JVM processes are started or stopped.
-     * @param listener the {@link JvmStatusListener} to be unregistered.
-     */
-    public void removeJvmStatusListener(JvmStatusListener listener);
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-import com.redhat.thermostat.common.config.ConfigUtils;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-public class AgentConfigsUtils {
-
-    public static AgentStartupConfiguration createAgentConfigs() throws InvalidConfigurationException {
-        
-        AgentStartupConfiguration config = new AgentStartupConfiguration();
-        
-        File propertyFile = ConfigUtils.getAgentConfigurationFile();
-        readAndSetProperties(propertyFile, config);
-        
-        return config;
-    }
-    
-    private static void readAndSetProperties(File propertyFile, AgentStartupConfiguration configuration)
-            throws InvalidConfigurationException
-    {
-        Properties properties = new Properties();
-        try {
-            properties.load(new FileInputStream(propertyFile));
-            
-        } catch (IOException e) {
-            throw new InvalidConfigurationException(e);
-        }
-        
-        if (properties.containsKey(AgentProperties.BACKENDS.name())) {
-            // this is a command separated list of backends
-            String backends = properties.getProperty(AgentProperties.BACKENDS.name());
-            configuration.parseBackends(backends.split(","));
-            
-        } else {
-            throw new InvalidConfigurationException(AgentProperties.BACKENDS + " property missing");
-        }
-        
-        if (properties.containsKey(AgentProperties.DB_URL.name())) {
-            String db = properties.getProperty(AgentProperties.DB_URL.name());
-            configuration.setDatabaseURL(db);
-        }
-        
-        configuration.setPurge(true);
-        if (properties.containsKey(AgentProperties.SAVE_ON_EXIT.name())) {
-            String purge = (String) properties.get(AgentProperties.SAVE_ON_EXIT.name());
-            configuration.setPurge(!Boolean.parseBoolean(purge));
-        }
-    }
-    
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import com.redhat.thermostat.common.cli.ArgumentSpec;
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.SimpleArgumentSpec;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-import com.redhat.thermostat.common.config.ThermostatOptionParser;
-
-public class AgentOptionParser implements ThermostatOptionParser {
-
-    private AgentStartupConfiguration configuration;
-    private Arguments args;
-    
-    private boolean isHelp;
-    
-    public AgentOptionParser(AgentStartupConfiguration configuration, Arguments args) {
-        this.configuration = configuration;
-        this.args = args;
-        isHelp = false;
-    }
-    
-    @Override
-    public void parse() throws InvalidConfigurationException {
-
-        if (args.hasArgument(Args.SAVE_ON_EXIT.option)) {
-            configuration.setPurge(false);
-        }
-
-        configuration.setDebugConsole(args.hasArgument(Args.DEBUG.option));
-        
-        if (args.hasArgument(Args.DB.option)) {
-            String url = args.getArgument(Args.DB.option);
-            configuration.setDatabaseURL(url);
-        } else {
-            if (configuration.getDBConnectionString() == null) {
-                System.err.println("database url not specified... must be " +
-                                   "either set in config or passed on " +
-                                   "the command line");
-                isHelp = true;
-            }
-        }
-    }
-    
-    public boolean isHelp() {
-        return isHelp;
-    }
-    
-    private static enum Args {
-        
-        // TODO: localize
-        SAVE_ON_EXIT("saveOnExit", "save the data on exit"),
-        DB("dbUrl", "connect to the given url"),
-        DEBUG("debug", "launch with debug console enabled"),
-        HELP("help", "print this help and exit");
-        
-        private String option;
-        private String description;
-        
-        Args(String option, String description) {
-            this.option = option;
-            this.description = description;
-        }
-    }
-
-    public static Collection<ArgumentSpec> getAcceptedArguments() {
-        ArgumentSpec saveOnExit = new SimpleArgumentSpec(Args.SAVE_ON_EXIT.option, "s", Args.SAVE_ON_EXIT.description, false, false);
-        ArgumentSpec db = new SimpleArgumentSpec(Args.DB.option, "d",  Args.DB.description, true, true);
-        ArgumentSpec debug = new SimpleArgumentSpec(Args.DEBUG.option, Args.DEBUG.description);
-        return Arrays.asList(saveOnExit, db, debug);
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-public enum AgentProperties {
-
-    // backend list, comma separated
-    BACKENDS,
-    DEBUG_CONSOLE,
-    DB_URL,
-    SAVE_ON_EXIT
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-import com.redhat.thermostat.backend.BackendID;
-import com.redhat.thermostat.backend.BackendsProperties;
-import com.redhat.thermostat.common.config.ConfigUtils;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-public class AgentStartupConfiguration implements StartupConfiguration {
-
-    private List<BackendID> backends;
-    
-    private boolean debugConsole;
-    private boolean purge;
-    
-    private String url;
-    
-    private long startTime;
-    
-    AgentStartupConfiguration() {
-        this.backends = new ArrayList<>();
-    }
-    
-    @Override
-    public String getDBConnectionString() {
-        return url;
-    }
-
-    void parseBackends(String[] backendsList) throws InvalidConfigurationException {
-        backends.clear();
-        
-        for (String simpleName : backendsList) {
-            String backendName = simpleName.trim();
-            
-            // a file must exist, at least with the class name
-            File backendSettings = ConfigUtils.getBackendPropertyFile(backendName);
-            if (!backendSettings.exists())
-                throw new InvalidConfigurationException("backends configuration " +
-                                                        "directory doesn't exist: " +
-                                                        backendSettings);
-            Properties backendProps = new Properties();
-            try {
-                backendProps.load(new FileInputStream(backendSettings));
-                
-            } catch (IOException e) {
-                throw new InvalidConfigurationException(e);
-            }
-            
-            String backendClass = backendProps.getProperty(BackendsProperties.BACKEND_CLASS.name());
-            if (backendClass == null) {
-                throw new InvalidConfigurationException("Class name not found for backend: " +
-                                                        backendName);
-            }
-            
-            BackendID backend = new BackendID(backendName, backendClass);
-            backends.add(backend);
-        }
-    }
-    
-    public List<BackendID> getBackends() {
-        return backends;
-    }
-
-    void setDebugConsole(boolean debugConsole) {
-        this.debugConsole = debugConsole;
-    }
-    
-    public boolean isDebugConsole() {
-        return debugConsole;
-    }
-
-    public void setDatabaseURL(String url) {
-        this.url = url;
-    }
-    
-    // TODO: that should be a friend, we only want the Service to set this value
-    public void setStartTime(long startTime) {
-        this.startTime = startTime;
-    }
-    
-    public long getStartTime() {
-        return startTime;
-    }
-
-    void setPurge(boolean purge) {
-        this.purge = purge;
-    }
-    
-    public boolean purge() {
-        return purge;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/ConfigurationWatcher.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.backend.BackendRegistry;
-import com.redhat.thermostat.common.storage.Storage;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class ConfigurationWatcher implements Runnable {
-
-    private static final Logger logger = LoggingUtils.getLogger(ConfigurationWatcher.class);
-
-    private Storage storage;
-    private BackendRegistry backends;
-
-    public ConfigurationWatcher(Storage storage, BackendRegistry backends) {
-        this.storage = storage;
-        this.backends = backends;
-    }
-
-    @Override
-    public void run() {
-        logger.fine("Watching for configuration changes.");
-        while (!Thread.interrupted()) {
-            checkConfigUpdates();
-        }
-        logger.fine("No longer watching for configuration changes.");
-    }
-
-    // TODO It would be best to develop this algorithm when we have a client that can initiate changes, so that it can be tested.
-    private void checkConfigUpdates() {
-        try { // THIS IS ONLY TEMPORARY.  Until we do implement this algorithm, we don't want this thread busy hogging CPU.
-            Thread.sleep(2000);
-        } catch (InterruptedException ignore) {
-            Thread.currentThread().interrupt();
-        }
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/Backend.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.redhat.thermostat.common.LaunchException;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Storage;
-
-/**
- * Represents a monitoring back-end. All the {@link Backend}s should be
- * registered with the {@link BackendRegistry}.
- */
-public abstract class Backend {
-
-    private boolean initialConfigurationComplete = false;
-    protected DAOFactory df = null;
-    private Storage storage = null;
-    private boolean observeNewJvm = attachToNewProcessByDefault();
-
-    private String version;
-    private String vendor;
-    private String description;
-    
-    private BackendID id;
-
-    /**
-     * 
-     * @param configMap a map containing the settings that this backend has been configured with.
-     * @throws LaunchException if map contains values that this backend does not accept.
-     */
-    protected final void setInitialConfiguration(Map<String, String> configMap) throws BackendLoadException {
-        if (initialConfigurationComplete) {
-            throw new BackendLoadException("A backend may only receive initial configuration once.");
-        }
-        for (Entry<String, String> e : configMap.entrySet()) {
-            String key = e.getKey();
-            String value = e.getValue();
-            try {
-                setConfigurationValue(key, value);
-            } catch (IllegalArgumentException iae) {
-                throw new BackendLoadException("Attempt to set invalid backend configuration for " + getName()
-                        + " backend.  Key: " + key + "   Value: " + value, iae);
-            }
-        }
-        initialConfigurationComplete = true;
-    }
-
-    public final void setDAOFactory(DAOFactory df) {
-        this.df = df;
-        this.storage = df.getStorage();
-        for (Category cat : getCategories()) {
-            storage.registerCategory(cat);
-        }
-        setDAOFactoryAction();
-    }
-
-    protected abstract void setDAOFactoryAction();
-
-    protected abstract Collection<Category> getCategories();
-
-    /**
-     * Set the named configuration to the given value.
-     * The basic special properties {@code name}, {@code version} and
-     * {@code description} are parsed here.
-     * 
-     * <br /><br />
-     * 
-     * Subclasses can just override the
-     * {@link #setConfigurationValueImpl(String, String)}
-     * method if they are not interested in parsing and setting those
-     * properties directly.
-     * 
-     * @param name
-     * @param value
-     * @throws IllegalArgumentException if either the key does not refer to a valid configuration option
-     *                                  for this backend or the value is not valid for the key
-     */
-    protected void setConfigurationValue(String name, String value) {
-        
-        if (name.equals(BackendsProperties.DESCRIPTION.name())) {
-            this.description = value;
-        } else if (name.equals(BackendsProperties.VERSION.name())) {
-            this.version = value;
-        } else if (name.equals(BackendsProperties.VENDOR.name())) {
-            this.vendor = value;
-        } else {
-            setConfigurationValueImpl(name, value);
-        }
-    }
-    
-    /**
-     * Set the named configuration to the given value.
-     * By default, does nothing.
-     */
-    protected void setConfigurationValueImpl(String name, String value) {}
-    
-    /**
-     * @return the name of the {@link Backend}
-     */
-    public String getName() {
-        return id.getSimpleName();
-    }
-
-    /**
-     * @returns the description of the {@link Backend}
-     */
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * @return the vendor of the {@link Backend}
-     */
-    public String getVendor() {
-        return vendor;
-    }
-
-    /** 
-     * @return the version of the {@link Backend}
-     */
-    public String getVersion() {
-        return version;
-    }
-
-    /** Get a map containing the current settings of this backend.
-     * Implementors of this abstract class which have some settings that
-     * are be configurable by the client must override this method
-     * to provide an appropriate map.
-     * 
-     * @return a map containing the settings of this backend
-     */
-    public Map<String, String> getConfigurationMap() {
-        return new HashMap<String, String>();
-    }
-
-    /**
-     * 
-     * @param key The constant key that corresponds to the desired configuration value
-     * @return The current value of the configuration value corresponding to the key given.
-     * @throws IllegalArgumentException if the key does not refer to a valid configuration option for
-     *                                  this backend
-     */
-    public abstract String getConfigurationValue(String key);
-
-    /**
-     * Activate the {@link Backend}.  Based on the current configuration,
-     * begin pushing data to the {@link Storage} layer.  If the {@link Backend} is
-     * already active, this method should have no effect
-     *
-     * @return true on success, false if there was an error
-     */
-    public abstract boolean activate();
-
-    /**
-     * Deactivate the {@link Backend}. The backend should release any
-     * resources that were obtained as a direct result of a call to
-     * {@link #activate()}.  If the {@link Backend} is not active, this
-     * method should have no effect
-     *
-     * @return true on success
-     */
-    public abstract boolean deactivate();
-
-    /**
-     * @return a boolean indicating whether the backend is currently active on this host
-     */
-    public abstract boolean isActive();
-
-    /**
-     * A {@link Backend} may be configured to automatically begin collecting from new Java
-     * processes.  This method determines whether this will be the case when the backend
-     * is initially started.
-     * 
-     * @return true if the initial backend behaviour is to attach to new java processes, false otherwise.
-     */
-    public abstract boolean attachToNewProcessByDefault();
-
-    /**
-     * Indicate whether this backend will attach to new java processes.
-     * 
-     * @return true if this backend will attach to new java processes, false otherwise.
-     */
-    public boolean getObserveNewJvm() {
-        return observeNewJvm;
-    }
-
-    /**
-     * Set whether this backend will attach to new java processes.
-     * 
-     * @param newValue
-     */
-    public void setObserveNewJvm(boolean newValue) {
-        observeNewJvm = newValue;
-    }
-
-    void setID(BackendID backendID) {
-        this.id = backendID;
-    }
-    
-    public BackendID getID() {
-        return id;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendConfigurationLoader.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-
-import com.redhat.thermostat.common.config.ConfigUtils;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-class BackendConfigurationLoader {
-
-    public Map<String, String> retrieveBackendConfigs(String name) throws InvalidConfigurationException {
-        
-        // reads the backend
-        File backend = new File(ConfigUtils.getBackendsBaseDirectory(), name);
-        backend = new File(backend, BackendsProperties.PROPERTY_FILE);
-        if (!backend.isFile() || !backend.canRead()) {
-            throw new InvalidConfigurationException("invalid backend configuration file: " + backend);
-        }
-        
-        Properties props = new Properties();
-        try {
-            props.load(new FileInputStream(backend));
-        } catch (IOException e) {
-            throw new InvalidConfigurationException("invalid backend configuration file", e);
-        }
-        
-        return toMap(props);
-    }
-
-    private static Map<String, String> toMap(Properties props) {
-
-        Map<String, String> configMap = new HashMap<>();
-        for (Entry<Object, Object> e : props.entrySet()) {
-            String key = (String) e.getKey();
-            String value = (String) e.getValue();
-            
-            configMap.put(key, value);
-        }
-        return configMap;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendID.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public class BackendID {
-
-    private String simpleName;
-    private String className;
-    
-    public BackendID(String simpleName, String className) {
-        this.simpleName = simpleName;
-        this.className = className;
-    }
-    
-    public String getSimpleName() {
-        return simpleName;
-    }
-    
-    public String getClassName() {
-        return className;
-    }
-    
-    @Override
-    public String toString() {
-        return simpleName + " = " + className;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendLoadException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public class BackendLoadException extends Exception {
-
-    private static final long serialVersionUID = 4057881401012295723L;
-
-    public BackendLoadException(String message) {
-        super(message);
-    }
-
-    public BackendLoadException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.lang.reflect.Constructor;
-import java.util.Collection;
-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.config.AgentStartupConfiguration;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * A registry for {@link Backend}s. Each {@link Backend} should call
- * {@link #register(Backend)} to register itself.
- */
-public class BackendRegistry {
-
-    private static final Logger logger = LoggingUtils.getLogger(BackendRegistry.class);
-
-    private final Map<String, Backend> registeredBackends;
-
-    public BackendRegistry(AgentStartupConfiguration config) throws BackendLoadException {
-        this(config, new BackendConfigurationLoader());
-    }
-
-    public BackendRegistry(AgentStartupConfiguration config, BackendConfigurationLoader backendConfigLoader) throws BackendLoadException {
-
-        registeredBackends = new HashMap<String, Backend>();
-        
-        List<BackendID> backends = config.getBackends();
-
-        DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
-        
-        /*
-         * Configure the dynamic/custom backends
-         */
-        for (BackendID backendID : backends) {
-            logger.log(Level.FINE, "Initializing backend: \"" + backendID.getClassName() + "\"");
-            Backend backend = null;
-            try {
-                Class<? > c = Class.forName(backendID.getClassName());
-                Class<? extends Backend> narrowed = c.asSubclass(Backend.class);
-                Constructor<? extends Backend> backendConstructor = narrowed.getConstructor();
-                backend = backendConstructor.newInstance();
-
-                backend.setDAOFactory(df);
-                backend.setID(backendID);
-                
-                backend.setInitialConfiguration(backendConfigLoader.retrieveBackendConfigs(backend.getName()));
-            } catch (Exception e) {
-                throw new BackendLoadException("Could not instantiate configured backend class: " + backendID.getClassName(), e);
-            }
-            register(backend);
-        }
-    }
-
-    private synchronized void register(Backend backend) throws BackendLoadException {
-        if (registeredBackends.containsKey(backend.getName())) {
-            throw new BackendLoadException("Attempt to register two backends with the same name: " + backend.getName());
-        }
-        registeredBackends.put(backend.getName(), backend);
-    }
-
-    private synchronized void unregister(Backend backend) {
-        registeredBackends.remove(backend.getName());
-    }
-
-    public synchronized Collection<Backend> getAll() {
-        return registeredBackends.values();
-    }
-
-    public synchronized Backend getByName(String name) {
-        for (Backend backend : registeredBackends.values()) {
-            if (backend.getName().equals((name))) {
-                return backend;
-            }
-        }
-        return null;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendsProperties.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-/**
- * Properties that any Backend needs to have, at minimum.
- */
-public enum BackendsProperties {
-    
-    DESCRIPTION,
-    VENDOR,
-    VERSION,
-    BACKEND_CLASS;
-    
-    public static final String PROPERTY_FILE = "backend.properties";
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.sample;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * Just an example backend implementation.  This is really just to test the loading and configuration mechanisms
- */
-public class SampleBackend extends Backend {
-    private final String NAME = "sample-backend";
-    private final String DESCRIPTION = "A backend which does nothing at all.";
-    private final String VENDOR = "Nobody";
-    private final String VERSION = "0.1";
-    private boolean currentlyActive = false;
-
-    private Logger logger = LoggingUtils.getLogger(SampleBackend.class);
-
-    private final Map<String, String> config = new HashMap<>();
-
-    public SampleBackend() {
-        super();
-    }
-
-    @Override
-    protected void setConfigurationValue(String name, String value) {
-        logger.log(Level.FINE, "Setting configuration value for backend: " + this.NAME);
-        logger.log(Level.FINE, "key: " + name + "    value: " + value);
-        config.put(name, value);
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public String getDescription() {
-        return DESCRIPTION;
-    }
-
-    @Override
-    public String getVendor() {
-        return VENDOR;
-    }
-
-    @Override
-    public String getVersion() {
-        return VERSION;
-    }
-
-    @Override
-    public Map<String, String> getConfigurationMap() {
-        return Collections.unmodifiableMap(config);
-    }
-
-    @Override
-    public String getConfigurationValue(String key) {
-        return config.get(key);
-    }
-
-    @Override
-    public boolean activate() {
-        currentlyActive = true;
-        return true;
-    }
-
-    @Override
-    public boolean deactivate() {
-        currentlyActive = false;
-        return true;
-    }
-
-    @Override
-    public boolean isActive() {
-        return currentlyActive;
-    }
-
-    @Override
-    protected Collection<Category> getCategories() {
-        return new HashSet<Category>();
-    }
-
-    @Override
-    public boolean attachToNewProcessByDefault() {
-        return false;
-    }
-
-    @Override
-    protected void setDAOFactoryAction() {
-        // TODO Auto-generated method stub
-        
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class CpuStatBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class);
-
-    private final ProcDataSource dataSource;
-
-    public CpuStatBuilder(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public CpuStat build() {
-        try (BufferedReader reader = new BufferedReader(dataSource.getCpuLoadReader())) {
-            return build(reader);
-        } catch (IOException e) {
-            logger.log(Level.WARNING, "unable to read data source for cpu info");
-        }
-        return new CpuStat(System.currentTimeMillis(),
-                CpuStat.INVALID_LOAD, CpuStat.INVALID_LOAD, CpuStat.INVALID_LOAD);
-    }
-
-    private CpuStat build(BufferedReader reader) throws IOException {
-        long timestamp = System.currentTimeMillis();
-        double load5 = CpuStat.INVALID_LOAD;
-        double load10 = CpuStat.INVALID_LOAD;
-        double load15 = CpuStat.INVALID_LOAD;
-        String[] loadAvgParts = reader.readLine().split(" +");
-        if (loadAvgParts.length >= 3) {
-            try {
-                load5 = Double.valueOf(loadAvgParts[0]);
-                load10 = Double.valueOf(loadAvgParts[1]);
-                load15 = Double.valueOf(loadAvgParts[2]);
-            } catch (NumberFormatException nfe) {
-                logger.log(Level.WARNING, "error extracting load");
-            }
-        }
-        return new CpuStat(timestamp, load5, load10, load15);
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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() {
-        try {
-            return new EtcOsRelease().getDistributionInformation();
-        } catch (IOException e) {
-            logger.log(Level.WARNING, "unable to use os-release", e);
-        }
-        try {
-            return new LsbRelease().getDistributionInformation();
-        } catch (IOException e) {
-            logger.log(Level.WARNING, "unable to use lsb_release", e);
-        }
-        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;
-    }
-
-}
\ No newline at end of file
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/DistributionInformationSource.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/agent/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.FileReader;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class EtcOsRelease implements DistributionInformationSource {
-
-    private static final Logger logger = LoggingUtils.getLogger(EtcOsRelease.class);
-
-    private static final String OS_RELEASE = "/etc/os-release";
-
-    @Override
-    public DistributionInformation getDistributionInformation() throws IOException {
-        return getFromOsRelease();
-    }
-
-    public DistributionInformation getFromOsRelease() throws IOException {
-        return getFromOsRelease(OS_RELEASE);
-    }
-
-    public DistributionInformation getFromOsRelease(String releaseFile) throws IOException {
-        BufferedReader reader = null;
-        try {
-            reader = new BufferedReader(new FileReader(releaseFile));
-            return getFromOsRelease(reader);
-        } finally {
-            try {
-                if (reader != null) {
-                    reader.close();
-                }
-            } catch (IOException e) {
-                logger.log(Level.WARNING, "unable to close input stream", e);
-            }
-        }
-    }
-
-    public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException {
-        String name = "Linux";
-        String version = DistributionInformation.UNKNOWN_VERSION;
-        String line = null;
-        while ((line = reader.readLine()) != null) {
-            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/agent/src/main/java/com/redhat/thermostat/backend/system/HostInfoBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.common.Constants;
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class HostInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(HostInfoBuilder.class);
-
-    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 long totalMemory;
-
-        public HostMemoryInfo(long totalMemory) {
-            this.totalMemory = totalMemory;
-        }
-    }
-
-    private final ProcDataSource dataSource;
-
-    public HostInfoBuilder(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public HostInfo build() {
-        String hostname = getHostName();
-        HostCpuInfo cpuInfo = getCpuInfo();
-        HostMemoryInfo memoryInfo = getMemoryInfo();
-        HostOsInfo osInfo = getOsInfo();
-
-        return new HostInfo(hostname, osInfo.distribution, osInfo.kernel, cpuInfo.model, cpuInfo.count, memoryInfo.totalMemory);
-    }
-
-    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() {
-        long totalMemory = -1;
-        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 = data * Constants.KILOBYTES_TO_BYTES;
-            }
-        } catch (IOException ioe) {
-            logger.log(Level.WARNING, "unable to read memory info");
-        }
-
-        logger.log(Level.FINEST, "totalMemory: " + totalMemory + " bytes");
-        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() {
-        try {
-            InetAddress localAddress = null;
-            localAddress = InetAddress.getLocalHost();
-            return getHostName(localAddress);
-        } catch (UnknownHostException uhe) {
-            logger.log(Level.WARNING, "unable to get hostname", uhe);
-        }
-
-        return Constants.AGENT_LOCAL_HOSTNAME;
-    }
-
-    String getHostName(InetAddress localAddress) {
-        String hostname = localAddress.getCanonicalHostName();
-        logger.log(Level.FINEST, "hostname: " + hostname);
-        return hostname;
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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 com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-
-import sun.jvmstat.monitor.Monitor;
-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);
-    }
-
-    public long getTotalCollectors() throws MonitorException {
-        return (Long) vm.findByName("sun.gc.policy.collectors").getValue();
-    }
-
-    public String getCollectorName(long collector) throws MonitorException {
-        return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue();
-    }
-
-    public long getCollectorTime(long collector) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue();
-    }
-
-    public long getCollectorInvocations(long collector) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue();
-    }
-
-    public long getTotalGcGenerations() throws MonitorException {
-        return (Long) vm.findByName("sun.gc.policy.generations").getValue();
-    }
-
-    public String getGenerationName(long generation) throws MonitorException {
-        return (String) vm.findByName("sun.gc.generation." + generation + ".name").getValue();
-    }
-
-    public long getGenerationCapacity(long generation) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".capacity").getValue();
-    }
-
-    public long getGenerationMaxCapacity(long generation) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".maxCapacity").getValue();
-    }
-
-    public String getGenerationCollector(long generation) throws MonitorException {
-        // this is just re-implementing getCollectorName()
-        // TODO check generation number and collector number are always associated
-        Monitor m = vm.findByName("sun.gc.collector." + generation + ".name");
-        if (m == null) {
-            return Generation.COLLECTOR_NONE;
-        }
-        return (String) m.getValue();
-    }
-
-    public long getTotalSpaces(long generation) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".spaces").getValue();
-    }
-
-    public String getSpaceName(long generation, long space) throws MonitorException {
-        return (String) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".name").getValue();
-    }
-
-    public long getSpaceCapacity(long generation, long space) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".capacity").getValue();
-    }
-
-    public long getSpaceMaxCapacity(long generation, long space) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".maxCapacity").getValue();
-    }
-
-    public long getSpaceUsed(long generation, long space) throws MonitorException {
-        return (Long) vm.findByName("sun.gc.generation." + generation + ".space." + space + ".used").getValue();
-    }
-
-    public long getLoadedClasses() throws MonitorException {
-        return (Long) vm.findByName("java.cls.loadedClasses").getValue();
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-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.JvmStatusListener;
-import com.redhat.thermostat.agent.JvmStatusNotifier;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class JvmStatHostListener implements HostListener, JvmStatusNotifier {
-
-    private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class);
-
-    private boolean attachNew;
-    private final DAOFactory df;
-    private final VmInfoDAO vmInfoDAO;
-
-    private Map<Integer, MonitoredVm> monitoredVms  = new HashMap<>();
-
-    private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>();
-
-    JvmStatHostListener(DAOFactory df, boolean attachNew) {
-        this.df = df;
-        this.vmInfoDAO = df.getVmInfoDAO();
-        this.attachNew = attachNew;
-    }
-
-    @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 vmId, MonitoredHost host)
-            throws MonitorException, URISyntaxException {
-        MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve(
-                new VmIdentifier(vmId.toString())));
-        if (vm != null) {
-            VmInfo info = null;
-            try {
-                long startTime = System.currentTimeMillis();
-                long stopTime = Long.MIN_VALUE;
-                JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-                Map<String, String> properties = new HashMap<String, String>();
-                ProcDataSource dataSource = new ProcDataSource();
-                Map<String, String> environment = new ProcessEnvironmentBuilder(dataSource).build(vmId);
-                // TODO actually figure out the loaded libraries.
-                List<String> loadedNativeLibraries = new ArrayList<String>();
-                info = new VmInfo(vmId, startTime, stopTime,
-                        extractor.getJavaVersion(), extractor.getJavaHome(),
-                        extractor.getMainClass(), extractor.getCommandLine(),
-                        extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(),
-                        properties, environment, loadedNativeLibraries);
-                vmInfoDAO.putVmInfo(info);
-                logger.finer("Sent VM_STARTED messsage");
-            } catch (MonitorException me) {
-                logger.log(Level.WARNING, "error getting vm info for " + vmId, me);
-            }
-
-            if (attachNew) {
-                vm.addVmListener(new JvmStatVmListener(df, vmId));
-                vm.addVmListener(new JvmStatVmClassListener(df, vmId));
-            } else {
-                logger.log(Level.FINE, "skipping new vm " + vmId);
-            }
-            for (JvmStatusListener statusListener : statusListeners) {
-                statusListener.jvmStarted(vmId);
-            }
-
-            monitoredVms.put(vmId, vm);
-        }
-    }
-
-    private void sendStoppedVM(Integer vmId, MonitoredHost host)
-            throws URISyntaxException, MonitorException {
-        VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(
-                new VmIdentifier(vmId.toString()));
-        if (resolvedVmID != null) {
-            long stopTime = System.currentTimeMillis();
-            for (JvmStatusListener statusListener : statusListeners) {
-                statusListener.jvmStopped(vmId);
-            }
-            vmInfoDAO.putVmStoppedTime(vmId, stopTime);
-
-            monitoredVms.remove(vmId).detach();
-        }
-    }
-
-    @Override
-    public void addJvmStatusListener(JvmStatusListener listener) {
-        statusListeners.add(listener);
-    }
-
-    @Override
-    public void removeJvmStatusListener(JvmStatusListener listener) {
-        statusListeners.remove(listener);
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Level;
-import java.util.logging.Logger;
-
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.event.MonitorStatusChangeEvent;
-import sun.jvmstat.monitor.event.VmEvent;
-import sun.jvmstat.monitor.event.VmListener;
-
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-class JvmStatVmClassListener implements VmListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(JvmStatVmClassListener.class);
-
-    private VmClassStatDAO dao;
-    private int vmId;
-
-    JvmStatVmClassListener(DAOFactory df, int vmId) {
-        this.dao = df.getVmClassStatsDAO();
-        this.vmId = vmId;
-    }
-
-    @Override
-    public void disconnected(VmEvent vmEvent) {
-        /* nothing to do here */
-    }
-
-    @Override
-    public void monitorStatusChanged(MonitorStatusChangeEvent vmEvent) {
-        /* nothing to do here */
-    }
-
-    @Override
-    public void monitorsUpdated(VmEvent vmEvent) {
-        MonitoredVm vm = vmEvent.getMonitoredVm();
-        try {
-            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-            long loadedClasses = extractor.getLoadedClasses();
-            long timestamp = System.currentTimeMillis();
-            VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses);
-            dao.putVmClassStat(stat);
-        } catch (MonitorException e) {
-            logger.log(Level.WARNING, "error gathering class info for vm " + vmId, e);
-        }
-
-
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.event.MonitorStatusChangeEvent;
-import sun.jvmstat.monitor.event.VmEvent;
-import sun.jvmstat.monitor.event.VmListener;
-
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class JvmStatVmListener implements VmListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class);
-
-    private final int vmId;
-    private final VmGcStatDAO gcDAO;
-    private final VmMemoryStatDAO memDAO;
-
-    public JvmStatVmListener(DAOFactory df, int vmId) {
-        gcDAO = df.getVmGcStatDAO();
-        memDAO = df.getVmMemoryStatDAO();
-        this.vmId = vmId;
-    }
-
-    @Override
-    public void disconnected(VmEvent event) {
-        /* nothing to do here */
-    }
-
-    @Override
-    public void monitorStatusChanged(MonitorStatusChangeEvent event) {
-        /* nothing to do here */
-    }
-
-    @Override
-    public void monitorsUpdated(VmEvent event) {
-        MonitoredVm vm = event.getMonitoredVm();
-        if (vm == null) {
-            throw new NullPointerException();
-        }
-        recordMemoryStat(vm);
-        recordGcStat(vm);
-    }
-
-    private void recordGcStat(MonitoredVm vm) {
-        try {
-            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-            long collectors = extractor.getTotalCollectors();
-            for (int i = 0; i < collectors; i++) {
-                long timestamp = System.currentTimeMillis();
-                VmGcStat stat = new VmGcStat(vmId, timestamp,
-                        extractor.getCollectorName(i),
-                        extractor.getCollectorInvocations(i),
-                        extractor.getCollectorTime(i));
-                gcDAO.putVmGcStat(stat);
-            }
-        } catch (MonitorException e) {
-            logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e);
-        }
-
-    }
-
-    private void recordMemoryStat(MonitoredVm vm) {
-        try {
-            long timestamp = System.currentTimeMillis();
-            JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-            long maxGenerations = extractor.getTotalGcGenerations();
-            List<Generation> generations = new ArrayList<Generation>();
-            VmMemoryStat stat = new VmMemoryStat(timestamp, vmId, generations);
-            for (long generation = 0; generation < maxGenerations; generation++) {
-                Generation g = new Generation();
-                generations.add(g);
-                g.name = extractor.getGenerationName(generation);
-                g.capacity = extractor.getGenerationCapacity(generation);
-                g.maxCapacity = extractor.getGenerationMaxCapacity(generation);
-                g.collector = extractor.getGenerationCollector(generation);
-                long maxSpaces = extractor.getTotalSpaces(generation);
-                List<Space> spaces = new ArrayList<Space>();
-                g.spaces = spaces;
-                for (long space = 0; space < maxSpaces; space++) {
-                    Space s = new Space();
-                    spaces.add(s);
-                    s.index = (int) space;
-                    s.name = extractor.getSpaceName(generation, space);
-                    s.capacity = extractor.getSpaceCapacity(generation, space);
-                    s.maxCapacity = extractor.getSpaceMaxCapacity(generation, space);
-                    s.used = extractor.getSpaceUsed(generation, space);
-                }
-            }
-            memDAO.putVmMemoryStat(stat);
-        } catch (MonitorException e) {
-            logger.log(Level.WARNING, "error gathering memory info for vm " + vmId, e);
-        }
-    }
-
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/LsbRelease.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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";
-
-    @Override
-    public DistributionInformation getDistributionInformation()
-            throws IOException {
-        return getFromLsbRelease();
-    }
-
-    public DistributionInformation getFromLsbRelease() throws IOException {
-
-        BufferedReader reader = null;
-        try {
-            Process lsbProc = Runtime.getRuntime().exec(new String[] { "lsb_release", "-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/agent/src/main/java/com/redhat/thermostat/backend/system/MemoryStatBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.Constants;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * Implementation note: uses information from /proc/
- */
-public class MemoryStatBuilder {
-
-    private static final long UNAVAILABLE = -1;
-
-    private static final String KEY_MEMORY_TOTAL = "MemTotal";
-    private static final String KEY_MEMORY_FREE = "MemFree";
-    private static final String KEY_BUFFERS = "Buffers";
-    private static final String KEY_CACHED = "Cached";
-    private static final String KEY_SWAP_TOTAL = "SwapTotal";
-    private static final String KEY_SWAP_FREE = "SwapFree";
-    private static final String KEY_COMMIT_LIMIT = "CommitLimit";
-
-    private static final Logger logger = LoggingUtils.getLogger(MemoryStatBuilder.class);
-
-    private final ProcDataSource dataSource;
-
-    public MemoryStatBuilder(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    protected MemoryStat build() {
-        long timestamp = System.currentTimeMillis();
-
-        long total = UNAVAILABLE;
-        long free = UNAVAILABLE;
-        long swapTotal = UNAVAILABLE;
-        long swapFree = UNAVAILABLE;
-        long buffers = UNAVAILABLE;
-        long cached = UNAVAILABLE;
-        long commitLimit = UNAVAILABLE;
-
-        try (BufferedReader reader = new BufferedReader(dataSource.getMemInfoReader())) {
-            String line = null;
-            while ((line = reader.readLine()) != null) {
-                String[] parts = line.split(":");
-                if (parts.length == 2) {
-                    String key = parts[0].trim();
-                    long value = getValue(parts[1].trim());
-                    if (key.equals(KEY_MEMORY_TOTAL)) {
-                        total = value;
-                    } else if (key.equals(KEY_MEMORY_FREE)) {
-                        free = value;
-                    } else if (key.equals(KEY_SWAP_TOTAL)) {
-                        swapTotal = value;
-                    } else if (key.equals(KEY_SWAP_FREE)) {
-                        swapFree = value;
-                    } else if (key.equals(KEY_BUFFERS)) {
-                        buffers = value;
-                    } else if (key.equals(KEY_CACHED)) {
-                        cached = value;
-                    } else if (key.equals(KEY_COMMIT_LIMIT)) {
-                        commitLimit = value;
-                    }
-                }
-            }
-        } catch (IOException ioe) {
-            logger.log(Level.WARNING, "unable to read memory info");
-        }
-
-        return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit);
-    }
-
-    private long getValue(String rawValue) {
-        String[] parts = rawValue.split(" +");
-        String value = rawValue;
-        String units = null;
-        if (parts.length > 1) {
-            value = parts[0];
-            units = parts[1];
-        }
-
-        long result = UNAVAILABLE;
-        try {
-            result = Long.parseLong(value);
-            if (units != null) {
-                if (units.equals("kB") || units.equals("KB")) {
-                    result = result * Constants.KILOBYTES_TO_BYTES;
-                } else {
-                    throw new NotImplementedException("unit conversion from " + units + " not implemented");
-                }
-            }
-        } catch (NumberFormatException nfe) {
-            logger.log(Level.WARNING, "error extracting memory info");
-        }
-
-        return result;
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/NetworkInfoBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class NetworkInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(NetworkInfoBuilder.class);
-
-    public static List<NetworkInterfaceInfo> build() {
-        List<NetworkInterfaceInfo> infos = new ArrayList<NetworkInterfaceInfo>();
-        try {
-            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
-            for (NetworkInterface iface : Collections.list(ifaces)) {
-                NetworkInterfaceInfo info = new NetworkInterfaceInfo(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/agent/src/main/java/com/redhat/thermostat/backend/system/ProcDataSource.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-
-public class ProcDataSource {
-
-    private static final String LOAD_FILE = "/proc/loadavg";
-    private static final String MEMINFO_FILE = "/proc/meminfo";
-    private static final String CPUINFO_FILE = "/proc/cpuinfo";
-
-    private static final String PID_STAT_FILE = "/proc/${pid}/stat";
-    private static final String PID_ENVIRON_FILE = "/proc/${pid}/environ";
-
-    /**
-     * Returns a reader for /proc/cpuinfo
-     */
-    public Reader getCpuInfoReader() throws IOException {
-        return new FileReader(CPUINFO_FILE);
-    }
-
-    /**
-     * Returns a reader for /proc/loadavg
-     */
-    public Reader getCpuLoadReader() throws IOException {
-        return new FileReader(LOAD_FILE);
-    }
-
-    /**
-     * Returns a reader for /proc/meminfo
-     */
-    public Reader getMemInfoReader() throws IOException {
-        return new FileReader(MEMINFO_FILE);
-    }
-
-    /**
-     * Returns a reader for /proc/$PID/stat
-     */
-    public Reader getStatReader(int pid) throws IOException {
-        return new FileReader(getPidFile(PID_STAT_FILE, pid));
-    }
-
-    /**
-     * Returns a reader for /proc/$PID/environ
-     */
-    public Reader getEnvironReader(int pid) throws IOException {
-        return new FileReader(getPidFile(PID_ENVIRON_FILE, pid));
-    }
-
-    private String getPidFile(String fileName, int pid) {
-        return fileName.replace("${pid}", Integer.toString(pid));
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.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/agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public class ProcessStatusInfo {
-
-    /* All times are measured in clock ticks */
-
-    private final int pid;
-    private final long userTime;
-    private final long kernelTime;
-
-    public ProcessStatusInfo(int pid, long userTime, long kernelTime) {
-        this.pid = pid;
-        this.userTime = userTime;
-        this.kernelTime = kernelTime;
-    }
-
-    public int getPid() {
-        return pid;
-    }
-
-    /**
-     * @return the time this process has spent in user-mode as a number of
-     * kernel ticks
-     */
-    public long getUserTime() {
-        return userTime;
-    }
-
-    /**
-     * @return the time this process spent in kernel-mode as a number of kernel
-     * ticks
-     */
-    public long getKernelTime() {
-        return kernelTime;
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Scanner;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-/**
- * Extract status information about the process from /proc/. This is what tools
- * like {@code ps} and {@code top} use.
- *
- * @see {@code proc(5)}
- */
-public class ProcessStatusInfoBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(ProcessStatusInfoBuilder.class);
-
-    private final ProcDataSource dataSource;
-
-    public ProcessStatusInfoBuilder(ProcDataSource dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    public ProcessStatusInfo build(int pid) {
-        try (BufferedReader reader = new BufferedReader(dataSource.getStatReader(pid))) {
-            return build(reader);
-        } catch (IOException e) {
-            logger.log(Level.WARNING, "unable to read stat info for " + pid);
-        }
-
-        return null;
-    }
-
-    private ProcessStatusInfo build(Reader r) throws IOException {
-
-        int pid = -1;
-        long utime = -1;
-        long stime = -1;
-
-        Scanner scanner = null;
-
-        /* TODO map these (effectively c) data types to java types more sanely */
-
-        try (BufferedReader reader = new BufferedReader(r)) {
-            String statusLine = reader.readLine();
-
-            /* be prepared for process names like '1 ) 2 3 4 foo 5' */
-
-            scanner = new Scanner(statusLine);
-            pid = scanner.nextInt();
-            scanner.close();
-
-            int execEndNamePos = statusLine.lastIndexOf(')');
-
-            String cleanStatusLine = statusLine.substring(execEndNamePos + 1);
-
-            scanner = new Scanner(cleanStatusLine);
-            /* state = */scanner.next();
-            /* ppid = */scanner.nextInt();
-            /* pgrp = */scanner.nextInt();
-            /* session = */scanner.nextInt();
-            /* tty_nr = */scanner.nextInt();
-            /* tpgid = */scanner.nextInt();
-            /* flags = */scanner.nextInt();
-            /* minflt = */scanner.nextLong();
-            /* cminflt = */scanner.nextLong();
-            /* majflt = */scanner.nextLong();
-            /* cmajflt = */scanner.nextLong();
-            utime = scanner.nextLong();
-            stime = scanner.nextLong();
-            scanner.close();
-        }
-
-        return new ProcessStatusInfo(pid, utime, stime);
-
-    }
-
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/SysConf.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.InputStreamReader;
-
-/**
- * A wrapper over POSIX's sysconf.
- * <p>
- * Implementation notes: uses {@code getconf(1)}
- */
-public class SysConf {
-
-    private SysConf() {
-        /* do not initialize */
-    }
-
-    public static long getClockTicksPerSecond() {
-        String ticks = sysConf("CLK_TCK");
-        try {
-            return Long.valueOf(ticks);
-        } catch (NumberFormatException nfe) {
-            return 0;
-        }
-    }
-
-    private static String sysConf(String arg) {
-        BufferedReader reader = null;
-        try {
-            Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg });
-            int result = process.waitFor();
-            if (result != 0) {
-                return null;
-            }
-            reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
-            return reader.readLine();
-        } catch (IOException e) {
-            return null;
-        } catch (InterruptedException e) {
-            return null;
-        } finally {
-            if (reader != null) {
-                try {
-                    reader.close();
-                } catch (IOException e) {
-                    // TODO
-                }
-            }
-        }
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,254 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.CopyOnWriteArraySet;
-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.JvmStatusListener;
-import com.redhat.thermostat.agent.JvmStatusNotifier;
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.SystemClock;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class SystemBackend extends Backend implements JvmStatusNotifier, JvmStatusListener {
-
-    private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class);
-
-    private CpuStatDAO cpuStats;
-    private HostInfoDAO hostInfos;
-    private MemoryStatDAO memoryStats;
-    private VmCpuStatDAO vmCpuStats;
-    private NetworkInterfaceInfoDAO networkInterfaces;
-
-    private final List<Category> categories = new ArrayList<Category>();
-
-    private final Set<Integer> pidsToMonitor = new CopyOnWriteArraySet<Integer>();
-
-    private long procCheckInterval = 1000; // TODO make this configurable.
-
-    private Timer timer = null;
-
-    private HostIdentifier hostId = null;
-    private MonitoredHost host = null;
-    private JvmStatHostListener hostListener;
-
-    private final VmCpuStatBuilder vmCpuBuilder;
-    private final HostInfoBuilder hostInfoBuilder;
-    private final CpuStatBuilder cpuStatBuilder;
-    private final MemoryStatBuilder memoryStatBuilder;
-
-    public SystemBackend() {
-        super();
-
-        // Set up categories that will later be registered.
-        categories.add(CpuStatDAO.cpuStatCategory);
-        categories.add(HostInfoDAO.hostInfoCategory);
-        categories.add(MemoryStatDAO.memoryStatCategory);
-        categories.add(NetworkInterfaceInfoDAO.networkInfoCategory);
-        categories.add(VmClassStatDAO.vmClassStatsCategory);
-        categories.add(VmCpuStatDAO.vmCpuStatCategory);
-        categories.add(VmGcStatDAO.vmGcStatCategory);
-        categories.add(VmInfoDAO.vmInfoCategory);
-        categories.add(VmMemoryStatDAO.vmMemoryStatsCategory);
-
-        Clock clock = new SystemClock();
-        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource());
-        long ticksPerSecond = SysConf.getClockTicksPerSecond();
-        ProcDataSource source = new ProcDataSource();
-        hostInfoBuilder = new HostInfoBuilder(source);
-        cpuStatBuilder = new CpuStatBuilder(source);
-        memoryStatBuilder = new MemoryStatBuilder(source);
-
-        int cpuCount = hostInfoBuilder.getCpuInfo().count;
-        vmCpuBuilder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, builder);
-    }
-
-    @Override
-    protected void setDAOFactoryAction() {
-        cpuStats = df.getCpuStatDAO();
-        hostInfos = df.getHostInfoDAO();
-        memoryStats = df.getMemoryStatDAO();
-        vmCpuStats = df.getVmCpuStatDAO();
-        networkInterfaces = df.getNetworkInterfaceInfoDAO();
-        hostListener = new JvmStatHostListener(df, getObserveNewJvm());
-    }
-
-    @Override
-    public synchronized boolean activate() {
-        if (timer != null) {
-            return true;
-        }
-        if (df == null) {
-            throw new IllegalStateException("Cannot activate backend without DAOFactory.");
-        }
-
-        addJvmStatusListener(this);
-
-        if (!getObserveNewJvm()) {
-            logger.fine("not monitoring new vms");
-        }
-        hostInfos.putHostInfo(hostInfoBuilder.build());
-
-        timer = new Timer();
-        timer.scheduleAtFixedRate(new TimerTask() {
-            @Override
-            public void run() {
-                cpuStats.putCpuStat(cpuStatBuilder.build());
-                for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) {
-                    networkInterfaces.putNetworkInterfaceInfo(info);
-                }
-                memoryStats.putMemoryStat(memoryStatBuilder.build());
-
-                for (Integer pid : pidsToMonitor) {
-                    if (vmCpuBuilder.knowsAbout(pid)) {
-                        VmCpuStat dataBuilt = vmCpuBuilder.build(pid);
-                        if (dataBuilt != null) {
-                            vmCpuStats.putVmCpuStat(dataBuilt);
-                        }
-                    } else {
-                        vmCpuBuilder.learnAbout(pid);
-                    }
-                }
-            }
-        }, 0, procCheckInterval);
-
-        try {
-            hostId = new HostIdentifier((String) null);
-            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;
-
-        removeJvmStatusListener(this);
-
-        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 String getConfigurationValue(String key) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    protected Collection<Category> getCategories() {
-        return Collections.unmodifiableCollection(categories);
-    }
-
-    @Override
-    public boolean attachToNewProcessByDefault() {
-        return true;
-    }
-
-    @Override
-    public void addJvmStatusListener(JvmStatusListener listener) {
-        hostListener.addJvmStatusListener(listener);
-    }
-
-    @Override
-    public void removeJvmStatusListener(JvmStatusListener listener) {
-        hostListener.removeJvmStatusListener(listener);
-    }
-
-    @Override
-    public void jvmStarted(int vmId) {
-        if (getObserveNewJvm()) {
-            pidsToMonitor.add(vmId);
-        }
-    }
-
-    @Override
-    public void jvmStopped(int vmId) {
-        pidsToMonitor.remove(vmId);
-        vmCpuBuilder.forgetAbout(vmId);
-    }
-}
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class VmCpuStatBuilder {
-
-    private static final Logger logger = LoggingUtils.getLogger(VmCpuStatBuilder.class);
-
-    // pid -> ticks
-    private final Map<Integer, Long> lastProcessTicks = new HashMap<Integer, Long>();
-    // pid -> last time the ticks were updated
-    private final Map<Integer, Long> lastProcessTickTime = new HashMap<Integer, Long>();
-
-    private final Clock clock;
-    private final int cpuCount;
-    private final long ticksPerSecond;
-    private final ProcessStatusInfoBuilder statusBuilder;
-
-    public VmCpuStatBuilder(Clock clock, int cpuCount, long ticksPerSecond, ProcessStatusInfoBuilder statusBuilder) {
-        this.clock = clock;
-        this.cpuCount = cpuCount;
-        this.ticksPerSecond = ticksPerSecond;
-        this.statusBuilder = statusBuilder;
-    }
-
-    /**
-     * @param pid the process id
-     * @return an object representing the cpu usage of the process, or null if
-     * the information can not be found.
-     */
-    public synchronized VmCpuStat build(Integer pid) {
-        if (!lastProcessTicks.containsKey(pid) || !lastProcessTickTime.containsKey(pid)) {
-            throw new IllegalArgumentException("unknown pid");
-        }
-
-        ProcessStatusInfo info = statusBuilder.build(pid);
-        if (info == null) {
-            return null;
-        }
-        long miliTime = clock.getRealTimeMillis();
-        long time = clock.getMonotonicTimeNanos();
-        long programTicks = (info.getKernelTime() + info.getUserTime());
-        double cpuLoad = 0.0;
-
-        double timeDelta = (time - lastProcessTickTime.get(pid)) * 1E-9;
-        long programTicksDelta = programTicks - lastProcessTicks.get(pid);
-        // 100 as in 100 percent.
-        cpuLoad = programTicksDelta * (100.0 / timeDelta / ticksPerSecond / cpuCount);
-
-        if (cpuLoad < 0.0 || cpuLoad > 100.0) {
-            logger.log(Level.WARNING, "cpu load for " + pid + " is outside [0,100]: " + cpuLoad);
-            logger.log(Level.WARNING, "  (" + pid + ") programTicks: " + programTicks);
-            logger.log(Level.WARNING, "  (" + pid + ") programTicksDelta: " + programTicksDelta);
-            logger.log(Level.WARNING, "  (" + pid + ") time: " + time);
-            logger.log(Level.WARNING, "  (" + pid + ") timeDelta: " + timeDelta);
-            logger.log(Level.WARNING, "  (" + pid + ") ticksPerSecond: " + ticksPerSecond);
-            logger.log(Level.WARNING, "  (" + pid + ") cpuCount: " + cpuCount);
-        }
-
-        lastProcessTicks.put(pid, programTicks);
-        lastProcessTickTime.put(pid, time);
-
-        return new VmCpuStat(miliTime, pid, cpuLoad);
-    }
-
-    public synchronized boolean knowsAbout(int pid) {
-        return (lastProcessTickTime.containsKey(pid) && lastProcessTicks.containsKey(pid));
-    }
-
-    public synchronized void learnAbout(int pid) {
-        long time = clock.getMonotonicTimeNanos();
-        ProcessStatusInfo info = statusBuilder.build(pid);
-        if (info == null) {
-            logger.log(Level.WARNING, "can not learn about pid " + pid + " : statusBuilder returned null");
-        }
-
-        lastProcessTickTime.put(pid, time);
-        lastProcessTicks.put(pid, info.getUserTime()+ info.getKernelTime());
-    }
-
-    public synchronized void forgetAbout(int pid) {
-        lastProcessTicks.remove(pid);
-        lastProcessTickTime.remove(pid);
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/agent/AgentApplicationTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collection;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.ArgumentSpec;
-import com.redhat.thermostat.common.cli.SimpleArgumentSpec;
-
-public class AgentApplicationTest {
-
-    // TODO: Test i18nized versions when they come.
-
-    private AgentApplication agent;
-
-    @Before
-    public void setUp() {
-        agent = new AgentApplication();
-    }
-
-    @After
-    public void tearDown() {
-        agent = null;
-    }
-
-    @Test
-    public void testName() {
-        String name = agent.getName();
-        assertEquals("agent", name);
-    }
-
-    @Test
-    public void testDescription() {
-        String description = agent.getDescription();
-        assertEquals("starts and stops the thermostat agent", description);
-    }
-
-    @Test
-    public void testUsage() {
-        String usage = agent.getUsage();
-        assertEquals("starts and stops the thermostat agent", usage);
-    }
-
-    @Test
-    public void testAcceptedArguments() {
-        Collection<ArgumentSpec> args = agent.getAcceptedArguments();
-        assertNotNull(args);
-        assertEquals(3, args.size());
-        assertTrue(args.contains(new SimpleArgumentSpec("saveOnExit", "s", "save the data on exit", false, false)));
-        assertTrue(args.contains(new SimpleArgumentSpec("debug", "launch with debug console enabled")));
-        assertTrue(args.contains(new SimpleArgumentSpec("dbUrl", "d", "connect to the given url", true, true)));
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/agent/AgentTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
-import com.redhat.thermostat.backend.Backend;
-import com.redhat.thermostat.backend.BackendRegistry;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.storage.AgentInformation;
-import com.redhat.thermostat.common.storage.BackendInformation;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class AgentTest {
-
-    private AgentStartupConfiguration config;
-    private Storage storage;
-    private BackendRegistry backendRegistry;
-    private Backend backend;
-    private DAOFactory daos;
-    
-    @Before
-    public void setUp() {
-        config = mock(AgentStartupConfiguration.class);
-        when(config.getStartTime()).thenReturn(123L);
-        when(config.purge()).thenReturn(true);
-        
-        storage = mock(Storage.class);
-        daos = mock(DAOFactory.class);
-        when(daos.getStorage()).thenReturn(storage);
-        
-        backend = mock(Backend.class);
-        when(backend.getName()).thenReturn("testname");
-        when(backend.getDescription()).thenReturn("testdesc");
-        when(backend.getObserveNewJvm()).thenReturn(true);
-        when(backend.activate()).thenReturn(true); // TODO: activate() should not return anything and throw exception in error case.
-        Collection<Backend> backends = new ArrayList<Backend>();
-        backends.add(backend);
-        
-        backendRegistry = mock(BackendRegistry.class);
-        when(backendRegistry.getAll()).thenReturn(backends);
-    }
-    
-    @Test
-    public void testStartAgent() throws Exception {
-        
-        // Start agent.
-        Agent agent = new Agent(backendRegistry, config, daos);
-        agent.start();
-
-        // Verify that backend has been activated and storage received the agent information.
-        verify(backend).activate();
-        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);
-        verify(storage).addAgentInformation(argument.capture());
-        assertEquals(123, argument.getValue().getStartTime());
-        List<BackendInformation> backendInfos = argument.getValue().getBackends();
-        assertEquals(1, backendInfos.size());
-        BackendInformation backend0 = backendInfos.get(0);
-        assertEquals("testname", backend0.getName());
-        assertEquals("testdesc", backend0.getDescription());
-        assertEquals(true, backend0.isObserveNewJvm());
-        // TODO: We should probably also test getPIDs() and getConfiguration(), but it's not clear to me at this point
-        // what those should really do (and it looks like they're not implemented yet).
-    }
-    
-    @Test
-    public void testStopAgentWithPurging() throws Exception {
-        Agent agent = new Agent(backendRegistry, config, daos);
-        agent.start();
-        
-        // stop agent
-        agent.stop();
-        
-        verify(backend).deactivate();
-
-        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);        
-        verify(storage, never()).updateAgentInformation(argument.capture());
-        verify(storage, times(1)).purge();
-    }
-    
-    @Test
-    public void testStopAgent() throws Exception {
-        
-        AgentStartupConfiguration config = mock(AgentStartupConfiguration.class);
-        when(config.getStartTime()).thenReturn(123L);
-        when(config.purge()).thenReturn(false);
-        
-        Agent agent = new Agent(backendRegistry, config, daos);
-        agent.start();
-        
-        // stop agent
-        agent.stop();
-        
-        verify(backend).deactivate();
-
-        ArgumentCaptor<AgentInformation> argument = ArgumentCaptor.forClass(AgentInformation.class);        
-        verify(storage).updateAgentInformation(argument.capture());
-        verify(storage, times(0)).purge();
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/agent/TestUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.util.Properties;
-import java.util.Random;
-
-import com.redhat.thermostat.agent.config.AgentProperties;
-import com.redhat.thermostat.backend.BackendsProperties;
-
-public class TestUtils {
-
-    public static int getProcessId() {
-        String name = ManagementFactory.getRuntimeMXBean().getName();
-        String pidPart = name.split("@")[0];
-        return Integer.parseInt(pidPart);
-    }
-
-    public static boolean isLinux() {
-        return (System.getProperty("os.name").toLowerCase().contains("linux"));
-    }
-        
-    public static String setupAgentConfigs() throws IOException {
-        // need to create dummy config files for the tests
-        Random random = new Random();
-
-        String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar +
-                Math.abs(random.nextInt()) + File.separatorChar;
-
-        System.setProperty("THERMOSTAT_HOME", tmpDir);
-        File agent = new File(tmpDir, "agent");
-        agent.mkdirs();
-
-        File tmpConfigs = new File(agent, "agent.properties");
-
-        new File(agent, "run").mkdirs();
-        new File(agent, "logs").mkdirs();
-
-        File backends = new File(tmpDir, "backends");
-        File system = new File(backends, "system");
-        system.mkdirs();
-        
-        Properties props = new Properties();            
-
-        props.setProperty(AgentProperties.BACKENDS.name(), "system");
-        props.setProperty(AgentProperties.SAVE_ON_EXIT.name(), "false");
-
-        props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties");
-
-        // now write the configs for the backends
-        tmpConfigs = new File(system, "backend.properties");
-        props = new Properties();
-        props.setProperty(BackendsProperties.BACKEND_CLASS.name(),
-                          "com.redhat.thermostat.backend.system.SystemBackend");
-        props.setProperty(BackendsProperties.DESCRIPTION.name(),
-                          "fluff backend for tests");
-        props.setProperty(BackendsProperties.VENDOR.name(),
-                          "Red Hat, Inc.");
-        props.setProperty(BackendsProperties.VERSION.name(),
-                          "1.0");
-        props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties");
-        
-        return tmpDir;
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/agent/config/AgentConfigsUtilsTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.TestUtils;
-import com.redhat.thermostat.backend.BackendID;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-public class AgentConfigsUtilsTest {
-    
-    @Before
-    public void setUp() throws IOException, InvalidConfigurationException {
-        TestUtils.setupAgentConfigs();
-    }
-    
-    @Test
-    public void test() throws InvalidConfigurationException {
-        AgentStartupConfiguration config = AgentConfigsUtils.createAgentConfigs();        
-        List<BackendID> backends = config.getBackends();
-        
-        // the test property only define the system backend so far
-        Assert.assertEquals(1, backends.size());
-        Assert.assertEquals("system", backends.get(0).getSimpleName());
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.config;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.TestUtils;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-public class AgentOptionParserTest {
-    
-    private static File tmpFile;
-    
-    @BeforeClass
-    public static void setup() throws IOException {
-        tmpFile = new File(TestUtils.setupAgentConfigs());
-    }
-    
-    @AfterClass
-    public static void shutdown() {
-        tmpFile.delete();
-    }
-    
-    @Test
-    public void testConfigs1() throws IOException, InvalidConfigurationException {
-        
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("dbUrl", "testURL");
-        args.addArgument("debug", "--debug");
-        
-        AgentStartupConfiguration configs = AgentConfigsUtils.createAgentConfigs();
-        AgentOptionParser parser = new AgentOptionParser(configs, args);
-        parser.parse();
-        
-        Assert.assertEquals("testURL", configs.getDBConnectionString());
-        Assert.assertTrue(configs.isDebugConsole());
-        Assert.assertTrue(configs.purge());
-    }
-    
-    @Test
-    public void testConfigs2() throws IOException, InvalidConfigurationException {
-        
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("dbUrl", "testURL2");
-        args.addArgument("saveOnExit", "--saveOnExit");
-        
-        AgentStartupConfiguration configs = new AgentStartupConfiguration();
-        AgentOptionParser parser = new AgentOptionParser(configs, args);
-        parser.parse();
-        
-        Assert.assertEquals("testURL2", configs.getDBConnectionString());
-        Assert.assertFalse(configs.isDebugConsole());
-        Assert.assertFalse(configs.purge());
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/BackendConfigurationLoaderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.io.IOException;
-import java.util.Map;
-
-import junit.framework.Assert;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.TestUtils;
-import com.redhat.thermostat.backend.system.SystemBackend;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-public class BackendConfigurationLoaderTest {
-    
-    @Before
-    public void setUp() throws IOException {
-        TestUtils.setupAgentConfigs();
-    }
-    
-    @Test
-    public void test() throws InvalidConfigurationException {
-        Map<String, String> backendProps = new BackendConfigurationLoader().retrieveBackendConfigs("system");
-        Assert.assertTrue(backendProps.containsKey(BackendsProperties.BACKEND_CLASS.name()));
-        
-        String className = backendProps.get(BackendsProperties.BACKEND_CLASS.name());
-        Assert.assertEquals(SystemBackend.class.getCanonicalName(), className);
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.config.AgentStartupConfiguration;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class BackendRegistryTest {
-
-    public static class MockBackend extends Backend {
-        public MockBackend() {
-            super();
-        }
-
-        @Override
-        protected Collection<Category> getCategories() {
-            return Collections.emptyList();
-        }
-        @Override
-        public String getConfigurationValue(String key) {
-            return null;
-        }
-        @Override
-        public boolean activate() {
-            return true;
-        }
-        @Override
-        public boolean deactivate() {
-            return false;
-        }
-        @Override
-        public boolean isActive() {
-            return false;
-        }
-        @Override
-        public boolean attachToNewProcessByDefault() {
-            return false;
-        }
-
-        @Override
-        protected void setDAOFactoryAction() {
-            // TODO Auto-generated method stub
-            
-        }
-    }
-
-    private List<BackendID> backends;
-    private AgentStartupConfiguration config;
-    private BackendConfigurationLoader configLoader;
-
-    @Before
-    public void setUp() throws InvalidConfigurationException {
-        backends = new ArrayList<>();
-
-        config = mock(AgentStartupConfiguration.class);
-        when(config.getBackends()).thenReturn(backends);
-
-        configLoader = mock(BackendConfigurationLoader.class);
-        when(configLoader.retrieveBackendConfigs(any(String.class))).thenReturn(new HashMap<String,String>());
-
-        Storage storage = mock(Storage.class);
-        DAOFactory df = mock(DAOFactory.class);
-        when(df.getStorage()).thenReturn(storage);
-        ApplicationContext.getInstance().setDAOFactory(df);
-    }
-
-    @After
-    public void tearDown() {
-        backends = null;
-        config = null;
-        configLoader = null;
-    }
-
-    @Test
-    public void testRegisterBackend() throws BackendLoadException, InvalidConfigurationException {
-        /* setup fake backend */
-        backends.add(new BackendID("mock", MockBackend.class.getName()));
-
-        BackendRegistry registry = new BackendRegistry(config, configLoader);
-        assertEquals(1, registry.getAll().size());
-        assertNotNull(registry.getByName("mock"));
-    }
-
-    @Test
-    public void testNoBackendsRegistered() throws InvalidConfigurationException, BackendLoadException {
-        BackendRegistry registry = new BackendRegistry(config, configLoader);
-        assertEquals(0, registry.getAll().size());
-        assertEquals(null, registry.getByName("system"));
-        assertEquals(null, registry.getByName("mock"));
-    }
-
-    @Test (expected=BackendLoadException.class)
-    public void testRegisterBackendTwice() throws BackendLoadException, InvalidConfigurationException {
-        /* setup fake backends */
-
-        backends.add(new BackendID("mock", MockBackend.class.getClass().getName()));
-        backends.add(new BackendID("mock", MockBackend.class.getClass().getName()));
-
-        /* load the backends */
-        new BackendRegistry(config, configLoader);
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/sample/SampleBackendTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.sample;
-
-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 java.util.Collection;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.storage.Category;
-
-public class SampleBackendTest {
-
-    private SampleBackend b;
-
-    @Before
-    public void setUp() {
-        b = new SampleBackend();
-    }
-
-    @Test
-    public void testBackendInfo() {
-        assertNotNull(b.getName());
-        assertNotNull(b.getVersion());
-        assertNotNull(b.getVendor());
-        assertNotNull(b.getDescription());
-    }
-
-    @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 testCategoriesAreSane() {
-        Collection<Category> categories = b.getCategories();
-        assertEquals(0, categories.size());
-    }
-
-    @Test
-    public void testDefaultConfiguration() {
-        assertTrue(b.getConfigurationMap().isEmpty());
-        assertTrue(b.getConfigurationValue("foo") == null);
-
-    }
-
-    @Test
-    public void testModifyConfiguration() {
-        b.setConfigurationValue("speed", "fast");
-        assertEquals("fast", b.getConfigurationValue("speed"));
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.CpuStat;
-
-public class CpuStatBuilderTest {
-
-    @Test
-    public void testSimpleBuild() {
-        ProcDataSource dataSource = new ProcDataSource();
-        CpuStat stat = new CpuStatBuilder(dataSource).build();
-        assertNotNull(stat);
-    }
-
-    @Test
-    public void testBuildCpuStatFromFile() throws IOException {
-        String line = "0.05 0.08 0.06 1/368 16413";
-        BufferedReader reader = new BufferedReader(new StringReader(line));
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getCpuLoadReader()).thenReturn(reader);
-        CpuStat stat = new CpuStatBuilder(dataSource).build();
-
-        verify(dataSource).getCpuLoadReader();
-        assertEquals(0.05, stat.getLoad5(), 0.01);
-        assertEquals(0.08, stat.getLoad10(), 0.01);
-        assertEquals(0.06, stat.getLoad15(), 0.01);
-
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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 org.junit.Test;
-
-import com.redhat.thermostat.agent.TestUtils;
-
-public class DistributionInformationTest {
-
-    @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/agent/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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 java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.test.Bug;
-
-public class EtcOsReleaseTest {
-
-    @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());
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/HostInfoBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Test;
-
-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.Constants;
-import com.redhat.thermostat.common.model.HostInfo;
-
-public class HostInfoBuilderTest {
-
-    @Test
-    public void testSimpleBuild() {
-        HostInfo info = new HostInfoBuilder(new ProcDataSource()).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).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).getMemoryInfo();
-        assertNotNull(memoryInfo);
-        assertEquals(12345 * Constants.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).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).getHostName(address);
-        assertEquals("test-hostname", name);
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,375 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.LongMonitor;
-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;
-    }
-
-    private MonitoredVm buildLongMonitoredVm(String monitorName, Long monitorReturn) throws MonitorException {
-        final LongMonitor monitor = mock(LongMonitor.class);
-        when(monitor.longValue()).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);
-    }
-
-    @Test
-    public void testTotalCollectors() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.policy.collectors";
-        final Long MONITOR_VALUE = 9l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getTotalCollectors();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(MONITOR_VALUE, returned);
-    }
-
-    @Test
-    public void testCollectorName() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.collector.0.name";
-        final String COLLECTOR_NAME = "SomeMemoryCollector";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getCollectorName(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(COLLECTOR_NAME, returned);
-    }
-
-    @Test
-    public void testCollectorTime() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.collector.0.time";
-        final Long COLLECTOR_TIME = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getCollectorTime(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(COLLECTOR_TIME, returned);
-    }
-
-    @Test
-    public void testCollectorInvocations() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.collector.0.invocations";
-        final Long COLLECTOR_INVOCATIONS = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getCollectorInvocations(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(COLLECTOR_INVOCATIONS, returned);
-    }
-
-    @Test
-    public void testTotalGcGenerations() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.policy.generations";
-        final Long GC_GENERATIONS = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GC_GENERATIONS);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getTotalGcGenerations();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(GC_GENERATIONS, returned);
-    }
-
-    @Test
-    public void testGenerationName() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.name";
-        final String GENERATION_NAME = "Youth";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_NAME);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getGenerationName(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(GENERATION_NAME, returned);
-    }
-
-    @Test
-    public void testGenerationCapacity() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.capacity";
-        final Long GENERATION_CAPACITY = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_CAPACITY);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getGenerationCapacity(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(GENERATION_CAPACITY, returned);
-    }
-
-    @Test
-    public void testGenerationMaxCapacity() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.maxCapacity";
-        final Long GENERATION_MAX_CAPACITY = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, GENERATION_MAX_CAPACITY);
-
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getGenerationMaxCapacity(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(GENERATION_MAX_CAPACITY, returned);
-    }
-
-    @Test
-    public void testGenerationCollector() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.collector.0.name";
-        final String GENERATION_COLLECTOR = "generation collector";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, GENERATION_COLLECTOR);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getGenerationCollector(0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(GENERATION_COLLECTOR, returned);
-    }
-
-    @Test
-    public void testTotalSpaces() throws MonitorException {
-        final Long TOTAL_SPACES = 99l;
-        final LongMonitor monitor = mock(LongMonitor.class);
-        when(monitor.getValue()).thenReturn(TOTAL_SPACES);
-        MonitoredVm vm = mock(MonitoredVm.class);
-        when(vm.findByName("sun.gc.generation.0.spaces")).thenReturn(monitor);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getTotalSpaces(0);
-
-        verify(vm).findByName(eq("sun.gc.generation.0.spaces"));
-        assertEquals(TOTAL_SPACES, returned);
-    }
-
-
-    @Test
-    public void testSpaceName() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.space.0.name";
-        final String SPACE_NAME = "Hilbert";
-        MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, SPACE_NAME);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        String returned = extractor.getSpaceName(0,0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(SPACE_NAME, returned);
-    }
-
-    @Test
-    public void testSpaceCapacity() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.space.0.capacity";
-        final Long SPACE_CAPACITY = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_CAPACITY);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getSpaceCapacity(0,0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(SPACE_CAPACITY, returned);
-    }
-
-    @Test
-    public void testSpaceMaxCapacity() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.space.0.maxCapacity";
-        final Long SPACE_MAX_CAPACITY = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_MAX_CAPACITY);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getSpaceMaxCapacity(0,0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(SPACE_MAX_CAPACITY, returned);
-    }
-
-    @Test
-    public void testSpaceUsed() throws MonitorException {
-        final String MONITOR_NAME = "sun.gc.generation.0.space.0.used";
-        final Long SPACE_USED = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, SPACE_USED);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getSpaceUsed(0,0);
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(SPACE_USED, returned);
-    }
-
-    @Test
-    public void testLoadedClasses() throws MonitorException {
-        final String MONITOR_NAME = "java.cls.loadedClasses";
-        final Long LOADED_CLASSES = 99l;
-        MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, LOADED_CLASSES);
-
-        JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm);
-        Long returned = extractor.getLoadedClasses();
-
-        verify(vm).findByName(eq(MONITOR_NAME));
-        assertEquals(LOADED_CLASSES, returned);
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.mockito.Matchers.any;
-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 java.util.HashSet;
-import java.util.Set;
-
-import org.junit.Test;
-import org.mockito.Matchers;
-
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-
-import sun.jvmstat.monitor.HostIdentifier;
-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 {
-
-    @Test
-    public void testVmStatusChangedAddsVmClassListener() throws Exception {
-        VmStatusChangeEvent vmEvent = mock(VmStatusChangeEvent.class);
-        Set<Integer> startedVms = new HashSet<Integer>();
-        startedVms.add(123);
-        when(vmEvent.getStarted()).thenReturn(startedVms);
-
-        MonitoredVm vm = mock(MonitoredVm.class);
-        StringMonitor monitor = mock(StringMonitor.class);
-        when(monitor.stringValue()).thenReturn("test");
-        when(monitor.getValue()).thenReturn("test");
-        when(vm.findByName(anyString())).thenReturn(monitor);
-        MonitoredHost host = mock(MonitoredHost.class);
-        HostIdentifier hostId = mock(HostIdentifier.class);
-        when(host.getHostIdentifier()).thenReturn(hostId);
-        when(host.getMonitoredVm(any(VmIdentifier.class))).thenReturn(vm);
-        when(vmEvent.getMonitoredHost()).thenReturn(host);
-
-        VmClassStatDAO vmClassDAO = mock(VmClassStatDAO.class);
-        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
-        DAOFactory df = mock(DAOFactory.class);
-        when(df.getVmClassStatsDAO()).thenReturn(vmClassDAO);
-        when(df.getVmInfoDAO()).thenReturn(vmInfoDAO);
-        JvmStatHostListener l = new JvmStatHostListener(df, true);
-        SystemBackend backend = mock(SystemBackend.class);
-        when(backend.getObserveNewJvm()).thenReturn(true);
-
-        l.vmStatusChanged(vmEvent);
-
-        verify(vm).addVmListener(Matchers.isA(JvmStatVmClassListener.class));
-    }
-
-}
\ No newline at end of file
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import sun.jvmstat.monitor.Monitor;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.event.VmEvent;
-
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.model.VmClassStat;
-
-public class JvmStatVmClassListenerTest {
-
-    private static final Integer VM_ID = 123;
-    private static final Long LOADED_CLASSES = 1234L;
-
-    @Test
-    public void testMonitorUpdatedClassStat() throws Exception {
-
-        VmClassStatDAO dao = mock(VmClassStatDAO.class);
-        DAOFactory df = mock(DAOFactory.class);
-        when(df.getVmClassStatsDAO()).thenReturn(dao);
-        JvmStatVmClassListener l = new JvmStatVmClassListener(df, VM_ID);
-        VmEvent vmEvent = mock(VmEvent.class);
-        MonitoredVm monitoredVm = mock(MonitoredVm.class);
-        Monitor m = mock(Monitor.class);
-        when(m.getValue()).thenReturn(LOADED_CLASSES);
-        when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m);
-        when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm);
-
-        l.monitorsUpdated(vmEvent);
-
-        ArgumentCaptor<VmClassStat> arg = ArgumentCaptor.forClass(VmClassStat.class);
-        verify(dao).putVmClassStat(arg.capture());
-        VmClassStat stat = arg.getValue();
-        assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses());
-        assertEquals(VM_ID, (Integer) stat.getVmId());
-    }
-
-    @Test
-    public void testMonitorUpdatedClassStatTwice() throws Exception {
-
-        VmClassStatDAO dao = mock(VmClassStatDAO.class);
-        DAOFactory df = mock(DAOFactory.class);
-        when(df.getVmClassStatsDAO()).thenReturn(dao);
-        JvmStatVmClassListener l = new JvmStatVmClassListener(df, VM_ID);
-        VmEvent vmEvent = mock(VmEvent.class);
-        MonitoredVm monitoredVm = mock(MonitoredVm.class);
-        Monitor m = mock(Monitor.class);
-        when(m.getValue()).thenReturn(LOADED_CLASSES);
-        when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m);
-        when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm);
-
-        l.monitorsUpdated(vmEvent);
-        l.monitorsUpdated(vmEvent);
-
-        // This checks a bug where the Category threw an IllegalStateException because the DAO
-        // created a new one on each call, thus violating the unique guarantee of Category.
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/LsbReleaseTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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 java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-public class LsbReleaseTest {
-
-    @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());
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/MemoryStatBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.Constants;
-import com.redhat.thermostat.common.model.MemoryStat;
-
-public class MemoryStatBuilderTest {
-
-    @Test
-    public void testSimpleBuild() {
-        MemoryStat stat = new MemoryStatBuilder(new ProcDataSource()).build();
-        assertNotNull(stat);
-    }
-
-    @Test
-    public void testEmptyBuild() throws IOException {
-        String memory = "";
-        StringReader memoryReader = new StringReader(memory);
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getMemInfoReader()).thenReturn(memoryReader);
-
-        MemoryStat stat = new MemoryStatBuilder(dataSource).build();
-        assertNotNull(stat);
-        verify(dataSource).getMemInfoReader();
-    }
-
-    @Test
-    public void testBuild() throws IOException {
-        int i = 1;
-        final long TOTAL = i++;
-        final long FREE = i++;
-        final long BUFFERS = i++;
-        final long CACHED = i++;
-        final long COMMIT_LIMIT = i++;
-        final long SWAP_TOTAL = i++;
-        final long SWAP_FREE = i++;
-
-        String memory = "" +
-                "MemTotal: " + TOTAL + " kB\n" +
-                "MemFree:  " + FREE + " kB\n" +
-                "Buffers:" + BUFFERS + " kB\n" +
-                "Cached: " + CACHED + " kB\n" +
-                "CommitLimit: " + COMMIT_LIMIT + " kB\n" +
-                "SwapTotal: " + SWAP_TOTAL + " kB\n" +
-                "SwapFree: " + SWAP_FREE + " kB\n";
-
-        StringReader memoryReader = new StringReader(memory);
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getMemInfoReader()).thenReturn(memoryReader);
-
-        MemoryStat stat = new MemoryStatBuilder(dataSource).build();
-
-        assertEquals(BUFFERS * Constants.KILOBYTES_TO_BYTES, stat.getBuffers());
-        assertEquals(CACHED * Constants.KILOBYTES_TO_BYTES, stat.getCached());
-        assertEquals(COMMIT_LIMIT * Constants.KILOBYTES_TO_BYTES, stat.getCommitLimit());
-        assertEquals(FREE * Constants.KILOBYTES_TO_BYTES, stat.getFree());
-        assertEquals(SWAP_FREE * Constants.KILOBYTES_TO_BYTES, stat.getSwapFree());
-        assertEquals(SWAP_TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getSwapTotal());
-        assertEquals(TOTAL * Constants.KILOBYTES_TO_BYTES, stat.getTotal());
-        assertTrue(stat.getTimeStamp() != 0 && stat.getTimeStamp() != Long.MIN_VALUE);
-        assertTrue(stat.getTimeStamp() <= System.currentTimeMillis());
-        verify(dataSource).getMemInfoReader();
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/NetworkInfoBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-
-public class NetworkInfoBuilderTest {
-
-    @Test
-    public void testBuilder() {
-
-        List<NetworkInterfaceInfo> info = NetworkInfoBuilder.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}"));
-            }
-            // TODO check for sane ipv6 address
-        }
-
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/ProcDataSourceTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.assertNotNull;
-
-import java.io.IOException;
-import java.io.Reader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.agent.TestUtils;
-
-public class ProcDataSourceTest {
-
-    @Test
-    public void testGetCpuInfoReader() throws IOException {
-        Reader r = new ProcDataSource().getCpuInfoReader();
-        assertNotNull(r);
-    }
-
-    @Test
-    public void testGetCpuLoadReader() throws IOException {
-        Reader r = new ProcDataSource().getCpuLoadReader();
-        assertNotNull(r);
-    }
-
-    @Test
-    public void testGetMemInfoReader() throws IOException {
-        Reader r = new ProcDataSource().getMemInfoReader();
-        assertNotNull(r);
-    }
-
-    @Test
-    public void testGetStatReader() throws IOException {
-        int pid = TestUtils.getProcessId();
-        Reader r = new ProcDataSource().getStatReader(pid);
-        assertNotNull(r);
-    }
-
-
-    @Test
-    public void testGetEnvironReader() throws IOException {
-        int pid = TestUtils.getProcessId();
-        Reader r = new ProcDataSource().getEnvironReader(pid);
-        assertNotNull(r);
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/ProcessEnvironmentBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.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/agent/src/test/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-public class ProcessStatusInfoBuilderTest {
-
-    @Test
-    public void testSimpleProcessStatus() {
-        ProcDataSource dataSource = new ProcDataSource();
-        ProcessStatusInfo stat = new ProcessStatusInfoBuilder(dataSource).build(1);
-        assertNotNull(stat);
-    }
-
-    @Test
-    public void testKnownProcessStatus() throws IOException {
-        final int PID = 10363;
-        String PROCESS_NAME = "(bash)";
-        String STATE = "S";
-        String PPID = "1737";
-        String PROCESS_GROUP_ID = "10363";
-        String SESSION_ID = "10363";
-        String TTY_NUMBER = "34817";
-        String TTY_PROCESS_GROUP_ID = "11404";
-        String FLAGS_WORD = "4202496";
-        String MINOR_FAULTS = "8093";
-        String MINOR_FAULTS_CHILDREN = "607263";
-        String MAJOR_FAULTS = "1";
-        String MAJOR_FAULTS_CHILDREN = "251";
-        final long USER_TIME_TICKS = 21;
-        final long KERNEL_TIME_TICKS = 7;
-        final long USER_TIME_CHILDREN = 10;
-        String KERNEL_TIME_CHILDREN = "1000";
-        String PRIORITY = "20";
-        String statString = "" +
-                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
-                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
-                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
-                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
-                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
-                KERNEL_TIME_CHILDREN + " " + PRIORITY;
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
-        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource);
-        ProcessStatusInfo stat = builder.build(PID);
-
-        verify(dataSource).getStatReader(PID);
-        assertNotNull(stat);
-        assertEquals(PID, stat.getPid());
-        assertEquals(USER_TIME_TICKS, stat.getUserTime());
-        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
-    }
-
-    @Test
-    public void testBadProcessName() throws IOException {
-        final int PID = 10363;
-        String PROCESS_NAME = "(secretly-bad process sleep 10 20 ) 6)";
-        String STATE = "S";
-        String PPID = "1737";
-        String PROCESS_GROUP_ID = "10363";
-        String SESSION_ID = "10363";
-        String TTY_NUMBER = "34817";
-        String TTY_PROCESS_GROUP_ID = "11404";
-        String FLAGS_WORD = "4202496";
-        String MINOR_FAULTS = "8093";
-        String MINOR_FAULTS_CHILDREN = "607263";
-        String MAJOR_FAULTS = "1";
-        String MAJOR_FAULTS_CHILDREN = "251";
-        final long USER_TIME_TICKS = 21;
-        final long KERNEL_TIME_TICKS = 7;
-        final long USER_TIME_CHILDREN = 10;
-        String KERNEL_TIME_CHILDREN = "1000";
-        String PRIORITY = "20";
-        String statString = "" +
-                PID + " " + PROCESS_NAME + " " + STATE + " " + PPID + " "
-                + PROCESS_GROUP_ID + " " + SESSION_ID + " " + TTY_NUMBER + " "
-                + TTY_PROCESS_GROUP_ID + " " + FLAGS_WORD + " " + MINOR_FAULTS + " "
-                + MINOR_FAULTS_CHILDREN + " " + MAJOR_FAULTS + " " + MAJOR_FAULTS_CHILDREN + " " +
-                USER_TIME_TICKS + " " + KERNEL_TIME_TICKS + " " + USER_TIME_CHILDREN + " " +
-                KERNEL_TIME_CHILDREN + " " + PRIORITY;
-
-        ProcDataSource dataSource = mock(ProcDataSource.class);
-        when(dataSource.getStatReader(any(Integer.class))).thenReturn(new StringReader(statString));
-        ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(dataSource);
-        ProcessStatusInfo stat = builder.build(PID);
-
-        verify(dataSource).getStatReader(PID);
-        assertNotNull(stat);
-        assertEquals(PID, stat.getPid());
-        assertEquals(USER_TIME_TICKS, stat.getUserTime());
-        assertEquals(KERNEL_TIME_TICKS, stat.getKernelTime());
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.assertTrue;
-
-import org.junit.Test;
-
-public class SysConfTest {
-
-    @Test
-    public void test() {
-        long ticksPerSecond = SysConf.getClockTicksPerSecond();
-        assertTrue(ticksPerSecond >= 1);
-    }
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class SystemBackendTest {
-
-    private SystemBackend b;
-
-    @Before
-    public void setUp() {
-        Storage s = mock(Storage.class);
-        CpuStatDAO cDAO = mock(CpuStatDAO.class);
-        HostInfoDAO hDAO = mock(HostInfoDAO.class);
-        MemoryStatDAO mDAO = mock(MemoryStatDAO.class);
-        VmCpuStatDAO vDAO = mock(VmCpuStatDAO.class);
-        NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class);
-        DAOFactory df = mock(DAOFactory.class);
-        when(df.getStorage()).thenReturn(s);
-        when(df.getCpuStatDAO()).thenReturn(cDAO);
-        when(df.getHostInfoDAO()).thenReturn(hDAO);
-        when(df.getMemoryStatDAO()).thenReturn(mDAO);
-        when(df.getVmCpuStatDAO()).thenReturn(vDAO);
-        when(df.getNetworkInterfaceInfoDAO()).thenReturn(nDAO);
-        b = new SystemBackend();
-        b.setDAOFactory(df);
-    }
-
-    @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 testCategoriesAreSane() {
-        Collection<Category> categories = b.getCategories();
-
-        assertTrue(categories.contains(CpuStatDAO.cpuStatCategory));
-        assertTrue(categories.contains(HostInfoDAO.hostInfoCategory));
-        assertTrue(categories.contains(MemoryStatDAO.memoryStatCategory));
-        assertTrue(categories.contains(NetworkInterfaceInfoDAO.networkInfoCategory));
-        assertTrue(categories.contains(VmClassStatDAO.vmClassStatsCategory));
-        assertTrue(categories.contains(VmCpuStatDAO.vmCpuStatCategory));
-        assertTrue(categories.contains(VmGcStatDAO.vmGcStatCategory));
-        assertTrue(categories.contains(VmInfoDAO.vmInfoCategory));
-        assertTrue(categories.contains(VmMemoryStatDAO.vmMemoryStatsCategory));
-    }
-
-}
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.Clock;
-import com.redhat.thermostat.common.model.VmCpuStat;
-
-public class VmCpuStatBuilderTest {
-
-    @Test
-    public void testBuilderKnowsNothing() {
-        Clock clock = mock(Clock.class);
-        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
-        int cpuCount = 0;
-        long ticksPerSecond = 0;
-        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
-
-        assertFalse(builder.knowsAbout(0));
-        assertFalse(builder.knowsAbout(1));
-        assertFalse(builder.knowsAbout(Integer.MIN_VALUE));
-        assertFalse(builder.knowsAbout(Integer.MAX_VALUE));
-
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testBuilderThrowsOnBuildOfUnknownPid() {
-        Clock clock = mock(Clock.class);
-        int cpuCount = 0;
-        long ticksPerSecond = 0;
-        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
-        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
-        builder.build(0);
-    }
-
-    @Test
-    public void testBuildNullOnInsufficentInformation() {
-        int PID = 0;
-        int cpuCount = 0;
-        long ticksPerSecond = 0;
-        final long CLOCK1 = 10000;
-        final long CLOCK2 = 20000;
-        final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, 1, 2);
-        final ProcessStatusInfo laterInfo = null;
-
-        Clock clock = mock(Clock.class);
-        when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6));
-
-        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
-        when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null);
-
-        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
-
-        builder.learnAbout(PID);
-        assertEquals(null, builder.build(PID));
-    }
-
-    @Test
-    public void testSaneBuild() {
-        final int PID = 0;
-
-        final int CPU_COUNT = 3;
-
-        final long USER_INITIAL_TICKS = 1;
-        final long KERNEL_INITIAL_TICKS = 1;
-
-        final long USER_LATER_TICKS = 10;
-        final long KERNEL_LATER_TICKS = 10;
-
-        final long CLOCK1 = 10000;
-        final long CLOCK2 = 20000;
-
-        final long TICKS_PER_SECOND = 100;
-
-        final double CPU_LOAD_PERCENT =
-                100.0
-                * ((USER_LATER_TICKS + KERNEL_LATER_TICKS) - (USER_INITIAL_TICKS + KERNEL_INITIAL_TICKS))
-                / TICKS_PER_SECOND
-                / ((CLOCK2 - CLOCK1) * 1E-3 /* millis to seconds */)
-                / CPU_COUNT;
-
-        final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, USER_INITIAL_TICKS, KERNEL_INITIAL_TICKS);
-        final ProcessStatusInfo laterInfo = new ProcessStatusInfo(PID, USER_LATER_TICKS, KERNEL_LATER_TICKS);
-
-        Clock clock = mock(Clock.class);
-        when(clock.getRealTimeMillis()).thenReturn(CLOCK2);
-        when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6));
-
-        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
-        when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null);
-
-        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, CPU_COUNT, TICKS_PER_SECOND, statusBuilder);
-
-        builder.learnAbout(PID);
-        VmCpuStat stat = builder.build(PID);
-
-        assertNotNull(stat);
-        assertEquals(PID, stat.getVmId());
-        assertEquals(CLOCK2, stat.getTimeStamp());
-        assertEquals(CPU_LOAD_PERCENT, stat.getCpuLoad(), 0.0001);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-client</artifactId>
+    <version>0.3-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-client-command</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat Command Channel Client</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-command</artifactId>
+      <version>${project.version}</version>
+      <type>bundle</type>
+    </dependency>
+    
+  </dependencies>
+
+  <build>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.client.command.AgentConfigurationActivator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.client.command
+            </Export-Package>
+            <Private-Package>
+            </Private-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/ConfigurationRequestContext.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.Bootstrap;
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+
+import com.redhat.thermostat.common.command.ConfigurationCommandContext;
+
+public class ConfigurationRequestContext extends ConfigurationCommandContext {
+
+    private final ClientBootstrap bootstrap;
+
+    ConfigurationRequestContext() {
+        this.bootstrap = createBootstrap();
+    }
+
+    @Override
+    public
+    Bootstrap getBootstrap() {
+        return bootstrap;
+    }
+
+    private ClientBootstrap createBootstrap() {
+        // Configure the client.
+        ClientBootstrap bootstrap = new ClientBootstrap(
+                new NioClientSocketChannelFactory(
+                        Executors.newCachedThreadPool(),
+                        Executors.newCachedThreadPool()));
+
+        // Set up the pipeline factory.
+        bootstrap.setPipelineFactory(new ClientPipelineFactory());
+
+        bootstrap.setOption("tcpNoDelay", true);
+        bootstrap.setOption("keepAlive", true);
+        bootstrap.setOption("reuseAddress", true);
+        bootstrap.setOption("connectTimeoutMillis", 100);
+        bootstrap.setOption("readWriteFair", true);
+        return bootstrap;
+    }
+
+    private class ClientPipelineFactory implements ChannelPipelineFactory {
+
+        @Override
+        public ChannelPipeline getPipeline() throws Exception {
+            ChannelPipeline pipeline = Channels.pipeline();
+            pipeline.addLast("decoder", new ResponseDecoder());
+            pipeline.addLast("encoder", new RequestEncoder());
+            return pipeline;
+        }
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/RequestEncoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import static org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+
+import com.redhat.thermostat.common.command.EncodingHelper;
+import com.redhat.thermostat.common.command.MessageEncoder;
+import com.redhat.thermostat.common.command.Request;
+
+
+class RequestEncoder extends MessageEncoder {
+
+    @Override
+    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
+
+        Request request = (Request) e.getMessage();
+
+        // Request Type
+        String requestType = EncodingHelper.trimType(request.getType().toString());
+        byte[] message = requestType.getBytes();
+        ChannelBuffer typeBuffer = EncodingHelper.encode(message);
+
+        // Compose the full message.
+        ChannelBuffer buf = wrappedBuffer(typeBuffer);
+        Channels.write(ctx, e.getFuture(), buf);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/RequestQueue.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelFuture;
+
+import com.redhat.thermostat.common.command.Request;
+
+class RequestQueue {
+
+    private final BlockingQueue<Request> queue;
+    private final ConfigurationRequestContext ctx;
+    private boolean processing;
+
+    RequestQueue(ConfigurationRequestContext ctx) {
+        processing = false;
+        this.ctx = ctx;
+        queue = new ArrayBlockingQueue<Request>(16, true);
+    }
+
+    void putRequest(Request request) {
+        queue.add(request);
+    }
+
+    void startProcessingRequests() {
+        if (!processing) {
+            processing = true;
+            new QueueRunner().start();
+        }
+    }
+
+    void stopProcessingRequests() {
+        processing = false;
+    }
+
+    private class QueueRunner extends Thread {
+
+        @Override
+        public void run() {
+            while (processing) {
+                Request request = null;
+                try {
+                    request = queue.take();
+                } catch (InterruptedException e) {
+                    if (Thread.interrupted()) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+                if (request == null) {
+                    break;
+                }
+                ChannelFuture f = ((ClientBootstrap) ctx.getBootstrap()).connect(request.getTarget());
+                f.awaitUninterruptibly();
+                Channel c = f.getChannel();
+                c.getPipeline().addLast("responseHandler", new ResponseHandler(request));
+                c.write(request);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/ResponseDecoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+
+import com.redhat.thermostat.common.command.DecodingHelper;
+import com.redhat.thermostat.common.command.MessageDecoder;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+
+class ResponseDecoder extends MessageDecoder {
+
+    @Override
+    protected Object decode(ChannelHandlerContext ctx, Channel channel,
+            ChannelBuffer buffer) {
+        String typeAsString = DecodingHelper.decodeString(buffer);
+        if (typeAsString == null) {
+            return null;
+        }
+        return new Response(ResponseType.valueOf(typeAsString));
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/ResponseHandler.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.logging.Logger;
+
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.command.Response;
+
+public class ResponseHandler extends SimpleChannelUpstreamHandler {
+
+    private static final Logger logger = Logger.getLogger(
+            ResponseHandler.class.getName());
+
+    private final Request request;
+
+    ResponseHandler(Request request) {
+        this.request = request;
+    }
+
+    @Override
+    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+        ctx.getPipeline().remove(this);
+        Response response = (Response) e.getMessage();
+        logger.info((response).getType().toString());
+        e.getChannel().close();
+        for (RequestResponseListener listener : request.getListeners()) {
+            listener.fireComplete(request, response);
+        }
+    }
+}
--- a/client/core/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/core/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -92,7 +92,7 @@
 
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- a/client/killvm/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/killvm/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -60,7 +60,7 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- a/client/living-vm-filter/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/living-vm-filter/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -64,7 +64,7 @@
 
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- a/client/memory-stats-panel/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/memory-stats-panel/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -65,7 +65,7 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- a/client/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -64,6 +64,7 @@
     <module>killvm</module>
     <module>memory-stats-panel</module>
     <module>living-vm-filter</module>
+    <module>command</module>
   </modules>
 
 </project>
--- a/client/vmclassstat/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/client/vmclassstat/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -64,7 +64,7 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-common</artifactId>
+    <version>0.3-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-common-command</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat Command Channel Common Library</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator></Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.common.command
+            </Export-Package>
+            <Private-Package>
+            </Private-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/ConfigurationCommandContext.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import java.net.InetSocketAddress;
+
+import org.jboss.netty.bootstrap.Bootstrap;
+
+public abstract class ConfigurationCommandContext {
+
+    private static final String HOST = "127.0.0.1";
+    private static final int PORT = 12000;
+
+    public abstract Bootstrap getBootstrap();
+
+    public InetSocketAddress getAddress() {
+        return new InetSocketAddress(HOST, PORT);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/DecodingHelper.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class DecodingHelper {
+
+    public static String decodeString(ChannelBuffer buffer) {
+        if (buffer.readableBytes() < 4) {
+            return null;
+        }
+        buffer.markReaderIndex();
+        int length = buffer.readInt();
+        if (buffer.readableBytes() < length) {
+            buffer.resetReaderIndex();
+            return null;
+        }
+        byte[] stringBytes = buffer.readBytes(length).array();
+        return new String(stringBytes);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/EncodingHelper.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import static org.jboss.netty.buffer.ChannelBuffers.buffer;
+
+public class EncodingHelper {
+
+    public static ChannelBuffer encode(byte[] message) {
+        ChannelBuffer buf = buffer(4 + message.length);
+        buf.writeInt(message.length);
+        buf.writeBytes(message);
+        return buf;
+    }
+
+    public static String trimType(String full) {
+        int typePointer = full.lastIndexOf('.');
+        return full.substring(typePointer + 1);
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/Message.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+
+interface Message {
+
+    interface MessageType {
+    }
+
+    MessageType getType();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/MessageDecoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+
+public abstract class MessageDecoder extends FrameDecoder {
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/MessageEncoder.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import org.jboss.netty.channel.SimpleChannelHandler;
+
+public abstract class MessageEncoder extends SimpleChannelHandler {
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/Request.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import java.net.SocketAddress;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+
+public class Request implements Message {
+
+    public enum RequestType implements MessageType {
+        PING;
+    }
+
+    private final RequestType type;
+    private final SocketAddress target;
+    private final Collection<RequestResponseListener> listeners;
+ 
+    public Request(RequestType type, SocketAddress target) {
+        this.type = type;
+        this.target = target;
+        listeners = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public MessageType getType() {
+        return type;
+    }
+
+    public SocketAddress getTarget() {
+        return target;
+    }
+
+    public void addListener(RequestResponseListener listener) {
+        listeners.add(listener);
+    }
+
+    public void removeListener(RequestResponseListener listener) {
+        listeners.remove(listener);
+    }
+
+    public Collection<RequestResponseListener> getListeners() {
+        return Collections.unmodifiableCollection(listeners);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/RequestResponseListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+public interface RequestResponseListener {
+
+    public void fireComplete(Request request, Response response);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/Response.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+
+
+
+public class Response implements Message {
+
+    public enum ResponseType implements MessageType {
+        PONG,
+        ERROR;
+    }
+
+    ResponseType type;
+
+    public Response (ResponseType type) {
+        this.type = type;
+    }
+
+    @Override
+    public ResponseType getType() {
+        return type;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/ConfigurationContextTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.InetSocketAddress;
+
+import org.jboss.netty.bootstrap.Bootstrap;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.command.ConfigurationCommandContext;
+
+public class ConfigurationContextTest {
+
+    @Test
+    public void testGetAddress() {
+        ConfigurationCommandContext ctx = new ConfigurationCommandContext() {
+
+            @Override
+            public Bootstrap getBootstrap() {
+                return null;
+            }
+            
+        };
+        InetSocketAddress addr = ctx.getAddress();
+        int port = addr.getPort();
+        String address = addr.getAddress().getHostAddress();
+
+        assertEquals(12000, port);
+        assertEquals("127.0.0.1", address);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/DecodingHelperTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import static org.junit.Assert.assertEquals;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.command.DecodingHelper;
+
+public class DecodingHelperTest {
+
+    @Test
+    public void testDecodeString() {
+        String original = "this is a test";
+        ChannelBuffer buf = ChannelBuffers.dynamicBuffer(4 + original.length());
+        buf.writeInt(original.length());
+        buf.writeBytes(original.getBytes());
+        String decoded = DecodingHelper.decodeString(buf);
+        assertEquals(original, decoded);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/EncodingHelperTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import static org.junit.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.command.EncodingHelper;
+
+public class EncodingHelperTest {
+
+    @Test
+    public void testEncode() {
+        byte[] input = "a test string".getBytes();
+        ChannelBuffer buf = EncodingHelper.encode(input);
+        int encodedMessageLength = buf.readInt();
+        assertEquals(input.length, encodedMessageLength);
+        ByteBuffer bbuf = ByteBuffer.allocate(buf.readableBytes());
+        buf.readBytes(bbuf);
+        byte[] output = bbuf.array();
+        assertEquals(input.length, output.length);
+        for (int i = 0; i < input.length; i++) {
+            assertEquals(input[i], output[i]);
+        }
+    }
+
+    @Test
+    public void testTrimType() {
+        String expected = "remaining";
+        String original = "this.is.going.to.be.trimmed.with.only.the.last." + expected;
+        String stripped = EncodingHelper.trimType(original);
+        assertEquals(expected, stripped);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/RequestTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetSocketAddress;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Request.RequestType;
+
+public class RequestTest {
+
+    private class RequestResponseListenerImpl implements RequestResponseListener {
+        @Override
+        public void fireComplete(Request request, Response response) {
+            // Won't actually be used.
+        }
+    }
+
+    private static final int PORT = 123;
+    private static final String HOST = "test.example.com";
+
+    @Test
+    public void testGetTypeAndTarget() {
+        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        RequestType type = (RequestType) request.getType();
+        assertEquals(RequestType.PING, type);
+
+        InetSocketAddress target = (InetSocketAddress) request.getTarget();
+        assertEquals(PORT, target.getPort());
+        assertEquals(HOST, target.getHostString());
+    }
+
+    @Test
+    public void testAddListener() {
+        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        RequestResponseListener listener1 = new RequestResponseListenerImpl();
+        RequestResponseListener listener2 = new RequestResponseListenerImpl();
+        request.addListener(listener1);
+        request.addListener(listener2);
+        Collection<RequestResponseListener> listeners = request.getListeners();
+        assertEquals(2, listeners.size());
+        assertTrue(listeners.contains(listener1));
+        assertTrue(listeners.contains(listener2));
+    }
+
+    @Test
+    public void testRemoveListener() {
+        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        RequestResponseListener listener1 = new RequestResponseListenerImpl();
+        RequestResponseListener listener2 = new RequestResponseListenerImpl();
+        request.addListener(listener1);
+        request.addListener(listener2);
+        Collection<RequestResponseListener> listeners = request.getListeners();
+        assertEquals(2, listeners.size());
+        assertTrue(listeners.contains(listener1));
+        assertTrue(listeners.contains(listener2));
+        request.removeListener(listener1);
+        listeners = request.getListeners();
+        assertEquals(1, listeners.size());
+        assertTrue(listeners.contains(listener2));
+        assertFalse(listeners.contains(listener1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/ResponseTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.command;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+
+public class ResponseTest {
+
+    @Test
+    public void testGetType() {
+        Response r = new Response(ResponseType.PONG);
+        assertEquals(ResponseType.PONG, r.getType());
+        r = new Response(ResponseType.ERROR);
+        assertEquals(ResponseType.ERROR, r.getType());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-common</artifactId>
+    <version>0.3-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>thermostat-common-core</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat Common Core</name>
+  <url>${project.parent.url}</url>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>1.4.0</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.common.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.common.cli,
+              com.redhat.thermostat.common.tools,
+              com.redhat.thermostat.common,
+              com.redhat.thermostat.common.appctx,
+              com.redhat.thermostat.common.config,
+              com.redhat.thermostat.common.dao,
+              com.redhat.thermostat.common.model,
+              com.redhat.thermostat.common.storage,
+              com.redhat.thermostat.common.utils,
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.test,
+              com.redhat.thermostat.tools,
+            </Private-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mongodb</groupId>
+      <artifactId>mongo-java-driver</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-cli</groupId>
+      <artifactId>commons-cli</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  
+  <properties>
+  	<argLine>-XX:-UseSplitVerifier</argLine>
+  </properties>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ActionEvent.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.EventObject;
+
+public class ActionEvent<T extends Enum<?>> extends EventObject {
+
+    private static final long serialVersionUID = -8648206929150142342L;
+
+    private Object payload;
+    
+    public ActionEvent(Object source, T actionId) {
+        super(source);
+        if (actionId == null) {
+            throw new NullPointerException();
+        }
+        this.actionId = actionId;
+    }
+
+    private T actionId;
+
+    public T getActionId() {
+        return actionId;
+    }
+
+    public Object getPayload() {
+        return payload;
+    }
+    
+    public void setPayload(Object payload) {
+        this.payload = payload;
+    }
+    
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + actionId.hashCode();
+        result = prime * result + source.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        @SuppressWarnings("rawtypes")
+        ActionEvent other = (ActionEvent) obj;
+        if (! actionId.equals(other.actionId)) {
+            return false;
+        }
+        if (! source.equals(other.source)) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ActionListener.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public interface ActionListener<T extends Enum<?>> {
+
+    void actionPerformed(ActionEvent<T> actionEvent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ActionNotifier.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.Collection;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class ActionNotifier<T extends Enum<?>> {
+
+    public ActionNotifier(Object source) {
+        this.source = source;
+        listeners = new CopyOnWriteArrayList<ActionListener<T>>();
+    }
+
+    private final Collection<ActionListener<T>> listeners;
+
+    private final Object source;
+
+    public void addActionListener(ActionListener<T> listener) {
+        listeners.add(listener);
+    }
+
+    public void removeActionListener(ActionListener<T> listener) {
+        listeners.remove(listener);
+    }
+
+    public void fireAction(T actionId) {
+        ActionEvent<T> action = new ActionEvent<>(source, actionId);
+        for (ActionListener<T> listener : listeners) {
+            listener.actionPerformed(action);
+        }
+    }
+
+    public void fireAction(T actionId, Object payload) {
+        ActionEvent<T> action = new ActionEvent<>(source, actionId);
+        action.setPayload(payload);
+        for (ActionListener<T> listener : listeners) {
+            listener.actionPerformed(action);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Activator.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.ServiceLoader;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandContextFactory;
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.CommandRegistryImpl;
+import com.redhat.thermostat.common.cli.Launcher;
+import com.redhat.thermostat.common.cli.LauncherImpl;
+
+public class Activator implements BundleActivator {
+
+    private ServiceRegistration launcherReg;
+    private CommandRegistry reg;
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        reg = new CommandRegistryImpl(context);
+        ServiceLoader<Command> cmds = ServiceLoader.load(Command.class, getClass().getClassLoader());
+        reg.registerCommands(cmds);
+
+        CommandContextFactory cmdCtxFactory = new CommandContextFactory(context);
+        Launcher launcher = new LauncherImpl(cmdCtxFactory);
+        launcherReg = context.registerService(Launcher.class.getName(), launcher, null);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        launcherReg.unregister();
+        reg.unregisterCommands();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Clock.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public interface Clock {
+
+    /**
+     * Returns the current real time in milliseconds (measured since the UNIX epoch).
+     */
+    long getRealTimeMillis();
+
+    /**
+     * Returns a time value corresponding to a monotonic clock measuring time
+     * in nanoseconds since some unspecified epoch.
+     */
+    long getMonotonicTimeNanos();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Constants.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+/**
+ * A grab bag of constants. This could be cleaned up later, but lets throw
+ * things here for now.
+ */
+public class Constants {
+
+    public static final int EXIT_UNKNOWN_ERROR = 1;
+    public static final int EXIT_UNABLE_TO_CONNECT_TO_DATABASE = 2;
+    public static final int EXIT_UNABLE_TO_READ_PROPERTIES = 3;
+    public static final int EXIT_CONFIGURATION_ERROR = 4;
+    public static final int EXIT_BACKEND_LOAD_ERROR = 5;
+    public static final int EXIT_BACKEND_START_ERROR = 6;
+
+    public static final int SAMPLING_INTERVAL_UNKNOWN = -1;
+
+    public static final String AGENT_ARGUMENT_LOCAL = "--local";
+    public static final String AGENT_ARGUMENT_LOGLEVEL = "--loglevel";
+    public static final String AGENT_ARGUMENT_DEVEL = "--devel";
+    public static final String AGENT_ARGUMENT_PROPERTIES = "--properties";
+
+    public static final String AGENT_PROPERTY_MONGOS_PORT = "mongos_port";
+    public static final String AGENT_PROPERTY_MONGOD_PORT = "mongod_port";
+    public static final String AGENT_PROPERTY_MONGO_LAUNCH_SCRIPT = "mongo_launch_script";
+    public static final String AGENT_PROPERTY_BACKENDS = "backends";
+    public static final String AGENT_PROPERTY_BACKEND_ACTIVE = "active";
+
+    public static final String CLIENT_PROPERTY_AGENT_LAUNCH_SCRIPT = "agent_launch_script";
+
+    public static final String AGENT_LOCAL_HOSTNAME = "localhost";
+
+    public static final long KILOBYTES_TO_BYTES = 1000;
+
+    public static final int HOST_INFO_NETWORK_IPV4_INDEX = 0;
+    public static final int HOST_INFO_NETWORK_IPV6_INDEX = 1;
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/LaunchException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+/**
+ * Exception that should be thrown when a condition is detected that prevents proper startup
+ * of program.
+ *
+ */
+public class LaunchException extends Exception {
+
+    private static final long serialVersionUID = -6757521147558143649L;
+
+    public LaunchException(String message) {
+        super(message);
+    }
+
+    public LaunchException(String message, Exception cause) {
+        super(message, cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/LogFormatter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.logging.Formatter;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+public class LogFormatter extends Formatter {
+
+    @Override
+    public synchronized String format(LogRecord record) {
+        StringBuilder sb = new StringBuilder();
+        Level level = record.getLevel();
+        if (level.intValue() >= Level.WARNING.intValue()) {
+            sb.append(level.toString() + " - ");
+        }
+        String[] fullLoggingClassName = record.getSourceClassName().split("\\.");
+        String loggingClassName = fullLoggingClassName[fullLoggingClassName.length - 1];
+        sb.append(loggingClassName);
+        sb.append(": ");
+        sb.append(record.getMessage());
+        sb.append("\n");
+        Throwable thrown = record.getThrown();
+        String indent = "  ";
+        while (thrown != null) {
+            sb.append(indent);
+            sb.append("Caused by:\n");
+            sb.append(indent);
+            sb.append(thrown.getClass().getCanonicalName());
+            sb.append(": ");
+            sb.append(thrown.getMessage());
+            sb.append("\n");
+            StackTraceElement[] stack = thrown.getStackTrace();
+            for (int i = 0; i < stack.length; i++) {
+                sb.append(indent);
+                sb.append(stack[i].toString());
+                sb.append("\n");
+            }
+            thrown = thrown.getCause();
+            indent = indent.concat("  ");
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/NotImplementedException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public class NotImplementedException extends RuntimeException {
+
+    private static final long serialVersionUID = -1620198443624195618L;
+
+    public NotImplementedException(String message) {
+        super(message);
+    }
+
+    public NotImplementedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/SystemClock.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public class SystemClock implements Clock {
+
+    @Override
+    public long getRealTimeMillis() {
+        return System.currentTimeMillis();
+    }
+
+    @Override
+    public long getMonotonicTimeNanos() {
+        return System.nanoTime();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ThreadPoolTimerFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+public class ThreadPoolTimerFactory implements TimerFactory {
+
+    public ThreadPoolTimerFactory(int poolSize) {
+        this(poolSize, Thread.currentThread().getThreadGroup());
+    }
+
+    ThreadPoolTimerFactory(int poolSize, final ThreadGroup group) {
+        timerThreadPool = Executors.newScheduledThreadPool(poolSize, new ThreadFactory() {
+            
+            @Override
+            public Thread newThread(Runnable r) {
+                return new Thread(group, r);
+            }
+        });
+    }
+
+    private class ThreadPoolTimer implements Timer {
+
+        private Runnable action;
+
+        private long delay;
+
+        private long period;
+
+        private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
+
+        private SchedulingType schedulingType = SchedulingType.ONCE;
+
+        private ScheduledFuture<?> timerTask;
+
+        @Override
+        public void start() {
+            if (action != null) {
+                startScheduling();
+            }          
+        }
+
+        private void startScheduling() {
+            switch (schedulingType) {
+            case FIXED_RATE:
+                timerTask = timerThreadPool.scheduleAtFixedRate(action, delay, period, timeUnit);
+                break;
+            case FIXED_DELAY:
+                timerTask = timerThreadPool.scheduleWithFixedDelay(action, delay, period, timeUnit);
+                break;
+            case ONCE:
+            default:
+                timerTask = timerThreadPool.schedule(action, delay, timeUnit);
+            }
+        }
+
+        @Override
+        public void stop() {
+            if (timerTask != null) {
+                timerTask.cancel(false);
+            }
+        }
+
+        @Override
+        public void setAction(Runnable action) {
+            this.action = action;
+        }
+
+        @Override
+        public void setInitialDelay(long delay) {
+            this.delay = delay;
+        }
+
+        @Override
+        public void setDelay(long period) {
+            this.period = period;
+        }
+
+        @Override
+        public void setSchedulingType(SchedulingType schedulingType) {
+            if (schedulingType == null) {
+                throw new NullPointerException();
+            }
+            this.schedulingType = schedulingType;
+        }
+
+        @Override
+        public void setTimeUnit(TimeUnit timeUnit) {
+            this.timeUnit = timeUnit;
+        }
+        
+    }
+
+    private ScheduledExecutorService timerThreadPool;
+
+    @Override
+    public Timer createTimer() {
+        return new ThreadPoolTimer();
+    }
+
+    @Override
+    public void shutdown() {
+        timerThreadPool.shutdown();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/Timer.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.util.concurrent.TimeUnit;
+
+public interface Timer {
+
+    enum SchedulingType {
+        ONCE, FIXED_RATE, FIXED_DELAY;
+    }
+
+    void start();
+    void stop();
+    void setAction(Runnable action);
+    void setInitialDelay(long initialDelay);
+    void setDelay(long period);
+    void setSchedulingType(SchedulingType schedulingType);
+    void setTimeUnit(TimeUnit timeUnit);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/TimerFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public interface TimerFactory {
+
+    Timer createTimer();
+
+    void shutdown();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/View.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+/**
+ * An object that is meant to be used as a View in an MVC setup.
+ *
+ * All implementations of this interface must have a no-arg public constructor
+ */
+public interface View {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ViewFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+public interface ViewFactory {
+
+    public <T extends View> T getView(Class<T> viewClass);
+
+    public <T extends View> Class<? extends T> getViewClass(Class<T> viewClass);
+
+    public <T extends View > void setViewClass(Class<T> viewClass, Class<? extends T> implClass);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.appctx;
+
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.ViewFactory;
+import com.redhat.thermostat.common.dao.DAOFactory;
+
+public class ApplicationContext {
+
+    private static ApplicationContext instance = new ApplicationContext();
+
+    private DAOFactory daoFactory;
+
+    private TimerFactory timerFactory;
+
+    private ViewFactory viewFactory;
+
+    public static ApplicationContext getInstance() {
+        return instance;
+    }
+
+    static void reset() {
+        instance = new ApplicationContext();
+    }
+
+    private ApplicationContext() {
+        // Nothing to do here, just prevent instantiation of this class outside
+        // the factory method.
+    }
+
+    public void setDAOFactory(DAOFactory daoFactory) {
+        this.daoFactory = daoFactory;
+    }
+
+    public DAOFactory getDAOFactory() {
+        return daoFactory;
+    }
+
+    public void setTimerFactory(TimerFactory timerFactory) {
+        this.timerFactory = timerFactory;
+    }
+
+    public TimerFactory getTimerFactory() {
+        return timerFactory;
+    }
+
+    public ViewFactory getViewFactory() {
+        return viewFactory;
+    }
+
+    public void setViewFactory(ViewFactory viewFactory) {
+        this.viewFactory = viewFactory;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContextUtil.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.appctx;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+
+public class ApplicationContextUtil {
+
+    /**
+     * This is here to allow tests to reset the ApplicationContext, while
+     * preventing real code the same (ApplicationContext.reset() is package private).
+     *
+     * It is vital that tests call this from their setUp() and tearDown() methods,
+     * to avoid leaking mocks and stuff from test to test.
+     */
+    public static void resetApplicationContext() {
+        ApplicationContext.reset();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/AppContextSetup.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+public interface AppContextSetup {
+
+    void setupAppContext(String dbUrl);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/AppContextSetupImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.MongoDAOFactory;
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.MongoStorageProvider;
+import com.redhat.thermostat.common.storage.StorageProvider;
+
+class AppContextSetupImpl implements AppContextSetup {
+
+    @Override
+    public void setupAppContext(String dbUrl) {
+        StartupConfiguration config = new ConnectionConfiguration(dbUrl);
+        
+        StorageProvider connProv = new MongoStorageProvider(config);
+        DAOFactory daoFactory = new MongoDAOFactory(connProv);
+        Connection connection = daoFactory.getConnection();
+        connection.connect();
+        ApplicationContext.getInstance().setDAOFactory(daoFactory);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/ArgumentSpec.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+public interface ArgumentSpec {
+
+    /**
+     * Return the name of the argument. This is used as the long option,
+     * e.g. a name of 'dbUrl' results in an option --dbUrl.
+     */
+    String getName();
+
+    /**
+     * Returns the short option version of the argument, e.g. 'd' results
+     * in an option -d.
+     */
+    String getShortOption();
+
+    boolean isRequired();
+
+    boolean isUsingAdditionalArgument();
+
+    String getDescription();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/Arguments.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.List;
+
+public interface Arguments {
+    List<String> getNonOptionArguments();
+    boolean hasArgument(String name);
+    String getArgument(String name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/BaseCommandRegistry.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.osgi.framework.ServiceRegistration;
+
+
+public abstract class BaseCommandRegistry implements CommandRegistry {
+
+    @Override
+    public Collection<ServiceRegistration> registerCommands(Iterable<? extends Command> cmds) {
+        Collection<ServiceRegistration> regs = new ArrayList<>();
+        for (Command cmd : cmds) {
+            regs.add(registerCommand(cmd));
+        }
+        return regs;
+    }
+
+    protected abstract ServiceRegistration registerCommand(Command cmd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/Command.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Collection;
+
+/**
+ * Represents a command on the command line.
+ * <p>
+ * To register a custom command, have a class implement this interface and
+ * register it as an OSGi service with the {@link #NAME} set to the value of
+ * {@link #getName()}.
+ */
+public interface Command {
+
+    static final String NAME = "COMMAND_NAME";
+
+    /**
+     * Execute the command
+     */
+    void run(CommandContext ctx) throws CommandException;
+
+    /**
+     * Called when the command is being removed from the system. The command
+     * should cancel any long-term action it has taken, such as any background
+     * tasks or threads it has spawned.
+     */
+    void disable();
+
+    /**
+     * Returns a name for this command. This will be used by the user to select
+     * this command.
+     */
+    String getName();
+
+    /**
+     * A short description for the command indicating what it does.
+     */
+    String getDescription();
+
+    /**
+     * How the user should invoke this command
+     */
+    String getUsage();
+
+    /**
+     * Returns a collection of arguments that the command is prepared to handle.
+     * If the user provides unknown or malformed arguments, this command will
+     * not be invoked.
+     */
+    Collection<ArgumentSpec> getAcceptedArguments();
+
+    boolean isStorageRequired();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContext.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+
+public interface CommandContext {
+
+    Console getConsole();
+
+    Arguments getArguments();
+
+    CommandRegistry getCommandRegistry();
+
+    AppContextSetup getAppContextSetup();
+
+    CommandContextFactory getCommandContextFactory();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContextFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import org.osgi.framework.BundleContext;
+
+public class CommandContextFactory {
+
+    private CommandRegistry commandRegistry;
+    private Console console = new SystemConsole();
+
+    private BundleContext bundleContext;
+
+    public CommandContextFactory(BundleContext ctx) {
+        commandRegistry = new CommandRegistryImpl(ctx);
+        bundleContext = ctx;
+    }
+
+    public CommandContext createContext(Arguments args) {
+        return new CommandContextImpl(args, this);
+    }
+
+    protected AppContextSetup getAppContextSetup() {
+        return new AppContextSetupImpl();
+    }
+
+    public CommandRegistry getCommandRegistry() {
+        return commandRegistry;
+    }
+
+    public Console getConsole() {
+        return console ;
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandContextImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+public class CommandContextImpl implements CommandContext {
+
+    private Arguments arguments;
+    private CommandContextFactory commandContextFactory;
+
+    public CommandContextImpl(Arguments args, CommandContextFactory ctxFactory) {
+        arguments = args;
+        commandContextFactory = ctxFactory;
+    }
+
+    @Override
+    public Console getConsole() {
+        return commandContextFactory.getConsole();
+    }
+
+    @Override
+    public Arguments getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public CommandRegistry getCommandRegistry() {
+        return commandContextFactory.getCommandRegistry();
+    }
+
+    @Override
+    public AppContextSetup getAppContextSetup() {
+        return commandContextFactory.getAppContextSetup();
+    }
+
+    @Override
+    public CommandContextFactory getCommandContextFactory() {
+        return commandContextFactory;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+public class CommandException extends Exception {
+
+    private static final long serialVersionUID = 3730368617641245016L;
+
+    public CommandException() {
+        super();
+    }
+
+    public CommandException(String message) {
+        super(message);
+    }
+
+    public CommandException(Throwable cause) {
+        super(cause);
+    }
+
+    public CommandException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+public class CommandLineArgumentParseException extends CommandException {
+
+    public CommandLineArgumentParseException() {
+        super();
+    }
+
+    public CommandLineArgumentParseException(String message) {
+        super(message);
+    }
+
+    public CommandLineArgumentParseException(Throwable cause) {
+        super(cause);
+    }
+
+    public CommandLineArgumentParseException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArguments.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+
+class CommandLineArguments implements Arguments {
+
+    private CommandLine cmdLine;
+
+    public CommandLineArguments(CommandLine commandLine) {
+        cmdLine = commandLine;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<String> getNonOptionArguments() {
+        return cmdLine.getArgList();
+    }
+
+    @Override
+    public boolean hasArgument(String name) {
+        return cmdLine.hasOption(name);
+    }
+
+    @Override
+    public String getArgument(String name) {
+        return cmdLine.getOptionValue(name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParser.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+public class CommandLineArgumentsParser {
+
+    private List<ArgumentSpec> arguments = new LinkedList<>();
+
+    void addArguments(Collection<ArgumentSpec> args) {
+        arguments.addAll(args);
+    }
+
+    Arguments parse(String[] args) throws CommandLineArgumentParseException {
+        try {
+            Options options = convertToCommonsCLIOptions(arguments);
+            CommandLineParser parser = new GnuParser();
+            CommandLine commandLine;
+            commandLine = parser.parse(options, args);
+            return new CommandLineArguments(commandLine);
+        } catch (MissingOptionException mae) {
+            String msg = createMissingOptionsMessage(mae);
+            throw new CommandLineArgumentParseException(msg.toString(), mae);
+        } catch (ParseException e) {
+            throw new CommandLineArgumentParseException(e.getMessage(), e);
+        }
+    }
+
+    private String createMissingOptionsMessage(MissingOptionException mae) {
+        @SuppressWarnings("unchecked")
+        List<String> missingOptions = mae.getMissingOptions();
+        StringBuilder msg = new StringBuilder();
+        if (missingOptions.size() == 1) {
+            msg.append("Missing required option: ");
+        } else {
+            msg.append("Missing required options: ");
+        }
+        for (Iterator<String> i = missingOptions.iterator(); i.hasNext();) {
+            String missingOption = i.next();
+            if (missingOption.length() > 1) {
+                msg.append("--");
+            } else {
+                msg.append("-");
+            }
+            msg.append(missingOption);
+            if (i.hasNext()) {
+                msg.append(", ");
+            }
+        }
+        return msg.toString();
+    }
+
+    private Options convertToCommonsCLIOptions(Collection<ArgumentSpec> args) {
+        Options options = new Options();
+        for (ArgumentSpec spec : args) {
+            options.addOption(convertSpecToOption(spec));
+        }
+        return options;
+    }
+
+    private Option convertSpecToOption(ArgumentSpec spec) {
+        String shortOpt = spec.getShortOption();
+        String longOpt = spec.getName();
+        Option option = new Option(shortOpt, longOpt, spec.isUsingAdditionalArgument(), spec.getDescription());
+        option.setRequired(spec.isRequired());
+        return option;
+    }
+
+    void printHelp(CommandContext ctx, Command cmd) {
+        HelpFormatter helpFormatter = new HelpFormatter();
+        PrintWriter pw = new PrintWriter(ctx.getConsole().getOutput());
+        CommonCommandOptions commonOpts = new CommonCommandOptions();
+        Collection<ArgumentSpec> acceptedOptions = commonOpts.getAcceptedOptionsFor(cmd);
+        Options options = convertToCommonsCLIOptions(acceptedOptions);
+        helpFormatter.printHelp(pw, 80, cmd.getName(), cmd.getUsage(), options, 2, 4, null, true);
+        pw.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistry.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Collection;
+
+import org.osgi.framework.ServiceRegistration;
+
+public interface CommandRegistry {
+
+    public abstract Collection<ServiceRegistration> registerCommands(Iterable<? extends Command> cmds);
+
+    public abstract void unregisterCommands();
+
+    public abstract Command getCommand(String name);
+
+    public abstract Collection<Command> getRegisteredCommands();
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+public class CommandRegistryImpl extends BaseCommandRegistry {
+
+    private static final Logger log = Logger.getLogger(CommandRegistryImpl.class.getName());
+
+    private BundleContext context;
+
+    private List<ServiceRegistration> ourRegistrations = new ArrayList<ServiceRegistration>();
+
+    public CommandRegistryImpl(BundleContext ctx) {
+        context = ctx;
+    }
+
+    protected ServiceRegistration registerCommand(Command cmd) {
+        Hashtable<String, String> props = new Hashtable<>();
+        props.put(Command.NAME, cmd.getName());
+        ServiceRegistration registration = context.registerService(Command.class.getName(), cmd, props);
+        ourRegistrations.add(registration);
+        return registration;
+    }
+
+    @Override
+    public void unregisterCommands() {
+        Iterator<ServiceRegistration> iter = ourRegistrations.iterator();
+        while (iter.hasNext()) {
+            ServiceRegistration registration = iter.next();
+            Object serviceObject =  context.getService(registration.getReference());
+            Command cmd = (Command) serviceObject;
+            cmd.disable();
+            registration.unregister();
+            iter.remove();
+        }
+    }
+
+    @Override
+    public Command getCommand(String name) {
+        ServiceReference[] refs = getCommandServiceRefs("(&(objectclass=*)(" + Command.NAME + "=" + name + "))");
+        if (refs == null || refs.length == 0) {
+            return null;
+        } else if (refs.length > 1) {
+            log.warning("More than one command implementation found for: " + name);
+        }
+        ServiceReference ref = refs[0];
+        return (Command) context.getService(ref);
+    }
+
+    @Override
+    public Collection<Command> getRegisteredCommands() {
+        ServiceReference[] refs = getCommandServiceRefs(null);
+        List<Command> cmds = new ArrayList<>();
+        for (ServiceReference ref : refs) {
+            Command cmd = (Command) context.getService(ref);
+            cmds.add(cmd);
+        }
+        return cmds;
+    }
+
+    private ServiceReference[] getCommandServiceRefs(String filter) {
+        ServiceReference[] refs;
+        try {
+            refs = context.getServiceReferences(Command.class.getName(), filter);
+        } catch (InvalidSyntaxException e) {
+            throw (InternalError) new InternalError().initCause(e);
+        }
+        return refs;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommonCommandOptions.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+class CommonCommandOptions {
+
+    static final String DB_URL_ARG = "dbUrl";
+    private static final String DB_URL_DESC = "the URL of the storage to connect to";
+
+    static final String LOG_LEVEL_ARG = "logLevel";
+    private static final String LOG_LEVEL_DESC = "log level";
+
+    Collection<ArgumentSpec> getAcceptedOptionsFor(Command cmd) {
+
+        Collection<ArgumentSpec> acceptedArguments = cmd.getAcceptedArguments();
+        acceptedArguments = new ArrayList<>(acceptedArguments);
+        addDbUrlOptionForStorageCommand(cmd, acceptedArguments);
+        addLogLevelOption(acceptedArguments);
+        return acceptedArguments;
+    }
+
+    private void addDbUrlOptionForStorageCommand(Command cmd, Collection<ArgumentSpec> acceptedArguments) {
+        if (cmd.isStorageRequired()) {
+            acceptedArguments.add(new SimpleArgumentSpec(DB_URL_ARG, "d", DB_URL_DESC, false, true));
+        }
+    }
+
+    private void addLogLevelOption(Collection<ArgumentSpec> acceptedArguments) {
+        acceptedArguments.add(new SimpleArgumentSpec(LOG_LEVEL_ARG, LOG_LEVEL_DESC, false, true));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/ConnectionConfiguration.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+class ConnectionConfiguration implements StartupConfiguration {
+
+    private String dbUrl;
+
+    ConnectionConfiguration(String dbUrl) {
+        this.dbUrl = dbUrl;
+    }
+
+    @Override
+    public String getDBConnectionString() {
+        return dbUrl;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/Console.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+
+public interface Console {
+
+    PrintStream getOutput();
+
+    PrintStream getError();
+
+    InputStream getInput();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class HelpCommand implements Command {
+
+    private static final int COMMANDS_COLUMNS_WIDTH = 15;
+    private static final String NAME = "help";
+    private static final String DESCRIPTION = "show help for a given command or help overview";
+    private static final String USAGE = DESCRIPTION;
+
+    @Override
+    public void run(CommandContext ctx) {
+        Arguments args = ctx.getArguments();
+        List<String> nonParsed = args.getNonOptionArguments();
+        if (nonParsed.isEmpty()) {
+            printCommandSummaries(ctx);
+        } else {
+            printCommandUsage(ctx, nonParsed.get(0));
+        }
+    }
+
+    private void printCommandSummaries(CommandContext ctx) {
+        CommandRegistry cmdRegistry = ctx.getCommandRegistry();
+
+        StringBuilder out = new StringBuilder();
+        out.append("list of commands:\n\n");
+
+        Collection<Command> commands = cmdRegistry.getRegisteredCommands();
+        for (Command cmd : commands) {
+            printCommandSummary(out, cmd);
+        }
+        ctx.getConsole().getOutput().print(out);
+    }
+
+    private void printCommandSummary(StringBuilder out, Command cmd) {
+        out.append(" ");
+        out.append(cmd.getName());
+        for (int i = 0; i < COMMANDS_COLUMNS_WIDTH - cmd.getName().length() - 1; i++) {
+            out.append(" ");
+        }
+        out.append(cmd.getDescription());
+        out.append("\n");
+    }
+
+    private void printCommandUsage(CommandContext ctx, String cmdName) {
+        Command cmd = ctx.getCommandRegistry().getCommand(cmdName);
+        if (cmd != null) {
+            CommandLineArgumentsParser cliParser = new CommandLineArgumentsParser();
+            cliParser.printHelp(ctx, cmd);
+        } else {
+            printCommandSummaries(ctx);
+        }
+    }
+
+    @Override
+    public void disable() { /* NO-OP */ }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return DESCRIPTION;
+    }
+
+    @Override
+    public String getUsage() {
+        return USAGE;
+    }
+
+    @Override
+    public Collection<ArgumentSpec> getAcceptedArguments() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean isStorageRequired() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/Launcher.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+/**
+ * Launcher is the main entry point for the command line "thermostat" program.
+ */
+public interface Launcher {
+
+    /**
+     * Invoked when thermostat starts
+     * @param command line arguments to the program
+     */
+    void run(String[] args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/LauncherImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.logging.Level;
+
+import org.osgi.framework.BundleException;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.storage.ConnectionException;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class LauncherImpl implements Launcher {
+
+    private static final String UNKNOWN_COMMAND_MESSAGE = "unknown command '%s'\n";
+
+    private ClientPreferences prefs = new ClientPreferences();
+
+    private String[] args;
+
+    private CommandContextFactory cmdCtxFactory;
+
+    private int usageCount = 0;
+
+    public LauncherImpl(CommandContextFactory cmdCtxFactory) {
+        this.cmdCtxFactory = cmdCtxFactory;
+    }
+
+    public void run(String[] args) {
+        usageCount++;
+        try {
+            initLogging();
+            this.args = args;
+            if (hasNoArguments()) {
+                runHelpCommand();
+            } else if (unknownCommand()) {
+                cmdCtxFactory.getConsole().getOutput().print(String.format(UNKNOWN_COMMAND_MESSAGE, args[0]));
+                runHelpCommand();
+            } else {
+                runCommandFromArguments();
+            }
+        } finally {
+            usageCount--;
+            shutdownIfLastLaunch();
+        }
+    }
+
+    private void shutdownIfLastLaunch() throws InternalError {
+        if (usageCount == 0) {
+            try {
+                ApplicationContext.getInstance().getTimerFactory().shutdown();
+                cmdCtxFactory.getBundleContext().getBundle(0).stop();
+            } catch (BundleException e) {
+                throw (InternalError) new InternalError().initCause(e);
+            }
+        }
+    }
+
+    void setPreferences(ClientPreferences prefs) {
+        this.prefs = prefs;
+    }
+
+    private void initLogging() {
+        try {
+            LoggingUtils.loadGlobalLoggingConfig();
+        } catch (InvalidConfigurationException e) {
+            System.err.println("WARNING: Could not read global Thermostat logging configuration.");
+        }
+        try {
+            LoggingUtils.loadUserLoggingConfig();
+        } catch (InvalidConfigurationException e) {
+            // We intentionally ignore this.
+        }
+    }
+
+    private boolean hasNoArguments() {
+        return args.length == 0;
+    }
+
+    private boolean unknownCommand() {
+        CommandRegistry registry = cmdCtxFactory.getCommandRegistry();
+        Command cmd = registry.getCommand(args[0]);
+        return cmd == null;
+    }
+
+    private void runHelpCommand() {
+        runCommand("help", new String[0]);
+    }
+
+    private void runCommandFromArguments() {
+        runCommand(args[0], Arrays.copyOfRange(args, 1, args.length));
+    }
+
+    private void runCommand(String cmdName, String[] cmdArgs) {
+        try {
+            parseArgsAndRunCommand(cmdName, cmdArgs);
+        } catch (CommandException e) {
+            cmdCtxFactory.getConsole().getError().println(e.getMessage());
+        }
+    }
+
+    private void parseArgsAndRunCommand(String cmdName, String[] cmdArgs) throws CommandException {
+
+        Command cmd = getCommand(cmdName);
+        if (cmd == null) {
+            throw new CommandException("Unknown command: " + cmdName);
+        }
+        CommonCommandOptions commonOpts = new CommonCommandOptions();
+        Collection<ArgumentSpec> acceptedOptions = commonOpts.getAcceptedOptionsFor(cmd);
+        Arguments args = parseCommandArguments(cmdArgs, acceptedOptions);
+        setupLogLevel(args);
+        CommandContext ctx = setupCommandContext(cmd, args);
+        cmd.run(ctx);
+    }
+
+    private void setupLogLevel(Arguments args) {
+        if (args.hasArgument(CommonCommandOptions.LOG_LEVEL_ARG)) {
+            String levelOption = args.getArgument(CommonCommandOptions.LOG_LEVEL_ARG);
+            setLogLevel(levelOption);
+        }
+    }
+
+    private void setLogLevel(String levelOption) {
+        try {
+            Level level = Level.parse(levelOption);
+            LoggingUtils.setGlobalLogLevel(level);
+        } catch (IllegalArgumentException ex) {
+            // Ignore this, use default loglevel.
+        }
+    }
+
+    private Command getCommand(String cmdName) {
+
+        CommandRegistry registry = cmdCtxFactory.getCommandRegistry();
+        Command cmd = registry.getCommand(cmdName);
+        return cmd;
+    }
+
+    private Arguments parseCommandArguments(String[] cmdArgs, Collection<ArgumentSpec> acceptedArguments)
+            throws CommandLineArgumentParseException {
+
+        CommandLineArgumentsParser cliArgsParser = new CommandLineArgumentsParser();
+        cliArgsParser.addArguments(acceptedArguments);
+        Arguments args = cliArgsParser.parse(cmdArgs);
+        return args;
+    }
+
+    private CommandContext setupCommandContext(Command cmd, Arguments args) throws CommandException {
+
+        CommandContext ctx = cmdCtxFactory.createContext(args);
+        if (cmd.isStorageRequired()) {
+            String dbUrl = ctx.getArguments().getArgument(CommonCommandOptions.DB_URL_ARG);
+            if (dbUrl == null) {
+                dbUrl = prefs.getConnectionUrl();
+            }
+            try {
+                ctx.getAppContextSetup().setupAppContext(dbUrl);
+            } catch (ConnectionException ex) {
+                throw new CommandException("Could not connect to: " + dbUrl, ex);
+            }
+        }
+        return ctx;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/SimpleArgumentSpec.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Objects;
+
+public class SimpleArgumentSpec implements ArgumentSpec {
+
+    private String name;
+    private String description;
+    private boolean required;
+    private boolean usingAddionalArgument;
+    private String shortOption;
+
+    public SimpleArgumentSpec() {
+        this(null, null);
+    }
+
+    public SimpleArgumentSpec(String name, String description) {
+        this(name, description, false, false);
+    }
+
+    public SimpleArgumentSpec(String name, String description, boolean required, boolean usingAdditionalArgument) {
+        this(name, null, description, required, usingAdditionalArgument);
+    }
+
+    public SimpleArgumentSpec(String name, String shortOption, String description, boolean required, boolean usingAdditionalArgument) {
+        this.name = name;
+        this.shortOption = shortOption;
+        this.description = description;
+        this.required = required;
+        this.usingAddionalArgument = usingAdditionalArgument;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getShortOption() {
+        return shortOption;
+    }
+
+    void setShortOption(String shortOption) {
+        this.shortOption = shortOption;
+    }
+
+    @Override
+    public boolean isRequired() {
+        return required;
+    }
+
+    public void setRequired(boolean required) {
+        this.required = required;
+    }
+
+    @Override
+    public boolean isUsingAdditionalArgument() {
+        return usingAddionalArgument;
+    }
+
+    public void setUsingAdditionalArgument(boolean usingAddionalArgument) {
+        this.usingAddionalArgument = usingAddionalArgument;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public boolean equals(Object o) {
+        if (! (o instanceof SimpleArgumentSpec)) {
+            return false;
+        }
+        SimpleArgumentSpec other = (SimpleArgumentSpec) o;
+        return Objects.equals(name, other.name)
+                && Objects.equals(description, other.description)
+                && usingAddionalArgument == other.usingAddionalArgument
+                && required == other.required
+                && Objects.equals(shortOption, other.shortOption);
+    }
+
+    public int hashCode() {
+        return Objects.hash(name, description, shortOption, usingAddionalArgument, required);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/SimpleArguments.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SimpleArguments implements Arguments {
+
+    private Map<String,String> arguments = new HashMap<>();
+
+    @Override
+    public boolean hasArgument(String name) {
+        return arguments.containsKey(name);
+    }
+
+    @Override
+    public String getArgument(String name) {
+        return arguments.get(name);
+    }
+
+    public void addArgument(String name, String value) {
+        arguments.put(name, value);
+        
+    }
+
+    @Override
+    public List<String> getNonOptionArguments() {
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/SystemConsole.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+
+class SystemConsole implements Console {
+
+    @Override
+    public PrintStream getOutput() {
+        return System.out;
+    }
+
+    @Override
+    public PrintStream getError() {
+        return System.err;
+    }
+
+    @Override
+    public InputStream getInput() {
+        return System.in;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+public class ClientPreferences {
+
+    private static final String CONNECTION_URL = "connection-url";
+
+    private final Preferences prefs;
+
+    public ClientPreferences() {
+        this(Preferences.userRoot().node("thermostat"));
+    }
+
+    ClientPreferences(Preferences prefs) {
+        this.prefs = prefs;
+    }
+
+    public String getConnectionUrl() {
+        return prefs.get(CONNECTION_URL, "mongodb://127.0.0.1:27518");
+    }
+
+    public void setConnectionUrl(String url) {
+        prefs.put(CONNECTION_URL, url);
+    }
+
+    public void flush() throws BackingStoreException {
+        prefs.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/ConfigUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+import java.io.File;
+
+public class ConfigUtils {
+
+    private static final String THERMOSTAT_USER_DIR = ".thermostat";
+
+    public static String getThermostatHome() throws InvalidConfigurationException {
+        // allow this to be specified also as a property, especially for
+        // tests, this overrides the env setting
+        String home = System.getProperty("THERMOSTAT_HOME");
+        if (home == null) {
+            home = System.getenv("THERMOSTAT_HOME");
+        }
+        
+        if (home == null) {
+            throw new InvalidConfigurationException("THERMOSTAT_HOME not defined...");
+        }
+        return home;
+    }
+
+    public static String getThermostatUserHome() {
+        String home = System.getProperty("user.home");
+        return home + File.separator + THERMOSTAT_USER_DIR;
+    }
+
+    public static File getBackendsBaseDirectory() throws InvalidConfigurationException {
+        String loc = getThermostatHome() + File.separatorChar + "backends";
+        File file = new File(loc);
+        return file;
+    }
+    
+    public static File getStorageBaseDirectory() throws InvalidConfigurationException {
+        String loc = getThermostatHome() + File.separatorChar + "storage";
+        File file = new File(loc);
+        return file;
+    }
+    
+    public static File getStorageDirectory() throws InvalidConfigurationException {
+        return new File(getStorageBaseDirectory(), "db");
+    }
+    
+    public static File getStorageConfigurationFile() throws InvalidConfigurationException {
+        return new File(getStorageBaseDirectory(), "db.properties");
+    }
+
+    public static File getStorageLogFile() throws InvalidConfigurationException {
+        File logDir = new File(getStorageBaseDirectory(), "logs");
+        File logFile = new File(logDir, "db.log");
+        
+        return logFile;
+    }
+
+    public static File getStoragePidFile() throws InvalidConfigurationException {
+        File logDir = new File(getStorageBaseDirectory(), "run");
+        File logFile = new File(logDir, "db.pid");
+        
+        return logFile;
+    }
+
+    public static File getBackendPropertyFile(String backendName)
+            throws InvalidConfigurationException
+    {
+        File backendsConfigDir = ConfigUtils.getBackendsBaseDirectory();
+        File backendConfig = new File(backendsConfigDir, backendName);
+        backendConfig = new File(backendConfig, "backend.properties");
+        return backendConfig;
+    }
+
+    public static File getAgentConfigurationFile() throws InvalidConfigurationException {
+
+        File agent = new File(getThermostatHome(), "agent");
+        return new File(agent, "agent.properties");
+    }
+
+    public static File getClientConfigurationDirectory() throws InvalidConfigurationException {
+        File client = new File(getThermostatHome(), "client");
+        return client;
+    }
+
+    public static File getHistoryFile() throws InvalidConfigurationException {
+        File history = new File(getClientConfigurationDirectory(), "cli-history");
+        return history;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/Defaults.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+import java.util.logging.Level;
+
+final class Defaults {
+
+	private Defaults() {
+	    /* Should not be instantiated */
+	}
+
+    public static final Level LOGGING_LEVEL = Level.WARNING;
+    public static final String DATABASE_URI = "mongodb://127.0.0.1";
+    public static final int MONGOS_PORT = 27517;
+    public static final int MONGOD_PORT = 27518;
+    public static final boolean LOCAL_MODE = false; // Default behaviour is to connect to cluster.
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+
+public class InvalidConfigurationException extends Exception {
+
+    private static final long serialVersionUID = -6555406006758264587L;
+
+    public InvalidConfigurationException() {
+        super();
+    }
+    
+    public InvalidConfigurationException(String message) {
+        super(message);
+    }
+    
+    public InvalidConfigurationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+    
+    public InvalidConfigurationException(Throwable cause) {
+        super(cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/StartupConfiguration.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+public interface StartupConfiguration {
+
+    String getDBConnectionString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/ThermostatOptionParser.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+public interface ThermostatOptionParser {
+    void parse() throws InvalidConfigurationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/Converter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.Pojo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+interface Converter<T extends Pojo> {
+
+    Chunk toChunk(T pojo);
+
+    T fromChunk(Chunk chunk);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/Countable.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+interface Countable {
+
+    public long getCount();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class CpuStatConverter implements Converter<CpuStat> {
+
+    @Override
+    public Chunk toChunk(CpuStat cpuStat) {
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, cpuStat.getTimeStamp());
+        chunk.put(CpuStatDAO.cpu5LoadKey, cpuStat.getLoad5());
+        chunk.put(CpuStatDAO.cpu10LoadKey, cpuStat.getLoad10());
+        chunk.put(CpuStatDAO.cpu15LoadKey, cpuStat.getLoad15());
+        return chunk;
+    }
+
+    @Override
+    public CpuStat fromChunk(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        double load5 = chunk.get(CpuStatDAO.cpu5LoadKey);
+        double load10 = chunk.get(CpuStatDAO.cpu10LoadKey);
+        double load15 = chunk.get(CpuStatDAO.cpu15LoadKey);
+        return new CpuStat(timestamp, load5, load10, load15);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface CpuStatDAO extends Countable {
+
+    static Key<Double> cpu5LoadKey = new Key<>("5load", false);
+    static Key<Double> cpu10LoadKey = new Key<>("10load", false);
+    static Key<Double> cpu15LoadKey = new Key<>("15load", false);
+
+    static final Category cpuStatCategory = new Category("cpu-stats",
+            Key.AGENT_ID, Key.TIMESTAMP, cpu5LoadKey, cpu10LoadKey, cpu15LoadKey);
+
+    List<CpuStat> getLatestCpuStats(HostRef ref);
+
+    void putCpuStat(CpuStat stat);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Storage;
+
+class CpuStatDAOImpl implements CpuStatDAO {
+
+    private Storage storage;
+
+    private Converter<CpuStat> converter = new CpuStatConverter();;
+
+    private Map<HostRef, HostLatestPojoListGetter<CpuStat>> getters = new HashMap<>();
+
+    CpuStatDAOImpl(Storage storage) {
+        this.storage = storage;
+    }
+
+    @Override
+    public List<CpuStat> getLatestCpuStats(HostRef ref) {
+        HostLatestPojoListGetter<CpuStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new HostLatestPojoListGetter<CpuStat>(storage, cpuStatCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+
+    @Override
+    public void putCpuStat(CpuStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+
+    @Override
+    public long getCount() {
+        return storage.getCount(cpuStatCategory);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+public class DAOException extends RuntimeException {
+
+    public DAOException() {
+        super();
+    }
+
+    public DAOException(String message) {
+        super(message);
+    }
+
+    public DAOException(Throwable cause) {
+        super(cause);
+    }
+
+    public DAOException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Storage;
+
+public interface DAOFactory {
+
+    // TODO this is temporary until DAO is made for those that are still using Storage directly.
+    public Storage getStorage();
+
+    public Connection getConnection();
+
+    public HostInfoDAO getHostInfoDAO();
+
+    public CpuStatDAO getCpuStatDAO();
+
+    public MemoryStatDAO getMemoryStatDAO();
+
+    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO();
+
+    public VmInfoDAO getVmInfoDAO();
+
+    public VmCpuStatDAO getVmCpuStatDAO();
+
+    public VmMemoryStatDAO getVmMemoryStatDAO();
+
+    public VmClassStatDAO getVmClassStatsDAO();
+
+    public VmGcStatDAO getVmGcStatDAO();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+public class HostInfoConverter implements Converter<HostInfo> {
+
+    @Override
+    public Chunk toChunk(HostInfo hostInfo) {
+        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        chunk.put(HostInfoDAO.hostNameKey, hostInfo.getHostname());
+        chunk.put(HostInfoDAO.osNameKey, hostInfo.getOsName());
+        chunk.put(HostInfoDAO.osKernelKey, hostInfo.getOsKernel());
+        chunk.put(HostInfoDAO.cpuModelKey, hostInfo.getCpuModel());
+        chunk.put(HostInfoDAO.cpuCountKey, hostInfo.getCpuCount());
+        chunk.put(HostInfoDAO.hostMemoryTotalKey, hostInfo.getTotalMemory());
+        return chunk;
+    }
+
+    @Override
+    public HostInfo fromChunk(Chunk chunk) {
+        String hostName = chunk.get(HostInfoDAO.hostNameKey);
+        String osName = chunk.get(HostInfoDAO.osNameKey);
+        String osKernel = chunk.get(HostInfoDAO.osKernelKey);
+        String cpuModel = chunk.get(HostInfoDAO.cpuModelKey);
+        int cpuCount = chunk.get(HostInfoDAO.cpuCountKey);
+        long totalMemory = chunk.get(HostInfoDAO.hostMemoryTotalKey);
+        return new HostInfo(hostName, osName, osKernel, cpuModel, cpuCount, totalMemory);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.Collection;
+
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface HostInfoDAO extends Countable {
+
+    static Key<String> hostNameKey = new Key<>("hostname", true);
+    static Key<String> osNameKey = new Key<>("os_name", false);
+    static Key<String> osKernelKey = new Key<>("os_kernel", false);
+    static Key<Integer> cpuCountKey = new Key<>("cpu_num", false);
+    static Key<String> cpuModelKey = new Key<>("cpu_model", false);
+    static Key<Long> hostMemoryTotalKey = new Key<>("memory_total", false);
+
+    static final Category hostInfoCategory = new Category("host-info",
+            Key.AGENT_ID, hostNameKey, osNameKey, osKernelKey,
+            cpuCountKey, cpuModelKey, hostMemoryTotalKey);
+
+    HostInfo getHostInfo(HostRef ref);
+
+    void putHostInfo(HostInfo info);
+
+    Collection<HostRef> getHosts();
+    Collection<HostRef> getAliveHosts();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.storage.AgentInformation;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class HostInfoDAOImpl implements HostInfoDAO {
+    private Storage storage;
+    private HostInfoConverter converter;
+
+    public HostInfoDAOImpl(Storage storage) {
+        this.storage = storage;
+        converter = new HostInfoConverter();
+    }
+
+    @Override
+    public HostInfo getHostInfo(HostRef ref) {
+        Chunk query = new Chunk(hostInfoCategory, false);
+        query.put(Key.AGENT_ID, ref.getAgentId());
+        Chunk result = storage.find(query);
+        return result == null ? null : converter.fromChunk(result);
+    }
+
+    @Override
+    public void putHostInfo(HostInfo info) {
+        storage.putChunk(converter.toChunk(info));
+    }
+    
+    @Override
+    public Collection<HostRef> getHosts() {
+        return getHosts(new Chunk(hostInfoCategory, false));
+    }
+    
+    private Collection<HostRef> getHosts(Chunk filter) {
+        Collection<HostRef> hosts = new ArrayList<HostRef>();
+        
+        Cursor hostsCursor = storage.findAll(filter);
+        while(hostsCursor.hasNext()) {
+            Chunk hostChunk = hostsCursor.next();
+            String agentId = hostChunk.get(Key.AGENT_ID);
+            String hostName = hostChunk.get(hostNameKey);
+            hosts.add(new HostRef(agentId, hostName));
+        }
+        return hosts;
+    }
+    
+    @Override
+    public Collection<HostRef> getAliveHosts() {
+        
+        Collection<HostRef> hosts = new ArrayList<HostRef>();
+        
+        Chunk agents = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
+        agents.put(AgentInformation.AGENT_ALIVE_KEY, true);
+        Cursor agentCursor = storage.findAll(agents);
+        while(agentCursor.hasNext()) {
+            Chunk chunk = agentCursor.next();
+            
+            Chunk filter = new Chunk(hostInfoCategory, false);
+            filter.put(Key.AGENT_ID, chunk.get(Key.AGENT_ID));
+            
+            hosts.addAll(getHosts(filter));
+        }
+        
+        return hosts;
+    }
+    @Override
+    public long getCount() {
+        return storage.getCount(hostInfoCategory);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.TimeStampedPojo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class HostLatestPojoListGetter<T extends TimeStampedPojo> implements LatestPojoListGetter<T> {
+
+    private Storage storage;
+    private Category cat;
+    private Converter<T> converter;
+    private HostRef ref;
+
+    private Map<HostRef, Long> lastUpdateTimes = new HashMap<>();
+
+    HostLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, HostRef ref) {
+        this.storage = storage;
+        this.cat = cat;
+        this.converter = converter;
+        this.ref = ref;
+    }
+
+    @Override
+    public List<T> getLatest() {
+        Chunk query = buildQuery();
+        return getLatest(query);
+    }
+
+    private List<T> getLatest(Chunk query) {
+        // TODO if multiple threads will be using this utility class, there may be some issues
+        // with the updateTimes
+        Long lastUpdate = lastUpdateTimes.get(ref);
+        Cursor cursor = storage.findAll(query);
+        List<T> result = new ArrayList<>();
+        while (cursor.hasNext()) {
+            Chunk chunk = cursor.next();
+            T pojo = converter.fromChunk(chunk);
+            result.add(pojo);
+            lastUpdateTimes.put(ref, Math.max(pojo.getTimeStamp(), lastUpdate));
+        }
+        return result;
+    }
+
+    protected Chunk buildQuery() {
+        Chunk query = new Chunk(cat, false);
+        query.put(Key.AGENT_ID, ref.getAgentId());
+        Long lastUpdate = lastUpdateTimes.get(ref);
+        if (lastUpdate != null) {
+            // TODO once we have an index and the 'column' is of type long, use
+            // a query which can utilize an index. this one doesn't
+            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+        } else {
+            lastUpdateTimes.put(ref, Long.MIN_VALUE);
+        }
+        return query;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostRef.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+public class HostRef implements Ref {
+
+    private final String uid;
+    private final String name;
+
+    public HostRef(String id, String name) {
+        this.uid = id;
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public String getAgentId() {
+        return uid;
+    }
+
+    public String getHostName() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != this.getClass()) {
+            return false;
+        }
+        HostRef other = (HostRef) obj;
+        if (equals(this.uid, other.uid) && equals(this.name, other.name)) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean equals(Object obj1, Object obj2) {
+        return (obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2));
+    }
+
+    @Override
+    public int hashCode() {
+        return uid.hashCode();
+    }
+
+    @Override
+    public String getStringID() {
+        return getAgentId();
+    }
+    
+    @Override
+    public String getName() {
+        return getHostName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.Pojo;
+
+interface LatestPojoListGetter<T extends Pojo> {
+    List<T> getLatest();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class MemoryStatConverter implements Converter<MemoryStat> {
+
+    @Override
+    public Chunk toChunk(MemoryStat mem) {
+        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
+        chunk.put(Key.TIMESTAMP, mem.getTimeStamp());
+        chunk.put(MemoryStatDAO.memoryTotalKey, mem.getTotal());
+        chunk.put(MemoryStatDAO.memoryFreeKey, mem.getFree());
+        chunk.put(MemoryStatDAO.memoryBuffersKey, mem.getBuffers());
+        chunk.put(MemoryStatDAO.memoryCachedKey, mem.getCached());
+        chunk.put(MemoryStatDAO.memorySwapTotalKey, mem.getSwapTotal());
+        chunk.put(MemoryStatDAO.memorySwapFreeKey, mem.getSwapFree());
+        chunk.put(MemoryStatDAO.memoryCommitLimitKey, mem.getCommitLimit());
+        return chunk;
+    }
+
+    @Override
+    public MemoryStat fromChunk(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        long total = chunk.get(MemoryStatDAO.memoryTotalKey);
+        long free = chunk.get(MemoryStatDAO.memoryFreeKey);
+        long buffers = chunk.get(MemoryStatDAO.memoryBuffersKey);
+        long cached = chunk.get(MemoryStatDAO.memoryCachedKey);
+        long swapTotal = chunk.get(MemoryStatDAO.memorySwapTotalKey);
+        long swapFree = chunk.get(MemoryStatDAO.memorySwapFreeKey);
+        long commitLimit = chunk.get(MemoryStatDAO.memoryCommitLimitKey);
+
+        return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface MemoryStatDAO extends Countable {
+
+    static Key<Long> memoryTotalKey = new Key<>("total", false);
+    static Key<Long> memoryFreeKey = new Key<>("free", false);
+    static Key<Long> memoryBuffersKey = new Key<>("buffers", false);
+    static Key<Long> memoryCachedKey = new Key<>("cached", false);
+    static Key<Long> memorySwapTotalKey = new Key<>("swap-total", false);
+    static Key<Long> memorySwapFreeKey = new Key<>("swap-free", false);
+    static Key<Long> memoryCommitLimitKey = new Key<>("commit-limit", false);
+
+    static final Category memoryStatCategory = new Category("memory-stats",
+            Key.AGENT_ID, Key.TIMESTAMP, memoryTotalKey, memoryFreeKey, memoryBuffersKey,
+            memoryCachedKey, memorySwapTotalKey, memorySwapFreeKey, memoryCommitLimitKey);
+
+    public List<MemoryStat> getLatestMemoryStats(HostRef ref);
+
+    void putMemoryStat(MemoryStat stat);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.storage.Storage;
+
+class MemoryStatDAOImpl implements MemoryStatDAO {
+
+    private Storage storage;
+
+    private Converter<MemoryStat> converter = new MemoryStatConverter();
+
+    private Map<HostRef, HostLatestPojoListGetter<MemoryStat>> getters = new HashMap<>();
+
+    MemoryStatDAOImpl(Storage storage) {
+        this.storage = storage;
+    }
+
+    @Override
+    public List<MemoryStat> getLatestMemoryStats(HostRef ref) {
+        HostLatestPojoListGetter<MemoryStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new HostLatestPojoListGetter<MemoryStat>(storage, memoryStatCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+
+    @Override
+    public void putMemoryStat(MemoryStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+
+    @Override
+    public long getCount() {
+        return storage.getCount(memoryStatCategory);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.StorageProvider;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class MongoDAOFactory implements DAOFactory {
+
+    private final Storage storage;
+
+    public MongoDAOFactory(StorageProvider prov) {
+        storage = prov.createStorage();
+    }
+
+    @Override
+    public Connection getConnection() {
+        return storage.getConnection();
+    }
+
+    @Override
+    public HostInfoDAO getHostInfoDAO() {
+        ensureStorageConnected();
+        return new HostInfoDAOImpl(storage);
+    }
+
+    @Override
+    public CpuStatDAO getCpuStatDAO() {
+        ensureStorageConnected();
+        return new CpuStatDAOImpl(storage);
+    }
+
+    @Override
+    public MemoryStatDAO getMemoryStatDAO() {
+        ensureStorageConnected();
+        return new MemoryStatDAOImpl(storage);
+    }
+
+    @Override
+    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO() {
+        ensureStorageConnected();
+        return new NetworkInterfaceInfoDAOImpl(storage);
+    }
+
+    @Override
+    public VmInfoDAO getVmInfoDAO() {
+        ensureStorageConnected();
+        return new VmInfoDAOImpl(storage);
+    }
+
+    @Override
+    public VmCpuStatDAO getVmCpuStatDAO() {
+        ensureStorageConnected();
+        return new VmCpuStatDAOImpl(storage);
+    }
+
+    public VmMemoryStatDAO getVmMemoryStatDAO() {
+        ensureStorageConnected();
+        return new VmMemoryStatDAOImpl(storage);
+    }
+
+    @Override
+    public VmClassStatDAO getVmClassStatsDAO() {
+        ensureStorageConnected();
+        return new VmClassStatDAOImpl(storage);
+    }
+
+    @Override
+    public VmGcStatDAO getVmGcStatDAO() {
+        ensureStorageConnected();
+        return new VmGcStatDAOImpl(storage);
+    }
+
+    @Override
+    public Storage getStorage() {
+        return storage;
+    }
+
+    private void ensureStorageConnected() {
+        if (!storage.getConnection().isConnected()) {
+            throw new IllegalStateException("Set up connection before accessing DAO");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+public class NetworkInterfaceInfoConverter implements Converter<NetworkInterfaceInfo> {
+
+    @Override
+    public Chunk toChunk(NetworkInterfaceInfo info) {
+        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, true);
+        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, info.getInterfaceName());
+        String ip4 = info.getIp4Addr();
+        if (ip4 != null) {
+            chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, ip4);
+        }
+        String ip6 = info.getIp6Addr();
+        if (ip6 != null) {
+            chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, ip6);
+        }
+        return chunk;
+    }
+
+    @Override
+    public NetworkInterfaceInfo fromChunk(Chunk chunk) {
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo(chunk.get(NetworkInterfaceInfoDAO.ifaceKey));
+        info.setIp4Addr(chunk.get(NetworkInterfaceInfoDAO.ip4AddrKey));
+        info.setIp6Addr(chunk.get(NetworkInterfaceInfoDAO.ip6AddrKey));
+        return info;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface NetworkInterfaceInfoDAO {
+
+    static Key<String> ifaceKey = new Key<>("iface", true);
+    static Key<String> ip4AddrKey = new Key<>("ipv4addr", false);
+    static Key<String> ip6AddrKey = new Key<>("ipv6addr", false);
+
+    static final Category networkInfoCategory = new Category("network-info",
+            Key.AGENT_ID, Key.TIMESTAMP, ifaceKey, ip4AddrKey, ip6AddrKey);
+
+    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref);
+
+    public void putNetworkInterfaceInfo(NetworkInterfaceInfo info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO {
+
+    private Storage storage;
+    private NetworkInterfaceInfoConverter converter;
+
+    NetworkInterfaceInfoDAOImpl(Storage storage) {
+        this.storage = storage;
+        converter = new NetworkInterfaceInfoConverter();
+    }
+
+    @Override
+    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref) {
+        Chunk query = new Chunk(networkInfoCategory, false);
+        query.put(Key.AGENT_ID, ref.getAgentId());
+
+        Cursor cursor = storage.findAll(query);
+        List<NetworkInterfaceInfo> result = new ArrayList<>();
+        while (cursor.hasNext()) {
+            Chunk chunk = cursor.next();
+            NetworkInterfaceInfo stat = converter.fromChunk(chunk);
+            result.add(stat);
+        }
+        return result;
+    }
+
+    @Override
+    public void putNetworkInterfaceInfo(NetworkInterfaceInfo info) {
+        storage.putChunk(converter.toChunk(info));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/Ref.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+public interface Ref {
+
+    String getStringID();
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmClassStatConverter implements Converter<VmClassStat> {
+
+    @Override
+    public Chunk toChunk(VmClassStat vmClassStat) {
+        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
+        chunk.put(Key.VM_ID, vmClassStat.getVmId());
+        chunk.put(Key.TIMESTAMP, vmClassStat.getTimeStamp());
+        chunk.put(VmClassStatDAO.loadedClassesKey, vmClassStat.getLoadedClasses());
+        return chunk;
+    }
+
+    @Override
+    public VmClassStat fromChunk(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        long loadedClasses = chunk.get(VmClassStatDAO.loadedClassesKey);
+        int vmId = chunk.get(Key.VM_ID);
+        return new VmClassStat(vmId, timestamp, loadedClasses);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface VmClassStatDAO {
+
+    static final Key<Long> loadedClassesKey = new Key<>("loadedClasses", false);
+
+    static final Category vmClassStatsCategory = new Category(
+            "vm-class-stats", Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, loadedClassesKey);
+
+    public List<VmClassStat> getLatestClassStats(VmRef ref);
+
+    public void putVmClassStat(VmClassStat stat);
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmClassStatDAOImpl implements VmClassStatDAO {
+
+    private Storage storage;
+
+    private Converter<VmClassStat> converter = new VmClassStatConverter();
+
+    private Map<VmRef, VmLatestPojoListGetter<VmClassStat>> getters = new HashMap<>();
+
+    VmClassStatDAOImpl(Storage storage) {
+        this.storage = storage;
+    }
+
+    @Override
+    public List<VmClassStat> getLatestClassStats(VmRef ref) {
+        VmLatestPojoListGetter<VmClassStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmClassStat>(storage, vmClassStatsCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+
+    @Override
+    public void putVmClassStat(VmClassStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmCpuStatConverter implements Converter<VmCpuStat> {
+
+    @Override
+    public Chunk toChunk(VmCpuStat vmCpuStat) {
+        Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, vmCpuStat.getTimeStamp());
+        chunk.put(Key.VM_ID, vmCpuStat.getVmId());
+        chunk.put(VmCpuStatDAO.vmCpuLoadKey, vmCpuStat.getCpuLoad());
+        return chunk;
+    }
+
+    @Override
+    public VmCpuStat fromChunk(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        int vmId = chunk.get(Key.VM_ID);
+        double processorUsage = chunk.get(VmCpuStatDAO.vmCpuLoadKey);
+        return new VmCpuStat(timestamp, vmId, processorUsage);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface VmCpuStatDAO {
+
+    static final Key<Double> vmCpuLoadKey = new Key<>("processor-usage", false);
+
+    static final Category vmCpuStatCategory = new Category("vm-cpu-stats",
+            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, vmCpuLoadKey);
+
+    public abstract List<VmCpuStat> getLatestVmCpuStats(VmRef ref);
+
+    public abstract void putVmCpuStat(VmCpuStat stat);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmCpuStatDAOImpl implements VmCpuStatDAO {
+
+    private final Storage storage;
+
+    private Converter<VmCpuStat> converter = new VmCpuStatConverter();
+
+    private Map<VmRef, VmLatestPojoListGetter<VmCpuStat>> getters = new HashMap<>();
+
+    VmCpuStatDAOImpl(Storage storage) {
+        this.storage = storage;
+    }
+
+    @Override
+    public List<VmCpuStat> getLatestVmCpuStats(VmRef ref) {
+        VmLatestPojoListGetter<VmCpuStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmCpuStat>(storage, vmCpuStatCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+
+    @Override
+    public void putVmCpuStat(VmCpuStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmGcStatConverter implements Converter<VmGcStat> {
+
+    @Override
+    public Chunk toChunk(VmGcStat vmGcStat) {
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
+
+        chunk.put(Key.VM_ID, vmGcStat.getVmId());
+        chunk.put(Key.TIMESTAMP, vmGcStat.getTimeStamp());
+        chunk.put(VmGcStatDAO.collectorKey, vmGcStat.getCollectorName());
+        chunk.put(VmGcStatDAO.runCountKey, vmGcStat.getRunCount());
+        chunk.put(VmGcStatDAO.wallTimeKey, vmGcStat.getWallTime());
+
+        return chunk;
+    }
+
+    @Override
+    public VmGcStat fromChunk(Chunk chunk) {
+        int vmId = chunk.get(Key.VM_ID);
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        String collectorName = chunk.get(VmGcStatDAO.collectorKey);
+        long runCount = chunk.get(VmGcStatDAO.runCountKey);
+        long wallTime = chunk.get(VmGcStatDAO.wallTimeKey);
+
+        return new VmGcStat(vmId, timestamp, collectorName, runCount, wallTime);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface VmGcStatDAO {
+
+    static final Key<String> collectorKey = new Key<>("collector", false);
+    static final Key<Long> runCountKey = new Key<>("runtime-count", false);
+    /** time in microseconds */
+    static final Key<Long> wallTimeKey = new Key<>("wall-time", false);
+
+    static final Category vmGcStatCategory = new Category("vm-gc-stats",
+            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, collectorKey,
+            runCountKey, wallTimeKey);
+
+    public List<VmGcStat> getLatestVmGcStats(VmRef ref);
+
+    public void putVmGcStat(VmGcStat stat);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmGcStatDAOImpl implements VmGcStatDAO {
+
+    private Storage storage;
+
+    private Converter<VmGcStat> converter = new VmGcStatConverter();
+
+    private Map<VmRef, VmLatestPojoListGetter<VmGcStat>> getters = new HashMap<>();
+
+    VmGcStatDAOImpl(Storage storage) {
+        this.storage = storage;
+    }
+
+    @Override
+    public List<VmGcStat> getLatestVmGcStats(VmRef ref) {
+        VmLatestPojoListGetter<VmGcStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmGcStat>(storage, vmGcStatCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+
+    @Override
+    public void putVmGcStat(VmGcStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+public class VmInfoConverter implements Converter<VmInfo> {
+
+    @Override
+    public Chunk toChunk(VmInfo info) {
+        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
+
+        chunk.put(VmInfoDAO.vmIdKey, info.getVmId());
+        chunk.put(VmInfoDAO.vmPidKey, info.getVmPid());
+        chunk.put(VmInfoDAO.startTimeKey, info.getStartTimeStamp());
+        chunk.put(VmInfoDAO.stopTimeKey, info.getStopTimeStamp());
+        chunk.put(VmInfoDAO.runtimeVersionKey, info.getJavaVersion());
+        chunk.put(VmInfoDAO.javaHomeKey, info.getJavaHome());
+        chunk.put(VmInfoDAO.mainClassKey, info.getMainClass());
+        chunk.put(VmInfoDAO.commandLineKey, info.getJavaCommandLine());
+        chunk.put(VmInfoDAO.vmNameKey, info.getVmName());
+        chunk.put(VmInfoDAO.vmInfoKey, info.getVmInfo());
+        chunk.put(VmInfoDAO.vmVersionKey, info.getVmVersion());
+        chunk.put(VmInfoDAO.vmArgumentsKey, info.getVmArguments());
+        chunk.put(VmInfoDAO.propertiesKey, info.getProperties());
+        chunk.put(VmInfoDAO.environmentKey, info.getEnvironment());
+        chunk.put(VmInfoDAO.librariesKey, info.getLoadedNativeLibraries());
+        return chunk;
+    }
+
+    @Override
+    public VmInfo fromChunk(Chunk chunk) {
+        int vmId = chunk.get(VmInfoDAO.vmIdKey);
+        long startTime = chunk.get(VmInfoDAO.startTimeKey);
+        long stopTime = chunk.get(VmInfoDAO.stopTimeKey);
+        String jVersion = chunk.get(VmInfoDAO.runtimeVersionKey);
+        String jHome = chunk.get(VmInfoDAO.javaHomeKey);
+        String mainClass = chunk.get(VmInfoDAO.mainClassKey);
+        String commandLine = chunk.get(VmInfoDAO.commandLineKey);
+        String vmName = chunk.get(VmInfoDAO.vmNameKey);
+        String vmInfo = chunk.get(VmInfoDAO.vmInfoKey);
+        String vmVersion = chunk.get(VmInfoDAO.vmVersionKey);
+        String vmArgs = chunk.get(VmInfoDAO.vmArgumentsKey);
+        Map<String, String> props = chunk.get(VmInfoDAO.propertiesKey);
+        Map<String, String> env = chunk.get(VmInfoDAO.propertiesKey);
+        List<String> libs = chunk.get(VmInfoDAO.librariesKey);
+        return new VmInfo(vmId, startTime, stopTime, jVersion, jHome, mainClass, commandLine, vmName,
+                vmInfo, vmVersion, vmArgs, props, env, libs);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface VmInfoDAO extends Countable {
+
+    static final Key<Integer> vmIdKey = new Key<>("vm-id", true);
+    static final Key<Integer> vmPidKey = new Key<>("vm-pid", false);
+    static final Key<String> runtimeVersionKey = new Key<>("runtime-version", false);
+    static final Key<String> javaHomeKey = new Key<>("java-home", false);
+    static final Key<String> mainClassKey = new Key<>("main-class", false);
+    static final Key<String> commandLineKey = new Key<>("command-line", false);
+    static final Key<String> vmArgumentsKey = new Key<>("vm-arguments", false);
+    static final Key<String> vmNameKey = new Key<>("vm-name", false);
+    static final Key<String> vmInfoKey = new Key<>("vm-info", false);
+    static final Key<String> vmVersionKey = new Key<>("vm-version", false);
+    static final Key<Map<String, String>> propertiesKey = new Key<>("properties", false);
+    static final Key<Map<String, String>> environmentKey = new Key<>("environment", false);
+    static final Key<List<String>> librariesKey = new Key<>("libraries", false);
+    static final Key<Long> startTimeKey = new Key<>("start-time", false);
+    static final Key<Long> stopTimeKey = new Key<>("stop-time", false);
+
+    static final Category vmInfoCategory = new Category("vm-info",
+            Key.AGENT_ID, vmIdKey, vmPidKey, runtimeVersionKey, javaHomeKey,
+            mainClassKey, commandLineKey,
+            vmArgumentsKey, vmNameKey, vmInfoKey, vmVersionKey,
+            propertiesKey, environmentKey, librariesKey,
+            startTimeKey, stopTimeKey);
+
+    public VmInfo getVmInfo(VmRef ref);
+
+    Collection<VmRef> getVMs(HostRef host);
+
+    public void putVmInfo(VmInfo info);
+
+    public void putVmStoppedTime(int vmId, long timestamp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmInfoDAOImpl implements VmInfoDAO {
+
+    private Storage storage;
+    private VmInfoConverter converter;
+
+    VmInfoDAOImpl(Storage storage) {
+        this.storage = storage;
+        this.converter = new VmInfoConverter();
+    }
+
+    @Override
+    public VmInfo getVmInfo(VmRef ref) {
+        Chunk query = new Chunk(vmInfoCategory, false);
+        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
+        query.put(vmIdKey, ref.getId());
+        Chunk result = storage.find(query);
+        if (result == null) {
+            throw new DAOException("Unknown VM: host:" + ref.getAgent().getAgentId() + ";vm:" + ref.getId());
+        }
+        return converter.fromChunk(result);
+    }
+
+    @Override
+    public Collection<VmRef> getVMs(HostRef host) {
+
+        Chunk query = buildQuery(host);
+        Cursor cursor = storage.findAll(query);
+        return buildVMsFromQuery(cursor, host);
+    }
+
+    private Chunk buildQuery(HostRef host) {
+        Chunk query = new Chunk(vmInfoCategory, false);
+        query.put(Key.AGENT_ID, host.getAgentId());
+        return query;
+    }
+
+    private Collection<VmRef> buildVMsFromQuery(Cursor cursor, HostRef host) {
+        List<VmRef> vmRefs = new ArrayList<VmRef>();
+        while (cursor.hasNext()) {
+            Chunk vmChunk = cursor.next();
+            VmRef vm = buildVmRefFromChunk(vmChunk, host);
+            vmRefs.add(vm);
+        }
+
+        return vmRefs;
+    }
+
+    private VmRef buildVmRefFromChunk(Chunk vmChunk, HostRef host) {
+        Integer id = vmChunk.get(vmIdKey);
+        // TODO can we do better than the main class?
+        String mainClass = vmChunk.get(mainClassKey);
+        VmRef ref = new VmRef(host, id, mainClass);
+        return ref;
+    }
+
+    @Override
+    public long getCount() {
+        return storage.getCount(vmInfoCategory);
+    }
+
+    @Override
+    public void putVmInfo(VmInfo info) {
+        storage.putChunk(converter.toChunk(info));
+    }
+
+    @Override
+    public void putVmStoppedTime(int vmId, long timestamp) {
+        storage.updateChunk(makeStoppedChunk(vmId, timestamp));
+    }
+
+    private Chunk makeStoppedChunk(int vmId, long stopTimeStamp) {
+        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, false);
+        chunk.put(VmInfoDAO.vmIdKey, vmId);
+        chunk.put(VmInfoDAO.stopTimeKey, stopTimeStamp);
+        return chunk;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import com.redhat.thermostat.common.model.TimeStampedPojo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmLatestPojoListGetter<T extends TimeStampedPojo> extends HostLatestPojoListGetter<T> {
+
+    private VmRef vmRef;
+
+    VmLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, VmRef ref) {
+        super(storage, cat, converter, ref.getAgent());
+        vmRef = ref;
+    }
+
+    @Override
+    protected Chunk buildQuery() {
+        Chunk query = super.buildQuery();
+        query.put(Key.VM_ID, vmRef.getId());
+        return query;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmMemoryStatConverter implements Converter<VmMemoryStat> {
+
+    @Override
+    public Chunk toChunk(VmMemoryStat vmMemStat) {
+        Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
+
+        chunk.put(Key.VM_ID, vmMemStat.getVmId());
+        chunk.put(Key.TIMESTAMP, vmMemStat.getTimeStamp());
+
+        Generation newGen = vmMemStat.getGeneration("new");
+
+        Space eden = newGen.getSpace("eden");
+        chunk.put(VmMemoryStatDAO.edenGenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.edenCollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.edenCapacityKey, eden.capacity);
+        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, eden.maxCapacity);
+        chunk.put(VmMemoryStatDAO.edenUsedKey, eden.used);
+
+        Space s0 = newGen.getSpace("s0");
+        chunk.put(VmMemoryStatDAO.s0GenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.s0CollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.s0CapacityKey, s0.capacity);
+        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, s0.maxCapacity);
+        chunk.put(VmMemoryStatDAO.s0UsedKey, s0.used);
+
+        Space s1 = newGen.getSpace("s1");
+        chunk.put(VmMemoryStatDAO.s1GenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.s1CollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.s1CapacityKey, s1.capacity);
+        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, s1.maxCapacity);
+        chunk.put(VmMemoryStatDAO.s1UsedKey, s1.used);
+
+        Generation oldGen = vmMemStat.getGeneration("old");
+
+        Space old = oldGen.getSpace("old");
+        chunk.put(VmMemoryStatDAO.oldGenKey, oldGen.name);
+        chunk.put(VmMemoryStatDAO.oldCollectorKey, oldGen.collector);
+        chunk.put(VmMemoryStatDAO.oldCapacityKey, old.capacity);
+        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, old.maxCapacity);
+        chunk.put(VmMemoryStatDAO.oldUsedKey, old.used);
+
+        Generation permGen = vmMemStat.getGeneration("perm");
+
+        Space perm = permGen.getSpace("perm");
+        chunk.put(VmMemoryStatDAO.permGenKey, permGen.name);
+        chunk.put(VmMemoryStatDAO.permCollectorKey, permGen.collector);
+        chunk.put(VmMemoryStatDAO.permCapacityKey, perm.capacity);
+        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, perm.maxCapacity);
+        chunk.put(VmMemoryStatDAO.permUsedKey, perm.used);
+
+        return chunk;
+    }
+
+    @Override
+    public VmMemoryStat fromChunk(Chunk chunk) {
+        Space space = null;
+        List<Space> spaces = null;
+
+        List<Generation> gens = new ArrayList<>();
+        Generation newGen = new Generation();
+        spaces = new ArrayList<>();
+        newGen.spaces = spaces;
+        newGen.name = "new";
+        newGen.capacity = 0;
+        newGen.maxCapacity = 0;
+        // FIXME Something is wrong here when we have the collector stored
+        // as part of 3 spaces in Chunk but is only one thing in Stat
+        newGen.collector = chunk.get(VmMemoryStatDAO.edenCollectorKey);
+
+        space = new Space();
+        space.name = VmMemoryStatDAO.edenKey.getName();
+        space.capacity = chunk.get(VmMemoryStatDAO.edenCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.edenMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.edenUsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
+
+        space = new Space();
+        space.name = VmMemoryStatDAO.s0Key.getName();
+        space.capacity = chunk.get(VmMemoryStatDAO.s0CapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.s0MaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.s0UsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
+
+        space = new Space();
+        space.name = VmMemoryStatDAO.s1Key.getName();
+        space.capacity = chunk.get(VmMemoryStatDAO.s1CapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.s1MaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.s1UsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
+
+        gens.add(newGen);
+
+        Generation oldGen = new Generation();
+        spaces = new ArrayList<>();
+        oldGen.spaces = spaces;
+        oldGen.name = "old";
+        oldGen.collector = chunk.get(VmMemoryStatDAO.oldCollectorKey);
+
+        space = new Space();
+        space.name = VmMemoryStatDAO.oldKey.getName();
+        space.capacity = chunk.get(VmMemoryStatDAO.oldCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.oldMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.oldUsedKey);
+        spaces.add(space);
+        oldGen.capacity = space.capacity;
+        oldGen.maxCapacity = space.capacity;
+
+        gens.add(oldGen);
+
+        Generation permGen = new Generation();
+        spaces = new ArrayList<>();
+        permGen.spaces = spaces;
+        permGen.name = "perm";
+        permGen.collector = chunk.get(VmMemoryStatDAO.permCollectorKey);
+
+        space = new Space();
+        space.name = VmMemoryStatDAO.permKey.getName();
+        space.capacity = chunk.get(VmMemoryStatDAO.permCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.permMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.permUsedKey);
+        spaces.add(space);
+        permGen.capacity = space.capacity;
+        permGen.maxCapacity = space.capacity;
+
+        gens.add(permGen);
+
+        return new VmMemoryStat(chunk.get(Key.TIMESTAMP), chunk.get(Key.VM_ID), gens);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Key;
+
+public interface VmMemoryStatDAO {
+
+    static final Key<String> edenKey = new Key<>("eden", false);
+    static final Key<String> edenGenKey = new Key<>("eden.gen", false);
+    static final Key<String> edenCollectorKey = new Key<>("eden.collector", false);
+    static final Key<Long> edenCapacityKey = new Key<>("eden.capacity", false);
+    static final Key<Long> edenMaxCapacityKey = new Key<>("eden.max-capacity", false);
+    static final Key<Long> edenUsedKey = new Key<>("eden.used", false);
+
+    static final Key<String> s0Key = new Key<>("s0", false);
+    static final Key<String> s0GenKey = new Key<>("s0.gen", false);
+    static final Key<String> s0CollectorKey = new Key<>("s0.collector", false);
+    static final Key<Long> s0CapacityKey = new Key<>("s0.capacity", false);
+    static final Key<Long> s0MaxCapacityKey = new Key<>("s0.max-capacity", false);
+    static final Key<Long> s0UsedKey = new Key<>("s0.used", false);
+
+    static final Key<String> s1Key = new Key<>("s1", false);
+    static final Key<String> s1GenKey = new Key<>("s1.gen", false);
+    static final Key<String> s1CollectorKey = new Key<>("s1.collector", false);
+    static final Key<Long> s1CapacityKey = new Key<>("s1.capacity", false);
+    static final Key<Long> s1MaxCapacityKey = new Key<>("s1.max-capacity", false);
+    static final Key<Long> s1UsedKey = new Key<>("s1.used", false);
+
+    static final Key<String> oldKey = new Key<>("old", false);
+    static final Key<String> oldGenKey = new Key<>("old.gen", false);
+    static final Key<String> oldCollectorKey = new Key<>("old.collector", false);
+    static final Key<Long> oldCapacityKey = new Key<>("old.capacity", false);
+    static final Key<Long> oldMaxCapacityKey = new Key<>("old.max-capacity", false);
+    static final Key<Long> oldUsedKey = new Key<>("old.used", false);
+
+    static final Key<String> permKey = new Key<>("perm", false);
+    static final Key<String> permGenKey = new Key<>("perm.gen", false);
+    static final Key<String> permCollectorKey = new Key<>("perm.collector", false);
+    static final Key<Long> permCapacityKey = new Key<>("perm.capacity", false);
+    static final Key<Long> permMaxCapacityKey = new Key<>("perm.max-capacity", false);
+    static final Key<Long> permUsedKey = new Key<>("perm.used", false);
+
+    static final Category vmMemoryStatsCategory = new Category("vm-memory-stats",
+            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP,
+            edenGenKey, edenCollectorKey,
+            edenCapacityKey, edenMaxCapacityKey,edenUsedKey,
+            s0GenKey, s0CollectorKey, s0CapacityKey,
+            s0MaxCapacityKey, s0UsedKey,
+            s1GenKey, s1CollectorKey, s1CapacityKey,
+            s1MaxCapacityKey, s1UsedKey,
+            oldGenKey, oldCollectorKey, oldCapacityKey,
+            oldMaxCapacityKey, oldUsedKey,
+            permGenKey, permCollectorKey, permCapacityKey,
+            permMaxCapacityKey, permUsedKey);
+
+    public VmMemoryStat getLatestMemoryStat(VmRef ref);
+
+    public List<VmMemoryStat> getLatestVmMemoryStats(VmRef vm);
+
+    public void putVmMemoryStat(VmMemoryStat stat);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmMemoryStatDAOImpl implements VmMemoryStatDAO {
+
+    private final Storage storage;
+    private final VmMemoryStatConverter converter;
+
+    private Map<VmRef, VmLatestPojoListGetter<VmMemoryStat>> getters = new HashMap<>();
+
+    VmMemoryStatDAOImpl(Storage storage) {
+        this.storage = storage;
+        converter = new VmMemoryStatConverter();
+    }
+
+    @Override
+    public VmMemoryStat getLatestMemoryStat(VmRef ref) {
+        Chunk query = new Chunk(vmMemoryStatsCategory, false);
+        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
+        query.put(Key.VM_ID, ref.getId());
+        Cursor cursor = storage.findAll(query).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1);
+        if (cursor.hasNext()) {
+            return converter.fromChunk(cursor.next());
+        }
+        return null;
+    }
+
+    @Override
+    public void putVmMemoryStat(VmMemoryStat stat) {
+        storage.putChunk(converter.toChunk(stat));
+    }
+
+    @Override
+    public List<VmMemoryStat> getLatestVmMemoryStats(VmRef ref) {
+        VmLatestPojoListGetter<VmMemoryStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmMemoryStat>(storage, vmMemoryStatsCategory, converter, ref);
+            getters.put(ref, getter);
+        }
+        return getter.getLatest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmRef.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+public class VmRef implements Ref {
+
+    private final HostRef hostRef;
+    private final Integer uid;
+    private final String uidString;
+    private final String name;
+
+    public VmRef(HostRef hostRef, Integer id, String name) {
+        this.hostRef = hostRef;
+        this.uid = id;
+        this.uidString = id.toString();
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public HostRef getAgent() {
+        return hostRef;
+    }
+
+    public Integer getId() {
+        return uid;
+    }
+
+    public String getIdString() {
+        return uidString;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj.getClass() != this.getClass()) {
+            return false;
+        }
+        VmRef other = (VmRef) obj;
+        if (equals(this.hostRef, other.hostRef) && equals(this.uid, other.uid) && equals(this.name, other.name)) {
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean equals(Object obj1, Object obj2) {
+        return (obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2));
+    }
+
+    @Override
+    public int hashCode() {
+        return uid.hashCode();
+    }
+
+    @Override
+    public String getStringID() {
+        return getIdString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/CpuStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class CpuStat implements TimeStampedPojo {
+
+    public static final double INVALID_LOAD = Double.MIN_VALUE;
+
+    private final double load5;
+    private final double load10;
+    private final double load15;
+    private final long timeStamp;
+
+    public CpuStat(long timestamp, double load5, double load10, double load15) {
+        this.timeStamp = timestamp;
+        this.load5 = load5;
+        this.load10 = load10;
+        this.load15 = load15;
+    }
+
+    public double getLoad5() {
+        return load5;
+    }
+
+    public double getLoad10() {
+        return load10;
+    }
+
+    public double getLoad15() {
+        return load15;
+    }
+
+    public double[] getLoad() {
+        return new double[] { load5, load10, load15 };
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timeStamp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/DiscreteTimeData.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+/**
+ * Represents a data associated with a discrete point in time
+ *
+ * @param <T> the type data associated with this point in time
+ */
+public class DiscreteTimeData<T> {
+
+    private long millis;
+    private T data;
+
+    public DiscreteTimeData(long millis, T data) {
+        this.millis = millis;
+        this.data = data;
+    }
+
+    public long getTimeInMillis() {
+        return millis;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/HostInfo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class HostInfo implements Pojo {
+
+    private final String hostname;
+    private final String osName;
+    private final String osKernel;
+    private final String cpuModel;
+    private final int cpuCount;
+    private final long totalMemory;
+
+    public HostInfo(String hostname, String osName, String osKernel, String cpuModel, int cpuCount, long totalMemory) {
+        this.hostname = hostname;
+        this.osName = osName;
+        this.osKernel = osKernel;
+        this.cpuModel = cpuModel;
+        this.cpuCount = cpuCount;
+        this.totalMemory = totalMemory;
+    }
+
+    public String getHostname() {
+        return hostname;
+    }
+
+    public String getOsName() {
+        return osName;
+    }
+
+    public String getOsKernel() {
+        return osKernel;
+    }
+
+    public String getCpuModel() {
+        return cpuModel;
+    }
+
+    public int getCpuCount() {
+        return cpuCount;
+    }
+
+    /**
+     * Total memory in bytes
+     */
+    public long getTotalMemory() {
+        return totalMemory;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/IntervalTimeData.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class IntervalTimeData<T> {
+
+    private long start;
+    private long end;
+    private T data;
+
+    public IntervalTimeData(long start, long end, T data) {
+        this.start = start;
+        this.end = end;
+        this.data = data;
+    }
+
+    public long getStartTimeInMillis() {
+        return start;
+    }
+
+    public long getEndTimeInMillis() {
+        return end;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class MemoryStat implements TimeStampedPojo {
+    private final long timestamp;
+    private final long total;
+    private final long free;
+    private final long buffers;
+    private final long cached;
+    private final long swapTotal;
+    private final long swapFree;
+    private final long commitLimit;
+
+    public MemoryStat(long timestamp, long total, long free, long buffers, long cached, long swapTotal, long swapFree, long commitLimit) {
+        this.timestamp = timestamp;
+        this.total = total;
+        this.free = free;
+        this.buffers = buffers;
+        this.cached = cached;
+        this.swapTotal = swapTotal;
+        this.swapFree = swapFree;
+        this.commitLimit = commitLimit;
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timestamp;
+    }
+
+    public long getTotal() {
+        return total;
+    }
+
+    public long getFree() {
+        return free;
+    }
+
+    public long getBuffers() {
+        return buffers;
+    }
+
+    public long getCached() {
+        return cached;
+    }
+
+    public long getSwapTotal() {
+        return swapTotal;
+    }
+
+    public long getSwapFree() {
+        return swapFree;
+    }
+
+    public long getCommitLimit() {
+        return commitLimit;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/MemoryType.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public enum MemoryType {
+    MEMORY_TOTAL,
+    MEMORY_FREE,
+    MEMORY_USED,
+    SWAP_TOTAL,
+    SWAP_FREE,
+    BUFFERS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class NetworkInterfaceInfo implements Pojo {
+
+    private String iFace;
+    private String ip4Addr;
+    private String ip6Addr;
+
+    public NetworkInterfaceInfo(String iFace) {
+        this.iFace = iFace;
+        this.ip4Addr = null;
+        this.ip6Addr = null;
+    }
+
+    public String getInterfaceName() {
+        return iFace;
+    }
+
+    public String getIp4Addr() {
+        return ip4Addr;
+    }
+
+    public void setIp4Addr(String newAddr) {
+        ip4Addr = newAddr;
+    }
+
+    public void clearIp4Addr() {
+        ip4Addr = null;
+    }
+
+    public String getIp6Addr() {
+        return ip6Addr;
+    }
+
+    public void setIp6Addr(String newAddr) {
+        ip6Addr = newAddr;
+    }
+
+    public void clearIp6Addr() {
+        ip6Addr = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/Pojo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+/**
+ * All data types should implement this empty interface, to support the
+ * generalization of DAO code where possible.
+ */
+public interface Pojo {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+/**
+ * Any Pojo which is taken as a timestamped piece of data should
+ * implement this interface.
+ */
+public interface TimeStampedPojo extends Pojo {
+
+    public long getTimeStamp();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelator.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+public class TimeStampedPojoCorrelator implements Iterable<TimeStampedPojoCorrelator.Correlation> {
+
+    public static class Correlation {
+
+        private long timestamp;
+        private TimeStampedPojo[] correlation;
+
+        private Correlation(long timestamp, TimeStampedPojo[] correlation) {
+            this.timestamp = timestamp;
+            this.correlation = correlation;
+        }
+
+        public TimeStampedPojo get(int i) {
+            return correlation[i];
+        }
+
+        public long getTimeStamp() {
+            return timestamp;
+        }
+        
+    }
+
+    private static class TimeStampedPojoComparator implements Comparator<TimeStampedPojo> {
+
+        @Override
+        public int compare(TimeStampedPojo o1, TimeStampedPojo o2) {
+            return Long.compare(o1.getTimeStamp(), o2.getTimeStamp());
+        }
+
+        
+    }
+
+    private class Correlator implements Iterator<Correlation> {
+
+        private List<Iterator<TimeStampedPojo>> seriesIterators;
+
+        private Correlator() {
+            seriesIterators = new ArrayList<>();
+            int index = 0;
+            for (List<TimeStampedPojo> series : seriesList) {
+                Iterator<TimeStampedPojo> seriesIterator = series.iterator();
+                seriesIterators.add(seriesIterator);
+                if (seriesIterator.hasNext()) {
+                    current[index] = seriesIterator.next();
+                }
+                index++;
+            }
+            
+        }
+
+        @Override
+        public boolean hasNext() {
+            boolean hasNext = false;
+            for (TimeStampedPojo pojo : current) {
+                hasNext |= pojo != null;
+            }
+            return hasNext;
+        }
+
+        @Override
+        public Correlation next() {
+            long minTimestamp = Long.MAX_VALUE;
+            for (TimeStampedPojo pojo : current) {
+                if (pojo != null) {
+                    minTimestamp = Math.min(minTimestamp, pojo.getTimeStamp());
+                }
+            }
+            TimeStampedPojo[] next = new TimeStampedPojo[numSeries];
+            for (int i = 0; i < numSeries; i++) {
+                if (current[i] != null && current[i].getTimeStamp() == minTimestamp) {
+                    next[i] = current[i];
+                    Iterator<TimeStampedPojo> iterator = seriesIterators.get(i);
+                    current[i] = iterator.hasNext() ? iterator.next() : null;
+                } else {
+                    next[i] = last != null ? last.get(i) : null;
+                }
+            }
+            last = new Correlation(minTimestamp, next);
+            return last;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+        
+    }
+
+    private int numSeries;
+
+    private List<List<TimeStampedPojo>> seriesList;
+
+    private TimeStampedPojo[] current;
+    private Correlation last;
+
+    public TimeStampedPojoCorrelator(int numSeries) {
+        this.numSeries = numSeries;
+        seriesList = new ArrayList<>();
+        for (int i = 0; i < numSeries; i++) {
+            seriesList.add(new ArrayList<TimeStampedPojo>());
+        }
+        current = new TimeStampedPojo[numSeries];
+    }
+
+    public void add(int seriesIndex, TimeStampedPojo timeStampedPojo) {
+        List<? extends TimeStampedPojo> series = seriesList.get(seriesIndex);
+        int insertIdx = Collections.binarySearch(series, timeStampedPojo, new TimeStampedPojoComparator());
+        if (insertIdx < 0) {
+            insertIdx = -(insertIdx + 1);
+        }
+        seriesList.get(seriesIndex).add(insertIdx, timeStampedPojo);
+    }
+
+    public Iterator<Correlation> iterator() {
+        return new Correlator();
+    }
+
+    public void clear() {
+        for (List<TimeStampedPojo> series : seriesList) {
+            series.clear();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class VmClassStat implements TimeStampedPojo {
+
+    private int vmId;
+    private long timestamp;
+    private long loadedClasses;
+
+    public VmClassStat(int vmId, long timestamp, long loadedClasses) {
+        this.vmId = vmId;
+        this.timestamp = timestamp;
+        this.loadedClasses = loadedClasses;
+    }
+
+    public int getVmId() {
+        return vmId;
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timestamp;
+    }
+
+    public long getLoadedClasses() {
+        return loadedClasses;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class VmCpuStat implements TimeStampedPojo {
+
+    private final long timestamp;
+    private final int vmId;
+    private final double cpuLoad;
+
+    public VmCpuStat(long timestamp, int vmId, double cpuLoad) {
+        this.timestamp = timestamp;
+        this.vmId = vmId;
+        this.cpuLoad = cpuLoad;
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timestamp;
+    }
+
+    public int getVmId() {
+        return vmId;
+    }
+
+    /**
+     * The cpu load in percent (as in 100.0 for 100%). This value should be
+     * normalized to be in the range [0, 100]
+     */
+    public double getCpuLoad() {
+        return cpuLoad;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+public class VmGcStat implements TimeStampedPojo {
+
+    private final long timestamp;
+    private final int vmId;
+    private final String collectorName;
+    private final long runCount;
+    private final long wallTime;
+
+    public VmGcStat(int vmId, long timestamp, String collectorName, long runCount, long wallTime) {
+        this.timestamp = timestamp;
+        this.vmId = vmId;
+        this.collectorName = collectorName;
+        this.runCount = runCount;
+        this.wallTime = wallTime;
+    }
+    public int getVmId() {
+        return vmId;
+    }
+    public String getCollectorName() {
+        return collectorName;
+    }
+    public long getRunCount() {
+        return runCount;
+    }
+    public long getWallTime() {
+        return wallTime;
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timestamp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/VmInfo.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class VmInfo implements Pojo {
+
+    private int vmPid = 0;
+    private long startTime = System.currentTimeMillis();
+    private long stopTime = Long.MIN_VALUE;
+    private String javaVersion = "unknown";
+    private String javaHome = "unknown";
+    private String javaCommandLine = "unknown";
+    private String mainClass = "unknown";
+    private String vmName = "unknown";
+    private String vmInfo = "unknown";
+    private String vmVersion = "unknown";
+    private String vmArguments = "unknown";
+    private Map<String, String> properties = new HashMap<String, String>();
+    private Map<String, String> environment = new HashMap<String, String>();
+    private List<String> loadedNativeLibraries;
+
+    public VmInfo() {
+        /* use defaults */
+    }
+
+    public VmInfo(int vmPid, long startTime, long stopTime,
+            String javaVersion, String javaHome,
+            String mainClass, String commandLine,
+            String vmName, String vmInfo, String vmVersion, String vmArguments,
+            Map<String, String> properties, Map<String, String> environment, List<String> loadedNativeLibraries) {
+        this.vmPid = vmPid;
+        this.startTime = startTime;
+        this.stopTime = stopTime;
+        this.javaVersion = javaVersion;
+        this.javaHome = javaHome;
+        this.mainClass = mainClass;
+        this.javaCommandLine = commandLine;
+        this.vmName = vmName;
+        this.vmInfo = vmInfo;
+        this.vmVersion = vmVersion;
+        this.vmArguments = vmArguments;
+        this.properties = properties;
+        this.environment = environment;
+        this.loadedNativeLibraries = loadedNativeLibraries;
+    }
+
+    public int getVmId() {
+        return vmPid;
+    }
+
+    public int getVmPid() {
+        return vmPid;
+    }
+
+    public long getStartTimeStamp() {
+        return startTime;
+    }
+
+    public long getStopTimeStamp() {
+        return stopTime;
+    }
+
+    public String getJavaVersion() {
+        return javaVersion;
+    }
+
+    public String getJavaHome() {
+        return javaHome;
+    }
+
+    public String getMainClass() {
+        return mainClass;
+    }
+
+    public String getJavaCommandLine() {
+        return javaCommandLine;
+    }
+
+    public String getVmName() {
+        return vmName;
+    }
+
+    public String getVmArguments() {
+        return vmArguments;
+    }
+
+    public String getVmInfo() {
+        return vmInfo;
+    }
+
+    public String getVmVersion() {
+        return vmVersion;
+    }
+
+    public boolean isAlive() {
+        return getStartTimeStamp() > getStopTimeStamp();
+    }
+    
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    public Map<String, String> getEnvironment() {
+        return environment;
+    }
+
+    public List<String> getLoadedNativeLibraries() {
+        return loadedNativeLibraries;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+import java.util.List;
+
+public class VmMemoryStat implements TimeStampedPojo {
+
+    public static class Generation {
+        public static final String COLLECTOR_NONE = "none";
+        public String name;
+        public long capacity;
+        public long maxCapacity;
+        public List<Space> spaces;
+        public String collector;
+
+        public Space getSpace(String string) {
+            for (Space s : spaces) {
+                if (s.name.equals(string)) {
+                    return s;
+                }
+            }
+            return null;
+        }
+    }
+
+    public static class Space {
+        public int index;
+        public String name;
+        public long capacity;
+        public long maxCapacity;
+        public long used;
+    }
+
+    private final List<Generation> generations;
+    private final long timestamp;
+    private final int vmId;
+
+    public VmMemoryStat(long timestamp, int vmId, List<Generation> generations) {
+        this.timestamp = timestamp;
+        this.vmId = vmId;
+        this.generations = generations;
+    }
+
+    public int getVmId() {
+        return vmId;
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return timestamp;
+    }
+
+    public List<Generation> getGenerations() {
+        return generations;
+    }
+
+    public Generation getGeneration(String name) {
+        for (Generation g : generations) {
+            if (g.name.equals(name)) {
+                return g;
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class AgentInformation {
+
+    public static final Category AGENT_INFO_CATEGORY =
+            new Category(StorageConstants.CATEGORY_AGENT_CONFIG, Key.AGENT_ID);
+
+    public static final Key<Boolean> AGENT_ALIVE_KEY = new Key<>("alive", false);
+    
+    private long startTime;
+    private long stopTime;
+
+    private boolean alive;
+    
+    private List<BackendInformation> backends = new ArrayList<BackendInformation>();
+    
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public void setStopTime(long stopTime) {
+        this.stopTime = stopTime;
+    }
+    
+    public long getStopTime() {
+        return stopTime;
+    }
+    
+    public List<BackendInformation> getBackends() {
+        return Collections.unmodifiableList(backends);
+    }
+
+    public boolean isAlive() {
+        return alive;
+    }
+    
+    public void setAlive(boolean alive) {
+        this.alive = alive;
+    }
+    
+    public void addBackend(BackendInformation backend) {
+        backends.add(backend);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/BackendInformation.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class BackendInformation {
+
+    private String name;
+    private String description;
+    private boolean observeNewJvm;
+    private List<Integer> pids;
+    private Map<String, String> configuration = new HashMap<String,String>();
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public boolean isObserveNewJvm() {
+        return observeNewJvm;
+    }
+
+    public void setObserveNewJvm(boolean observeNewJvm) {
+        this.observeNewJvm = observeNewJvm;
+    }
+
+    public List<Integer> getPids() {
+        return pids;
+    }
+
+    public Map<String, String> getConfiguration() {
+        return configuration;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Category.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class Category {
+    private final String name;
+    private final Map<String, Key<?>> keys;
+
+    private ConnectionKey connectionKey;
+
+    private static Set<String> categoryNames = new HashSet<String>();
+
+    /**
+     * Creates a new Category instance with the specified name.
+     *
+     * @param name the name of the category
+     *
+     * @throws IllegalArgumentException if a Category is created with a name that has been used before
+     */
+    public Category(String name, Key<?>... keys) {
+        if (categoryNames.contains(name)) {
+            throw new IllegalStateException();
+        }
+        categoryNames.add(name);
+        this.name = name;
+        Map<String, Key<?>> keysMap = new HashMap<String, Key<?>>();
+        for (Key<?> key : keys) {
+            keysMap.put(key.getName(), key);
+        }
+        this.keys = Collections.unmodifiableMap(keysMap);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public synchronized Collection<Key<?>> getKeys() {
+        return keys.values();
+    }
+
+    public void setConnectionKey(ConnectionKey connKey) {
+        connectionKey = connKey;
+    }
+
+    public ConnectionKey getConnectionKey() {
+        return connectionKey;
+    }
+
+    public boolean hasBeenRegistered() {
+        return getConnectionKey() != null;
+    }
+
+    public Key<?> getKey(String name) {
+        return keys.get(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Chunk.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A Chunk is a unit containing a set of data that can be added as a whole to the dataset
+ * that exists behind the storage layer.
+ */
+public class Chunk {
+    private final Category category;
+    private final boolean replace;
+
+    private Map<Key<?>, Object> values = new LinkedHashMap<Key<?>, Object>();
+
+    /**
+     *
+     * @param category The {@link Category} of this data.  This should be a Category that the {@link Backend}
+     * who is producing this Chunk has registered via {@link Storage#registerCategory()}
+     * @param replace whether this chunk should replace the values based on the keys for this category,
+     * or be added to a set of values in this category
+     */
+    public Chunk(Category category, boolean replace) {
+        this.category = category;
+        this.replace = replace;
+    }
+
+    public Category getCategory() {
+        return category;
+    }
+
+    public boolean getReplace() {
+        return replace;
+    }
+
+    public <T> void put(Key<T> entry, T value) {
+        values.put(entry, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(Key<T> entry) {
+        // We only allow matching types in put(), so this cast should be fine.
+        return (T) values.get(entry);
+    }
+
+    public Set<Key<?>> getKeys() {
+        return values.keySet();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (! (o instanceof Chunk)) {
+            return false;
+        }
+        Chunk other = (Chunk) o;
+        return equalCategory(other) && equalValues(other);
+
+    }
+
+    private boolean equalCategory(Chunk other) {
+        return category == other.category;
+    }
+
+    private boolean equalValues(Chunk other) {
+        if (values.size() != other.values.size()) {
+            return false;
+        }
+        for (Entry<Key<?>, Object> entry : values.entrySet()) {
+            if (! equalEntry(other, entry)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean equalEntry(Chunk other, Entry<Key<?>, Object> entry) {
+        Key<?> key = entry.getKey();
+        return other.values.containsKey(key) && Objects.equals(other.values.get(key), values.get(key));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/ChunkConverter.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+class ChunkConverter {
+
+    private static final Logger logger = LoggingUtils.getLogger(ChunkConverter.class);
+
+    DBObject chunkToDBObject(Chunk chunk) {
+        BasicDBObject dbObject = new BasicDBObject();
+        Map<String, DBObject> dbObjectMap = null;
+        for (Key<?> key : chunk.getKeys()) {
+            dbObjectMap = convertChunkKey(chunk, key, dbObject, dbObjectMap);
+        }
+        return dbObject;
+    }
+
+    private Map<String, DBObject> convertChunkKey(Chunk chunk, Key<?> key, DBObject dbObject, Map<String,DBObject> dbObjectMap) {
+        String[] keyParts = key.getName().split("\\.");
+        String initialName = keyParts[0];
+        return convertChunkKeyRecursively(chunk, key, dbObject, keyParts, 0, initialName, dbObjectMap);
+    }
+
+    private Map<String, DBObject> convertChunkKeyRecursively(Chunk chunk, Key<?> key, DBObject dbObject, String[] keyParts, int partIndex,
+                                            String partialKeyName, Map<String, DBObject> dbObjectMap) {
+        if (partIndex == keyParts.length - 1) {
+            dbObject.put(keyParts[partIndex], chunk.get(key));
+        } else {
+            dbObjectMap = lazyCreateDBObjectMap(dbObjectMap);
+            DBObject nestedDbObject = getOrCreateSubObject(partialKeyName, dbObjectMap);
+            dbObject.put(keyParts[partIndex], nestedDbObject);
+            partIndex++;
+            String nextSubKey = keyParts[partIndex];
+            partialKeyName = partialKeyName + "." + nextSubKey;
+            convertChunkKeyRecursively(chunk, key, nestedDbObject, keyParts, partIndex, partialKeyName, dbObjectMap);
+        }
+        return dbObjectMap;
+    }
+
+    
+    private Map<String, DBObject> lazyCreateDBObjectMap(Map<String, DBObject> dbObjectMap) {
+        if (dbObjectMap == null) {
+            dbObjectMap = new HashMap<String, DBObject>();
+        }
+        return dbObjectMap;
+    }
+
+    private DBObject getOrCreateSubObject(String partialKeyName,
+            Map<String, DBObject> dbObjectMap) {
+        DBObject dbObject = dbObjectMap.get(partialKeyName);
+        if (dbObject == null) {
+            dbObject = new BasicDBObject();
+            dbObjectMap.put(partialKeyName, dbObject);
+        }
+        return dbObject;
+    }
+
+    public Chunk dbObjectToChunk(DBObject dbObject, Category category) {
+        Chunk chunk = new Chunk(category, false);
+        dbObjectToChunkRecurse(chunk, dbObject, category, null);
+        return chunk;
+    }
+
+    private void dbObjectToChunkRecurse(Chunk chunk, DBObject dbObject, Category category, String fullKey) {
+        for (String dbKey : dbObject.keySet()) {
+            if (!dbKey.equals("_id")) { // Mongo adds this to any stored document.
+                String newFullKey;
+                if (fullKey == null) {
+                    newFullKey = dbKey;
+                } else {
+                    newFullKey = fullKey + "." + dbKey;
+                }
+                dbObjectToChunkRecursively(chunk, dbObject, category, dbKey, newFullKey);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void dbObjectToChunkRecursively(Chunk chunk, DBObject dbObject, Category category, String dbKey, String fullKey) {
+        Object value = dbObject.get(dbKey);
+        if (value instanceof DBObject) {
+            DBObject dbObj = (DBObject) value;
+            dbObjectToChunkRecurse(chunk, dbObj, category, fullKey);
+        } else {
+            @SuppressWarnings("rawtypes")
+            Key key = category.getKey(fullKey);
+            if (key != null) {
+                chunk.put(key, value);
+            } else {
+                logger.warning("No key matching \"" + fullKey + "\" in category \"" + category + "\"");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Connection.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public abstract class Connection {
+
+    public enum ConnectionType {
+        LOCAL(false),
+        REMOTE(true),
+        CLUSTER(true),
+        ;
+
+        boolean isDisplayable = false;
+        boolean needsUrl = false;
+
+        private ConnectionType(boolean needsUrl) {
+            this.needsUrl = needsUrl;
+        }
+
+        private ConnectionType(boolean isDisplayable, boolean needsUrl) {
+            this.isDisplayable = isDisplayable;
+        }
+
+        public boolean isDisplayable() {
+            return isDisplayable;
+        }
+
+        public boolean needsUrl() {
+            return needsUrl;
+        }
+    }
+
+    public enum ConnectionStatus {
+        CONNECTED,
+        CONNECTING,
+        FAILED_TO_CONNECT,
+        DISCONNECTED,
+    }
+
+    public interface ConnectionListener {
+        public void changed(ConnectionStatus newStatus);
+    }
+
+    protected boolean connected = false;
+
+    private ConnectionType type;
+    private String url;
+
+    private List<Connection.ConnectionListener> listeners = new CopyOnWriteArrayList<>();
+
+    public void setType(ConnectionType type) {
+        this.type = type;
+    }
+
+    public ConnectionType getType() {
+        return type;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    @Override
+    public String toString() {
+        if (url == null) {
+            return type.toString();
+        }
+        return type.toString() + " to " + url;
+    }
+
+    public abstract void connect();
+
+    public abstract void disconnect();
+
+    public boolean isConnected() {
+        return connected;
+    }
+
+    public void addListener(ConnectionListener listener) {
+        this.listeners.add(listener);
+    }
+
+    public void removeListener(ConnectionListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    protected void fireChanged(ConnectionStatus status) {
+        for (ConnectionListener listener: listeners) {
+            listener.changed(status);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/ConnectionException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+public class ConnectionException extends RuntimeException {
+
+    public ConnectionException() {
+        super();
+    }
+
+    public ConnectionException(String message) {
+        super(message);
+    }
+
+    public ConnectionException(Throwable cause) {
+        super(cause);
+    }
+
+    public ConnectionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/ConnectionKey.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+public interface ConnectionKey {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Cursor.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+public interface Cursor {
+
+    public enum SortDirection {
+        ASCENDING(1),
+        DESCENDING(-1);
+
+        private int value;
+
+        private SortDirection(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    boolean hasNext();
+
+    Chunk next();
+
+    Cursor sort(Key<?> orderBy, SortDirection direction);
+
+    Cursor limit(int i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Key.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+/**
+ * A Key is used to refer to data in a {@link Chunk}.  It may also be a partial key to the
+ * set of data represented by a {@link Chunk} in a category.
+ */
+public class Key<T> {
+
+    // Keys used by most Categories.
+    public static final Key<Long> TIMESTAMP = new Key<>("timestamp", false);
+    public static final Key<String> AGENT_ID = new Key<>("agent-id", false);
+    public static final Key<Integer> VM_ID = new Key<>("vm-id", false);
+    public static final Key<String> WHERE = new Key<>("$where", false);
+
+    private String name;
+    private boolean isPartialCategoryKey;
+
+    public Key(String name, boolean isPartialCategoryKey) {
+        if (name == null || name.length() == 0) {
+            throw new IllegalArgumentException("A Key must have a non-null name of length >= 1.");
+        }
+        this.name = name;
+        this.isPartialCategoryKey = isPartialCategoryKey;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isPartialCategoryKey() {
+        return isPartialCategoryKey;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if ((o == null) || (o.getClass() != this.getClass())) {
+            return false;
+        }
+        Key<?> e = (Key<?>) o;
+        return (isPartialCategoryKey == e.isPartialCategoryKey()) &&
+            name.equals(e.getName());
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 1867;
+        hash = hash * 37 + (isPartialCategoryKey ? 0 : 1);
+        hash = hash * 37 + (name == null ? 0 : name.hashCode());
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        return "Key: " + name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoConnection.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+
+import com.mongodb.DB;
+import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+import com.mongodb.MongoURI;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+class MongoConnection extends Connection {
+
+    private Mongo m = null;
+    private DB db = null;
+    private StartupConfiguration conf;
+
+    MongoConnection(StartupConfiguration conf) {
+        this.conf = conf;
+    }
+
+    @Override
+    public void connect() {
+        try {
+            createConnection();
+            /* the mongo java driver does not ensure this connection is actually working */
+            testConnection();
+        } catch (IOException | MongoException |
+                 NotImplementedException | IllegalArgumentException e)
+        {
+            fireChanged(ConnectionStatus.FAILED_TO_CONNECT);
+            throw new ConnectionException(e.getMessage(), e);
+        }
+        fireChanged(ConnectionStatus.CONNECTED);
+        connected = true;
+    }
+
+    @Override
+    public void disconnect() {
+        connected = false;
+        db = null;
+        if (m != null) {
+            m.close();
+        }
+    }
+
+    public DB getDB() {
+        return db;
+    }
+
+    private void createConnection() throws MongoException, UnknownHostException {
+        this.m = new Mongo(getMongoURI());
+        this.db = m.getDB(StorageConstants.THERMOSTAT_DB_NAME);
+    }
+
+    private MongoURI getMongoURI() {
+        MongoURI uri = new MongoURI(conf.getDBConnectionString());
+        return uri;
+    }
+
+    private void testConnection() {
+        db.getCollection("agent-config").getCount();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+
+class MongoCursor implements Cursor {
+
+    private DBCursor cursor;
+    private Category category;
+
+    MongoCursor(DBCursor cursor, Category category) {
+        this.cursor = cursor;
+        this.category = category;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return cursor.hasNext();
+    }
+
+    @Override
+    public Chunk next() {
+        DBObject next = cursor.next();
+        if (next == null) {
+            return null;
+        }
+        ChunkConverter converter = new ChunkConverter();
+        return converter.dbObjectToChunk(next, category);
+    }
+
+    @Override
+    public Cursor sort(Key<?> orderBy, SortDirection direction) {
+        if (!category.getKeys().contains(orderBy)) {
+            throw new IllegalArgumentException("Key not present in this Cursor's category.");
+        }   /* TODO: There are other possible error conditions.  Once there is API to configure
+             * indexing/optimization, we may want to prevent or log predictably bad performance
+             * sorting requests.
+             */
+        DBObject dbOrderBy = new BasicDBObject(orderBy.getName(), direction.getValue());
+        DBCursor sorted = cursor.sort(dbOrderBy);
+        return new MongoCursor(sorted, category);
+    }
+
+    @Override
+    public Cursor limit(int i) {
+        DBCursor limited = cursor.limit(i);
+        return new MongoCursor(limited, category);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.bson.BSONObject;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+
+/**
+ * Implementation of the Storage interface that uses MongoDB to store the instrumentation data.
+ *
+ * In this implementation, each CATEGORY is given a distinct collection.
+ */
+public class MongoStorage extends Storage {
+
+    public static final String KEY_AGENT_ID = "agent-id";
+    public static final String SET_MODIFIER = "$set";
+
+    private MongoConnection conn;
+    private DB db = null;
+    private Map<String, DBCollection> collectionCache = new HashMap<String, DBCollection>();
+
+    private UUID agentId = null;
+
+    public MongoStorage(StartupConfiguration conf) {
+        conn = new MongoConnection(conf);
+        conn.addListener(new ConnectionListener() {
+            @Override
+            public void changed(ConnectionStatus newStatus) {
+                switch (newStatus) {
+                case DISCONNECTED:
+                    db = null;
+                case CONNECTED:
+                    db = conn.getDB();
+                default:
+                    // ignore other status events
+                }
+            }
+        });
+    }
+
+    @Override
+    public Connection getConnection() {
+        return conn;
+    }
+
+    @Override
+    public void setAgentId(UUID agentId) {
+        this.agentId = agentId;
+    }
+
+    private BasicDBObject getAgentDBObject() {
+        return new BasicDBObject(KEY_AGENT_ID, agentId.toString());
+    }
+
+    @Override
+    public void putChunk(Chunk chunk) {
+        Category cat = chunk.getCategory();
+        DBCollection coll = getCachedCollection(cat.getName());
+        BasicDBObject toInsert = getAgentDBObject();
+        BasicDBObject replaceKey = null;
+        boolean replace = chunk.getReplace();
+        Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>();
+        Map<String, BasicDBObject> replaceKeyNestedParts = null;
+        if (replace) {
+            replaceKey = getAgentDBObject();
+            replaceKeyNestedParts = new HashMap<String, BasicDBObject>();
+        }
+        for (Key<?> key : cat.getKeys()) {
+            boolean isKey = key.isPartialCategoryKey();
+            String[] entryParts = key.getName().split("\\.");
+            if (entryParts.length == 2) {
+                BasicDBObject nested = nestedParts.get(entryParts[0]);
+                if (nested == null) {
+                    if (isKey) {
+                        throwMissingKey(key.getName());
+                    }
+                    nested = new BasicDBObject();
+                    nestedParts.put(entryParts[0], nested);
+                }
+                nested.append(entryParts[1], chunk.get(key));
+                if (replace && isKey) {
+                    BasicDBObject replaceKeyNested = replaceKeyNestedParts.get(entryParts[0]);
+                    if (replaceKeyNested == null) {
+                        replaceKeyNested = new BasicDBObject();
+                        replaceKeyNestedParts.put(entryParts[0], replaceKeyNested);
+                    }
+                    replaceKeyNested.append(entryParts[1], replaceKeyNested);
+                }
+            } else {
+                if (!key.equals(Key.AGENT_ID)) {
+                    String mongoKey = key.getName();
+                    Object value = chunk.get(key);
+                    if ((value == null) && isKey) {
+                        throwMissingKey(key.getName());
+                    }
+                    toInsert.append(mongoKey, value);
+                    if (replace && isKey) {
+                        replaceKey.append(mongoKey, value);
+                    }
+                }
+            }
+        }
+        for (Entry<String, BasicDBObject> entry: nestedParts.entrySet()) {
+            toInsert.append(entry.getKey(), entry.getValue());
+        }
+        if (replace) {
+            for (Entry<String, BasicDBObject> entry: replaceKeyNestedParts.entrySet()) {
+                replaceKey.append(entry.getKey(), entry.getValue());
+            }
+            coll.update(replaceKey, toInsert, true, false);
+        } else {
+            coll.insert(toInsert);
+        }
+    }
+
+    @Override
+    public void updateChunk(Chunk chunk) {
+        Category cat = chunk.getCategory();
+        DBCollection coll = getCachedCollection(cat.getName());
+        BasicDBObject toUpdate = new BasicDBObject();
+        BasicDBObject updateKey = getAgentDBObject();
+        Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>();
+        Map<String, BasicDBObject> updateKeyNestedParts = new HashMap<String, BasicDBObject>();
+        for (Key<?> key : cat.getKeys()) {
+            boolean isKey = key.isPartialCategoryKey();
+            String[] entryParts = key.getName().split("\\.");
+            if (entryParts.length == 2) {
+                BasicDBObject nested = nestedParts.get(entryParts[0]);
+                if (nested == null) {
+                    if (isKey) {
+                        throwMissingKey(key.getName());
+                    }
+                } else {
+                    if (isKey) {
+                        BasicDBObject updateKeyNested = updateKeyNestedParts.get(entryParts[0]);
+                        if (updateKeyNested == null) {
+                            updateKeyNested = new BasicDBObject();
+                            updateKeyNestedParts.put(entryParts[0], updateKeyNested);
+                        }
+                        updateKeyNested.append(entryParts[1], updateKeyNested);
+                    } else {
+                        nested.append(SET_MODIFIER, new BasicDBObject(entryParts[1], chunk.get(key)));
+                    }
+                }
+            } else {
+                String mongoKey = key.getName();
+                Object value = chunk.get(key);
+                if (value == null) {
+                    if (isKey) {
+                        throwMissingKey(key.getName());
+                    }
+                } else {
+                    if (isKey) {
+                        updateKey.append(mongoKey, value);
+                    } else {
+                        toUpdate.append(SET_MODIFIER, new BasicDBObject(mongoKey, value));
+                    }
+                }
+            }
+        }
+        for (Entry<String, BasicDBObject> entry: nestedParts.entrySet()) {
+            toUpdate.append(entry.getKey(), entry.getValue());
+        }
+        for (Entry<String, BasicDBObject> entry: updateKeyNestedParts.entrySet()) {
+            updateKey.append(entry.getKey(), entry.getValue());
+        }
+        coll.update(updateKey, toUpdate);
+    }
+
+    private void throwMissingKey(String keyName) {
+        throw new IllegalArgumentException("Attempt to insert chunk with incomplete partial key.  Missing: " + keyName);
+    }
+
+    private DBCollection getCachedCollection(String collName) {
+        DBCollection coll = collectionCache.get(collName);
+        if (coll == null && db.collectionExists(collName)) {
+            coll = db.getCollection(collName);
+            if (coll != null) {
+                collectionCache.put(collName, coll);
+            }
+        }
+        return coll;
+    }
+
+    private DBObject createConfigDBObject(AgentInformation agentInfo) {
+        BasicDBObject result = getAgentDBObject();
+        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_START_TIME, agentInfo.getStartTime());
+        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_STOP_TIME, agentInfo.getStopTime());
+        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_ALIVE, agentInfo.isAlive());
+        
+        BasicDBObject backends = new BasicDBObject();
+        for (BackendInformation backend : agentInfo.getBackends()) {
+            backends.put(backend.getName(), createBackendConfigDBObject(backend));
+        }
+        result.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS, backends);
+        
+        return result;
+    }
+
+    private DBObject createBackendConfigDBObject(BackendInformation backend) {
+        BasicDBObject result = new BasicDBObject();
+        Map<String, String> configMap = backend.getConfiguration();
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NAME, backend.getName());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_DESC, backend.getDescription());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_ACTIVE, createBackendActiveDBObject(backend));
+        for (Entry<String, String> entry: configMap.entrySet()) {
+            result.append(entry.getKey(), entry.getValue());
+        }
+        return result;
+    }
+
+    private DBObject createBackendActiveDBObject(BackendInformation backend) {
+        BasicDBObject result = new BasicDBObject();
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NEW, backend.isObserveNewJvm());
+        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_PIDS, new BasicDBList());
+        // TODO check which processes are already being listened to.
+        return result;
+    }
+
+    @Override
+    public void purge() {
+        BasicDBObject deleteKey = getAgentDBObject();
+        for (DBCollection coll : collectionCache.values()) {
+            coll.remove(deleteKey);
+        }
+    }
+    
+    @Override
+    public ConnectionKey createConnectionKey(Category category) {
+        // TODO: There is probably some better place to do this, perhaps related to the inner class
+        // idea mentioned below.
+        if (!db.collectionExists(category.getName())) {
+            db.createCollection(category.getName(), new BasicDBObject("capped", false));
+        }
+        // TODO: We want to return an instance of an inner class here that carries the actual connection
+        // and replace the collectionCache. For now this is good enough though.
+        return new ConnectionKey(){};
+    }
+
+    @Override
+    public Cursor findAll(Chunk query) {
+        Category cat = query.getCategory();
+        DBCollection coll = getCachedCollection(cat.getName());
+        ChunkConverter converter = new ChunkConverter();
+        DBObject obj = converter.chunkToDBObject(query);
+        DBCursor dbCursor = coll.find(obj);
+        return new MongoCursor(dbCursor, query.getCategory());
+    }
+
+    // TODO: This method is only temporary to enable tests, until we come up with a better design,
+    // in particular, the collection should be stored in the category itself. It must not be called
+    // from production code.
+    void mapCategoryToDBCollection(Category category, DBCollection coll) {
+        collectionCache.put(category.getName(), coll);
+    }
+
+    @Override
+    public Chunk find(Chunk query) {
+        Category cat = query.getCategory();
+        DBCollection coll = getCachedCollection(cat.getName());
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbResult = coll.findOne(converter.chunkToDBObject(query));
+        return dbResult == null ? null : converter.dbObjectToChunk(dbResult, cat);
+    }
+    
+    @Override
+    public Cursor findAllFromCategory(Category category) {
+        DBCollection coll = getCachedCollection(category.getName());
+        DBCursor dbCursor = coll.find();
+        return new MongoCursor(dbCursor, category);
+    }
+
+    @Override
+    public long getCount(Category category) {
+        DBCollection coll = getCachedCollection(category.getName());
+        if (coll != null) {
+            return coll.getCount();
+        }
+        return 0L;
+    }
+
+    // TODO these methods below belong in some DAO.
+    @Override
+    public void addAgentInformation(AgentInformation agentInfo) {
+        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
+        DBObject toInsert = createConfigDBObject(agentInfo);
+        /* cast required to disambiguate between putAll(BSONObject) and putAll(Map) */
+        toInsert.putAll((BSONObject) getAgentDBObject());
+        configCollection.insert(toInsert, WriteConcern.SAFE);
+    }
+    
+    @Override
+    public void updateAgentInformation(AgentInformation agentInfo) {
+        BasicDBObject queryObject = getAgentDBObject();
+
+        DBObject updated = createConfigDBObject(agentInfo);
+        updated.putAll((BSONObject) queryObject);
+
+        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
+        configCollection.update(queryObject, updated);
+    }
+
+    @Override
+    public void removeAgentInformation() {
+        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
+        BasicDBObject toRemove = getAgentDBObject();
+        configCollection.remove(toRemove, WriteConcern.NORMAL);
+    }
+
+    @Override
+    public String getBackendConfig(String backendName, String configurationKey) {
+        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
+        BasicDBObject query = getAgentDBObject();
+        query.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS + "." + backendName, new BasicDBObject("$exists", true));
+        DBObject config = configCollection.findOne(query);
+        Object value = config.get(configurationKey);
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorageProvider.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+public class MongoStorageProvider implements StorageProvider {
+
+    private StartupConfiguration configuration;
+
+    public MongoStorageProvider(StartupConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public Storage createStorage() {
+        return new MongoStorage(configuration);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import java.util.UUID;
+
+
+public abstract class Storage {
+
+    public abstract void setAgentId(UUID id);
+
+    public final void registerCategory(Category category) {
+        if (category.hasBeenRegistered()) {
+            throw new IllegalStateException("Category may only be associated with one backend.");
+        }
+        ConnectionKey connKey = createConnectionKey(category);
+        category.setConnectionKey(connKey);
+    }
+
+    public abstract Connection getConnection();
+
+    public abstract ConnectionKey createConnectionKey(Category category);
+
+    public abstract void putChunk(Chunk chunk);
+
+    public abstract void updateChunk(Chunk chunk);
+
+    /**
+     * Drop all data related to the currently running agent.
+     */
+    public abstract void purge();
+    
+    public abstract Cursor findAll(Chunk query);
+
+    public abstract Chunk find(Chunk query);
+
+    public abstract Cursor findAllFromCategory(Category category);
+    
+    public abstract long getCount(Category category);
+
+    // TODO these will move to appropriate DAO
+    public abstract void addAgentInformation(AgentInformation agentInfo);
+
+    public abstract void removeAgentInformation();
+
+    public abstract void updateAgentInformation(AgentInformation agentInfo);
+
+    /**
+     * @return {@code null} if the value is invalid or missing
+     */
+    public abstract String getBackendConfig(String backendName, String configurationKey);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/StorageConstants.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+public class StorageConstants {
+    public static final String THERMOSTAT_DB_NAME = "thermostat";
+
+    public static final String CATEGORY_AGENT_CONFIG = "agent-config";
+
+    public static final String KEY_AGENT_CONFIG_BACKENDS = "backends";
+    public static final String KEY_AGENT_CONFIG_AGENT_START_TIME = "start-time";
+    public static final String KEY_AGENT_CONFIG_BACKEND_NAME = "name";
+    public static final String KEY_AGENT_CONFIG_BACKEND_DESC = "description";
+    public static final String KEY_AGENT_CONFIG_BACKEND_ACTIVE = "active";
+    public static final String KEY_AGENT_CONFIG_BACKEND_NEW = "new";
+    public static final String KEY_AGENT_CONFIG_BACKEND_PIDS = "pids";
+
+    public static final String KEY_AGENT_CONFIG_AGENT_ALIVE = "alive";
+    public static final String KEY_AGENT_CONFIG_AGENT_STOP_TIME = "stop-time";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+public interface StorageProvider {
+
+    Storage createStorage();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/ApplicationException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.tools;
+
+public class ApplicationException extends Exception {
+
+    private static final long serialVersionUID = 5910852125476383826L;
+
+    public ApplicationException(String message) {
+        super(message);
+    }
+
+    public ApplicationException(Throwable cause) {
+        super(cause);
+    }
+
+    public ApplicationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ApplicationException(String message, Throwable cause,
+            boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/ApplicationState.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.tools;
+
+/**
+ * Denotes the condition this application is in.
+ */
+public enum ApplicationState {
+
+    NONE,
+    SUCCESS,
+    FAIL,
+    HELP,
+    START,
+    STOP;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/BasicCommand.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.tools;
+
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+/**
+ * Common base class for all daemon and application
+ */
+public abstract class BasicCommand implements Command {
+
+    private ActionNotifier<ApplicationState> notifier;
+    private boolean storageRequired;
+    
+    public BasicCommand() {
+        this.notifier = new ActionNotifier<>(this);
+    }
+
+    public ActionNotifier<ApplicationState> getNotifier() {
+        return notifier;
+    }
+
+    public abstract StartupConfiguration getConfiguration();
+
+    @Override
+    public boolean isStorageRequired() {
+        return storageRequired;
+    }
+
+    protected void setStorageRequired(boolean storageRequired) {
+        this.storageRequired = storageRequired;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/ProcessStartException.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.tools;
+
+public class ProcessStartException extends ApplicationException {
+
+    private String commandName;
+
+    /**
+     * @param commandName the name of the program that failed to execute
+     * @param cause the original exception
+     */
+    public ProcessStartException(String commandName, Throwable cause) {
+        super("unable to execute " + commandName, cause);
+        this.commandName = commandName;
+    }
+
+    public String getCommandName() {
+        return commandName;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/DisplayableValues.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.utils;
+
+public class DisplayableValues {
+
+    private static final long BYTES_IN_KB = 1024;
+    private static final long BYTES_IN_MB = 1024*BYTES_IN_KB;
+    private static final long BYTES_IN_GB = 1024*BYTES_IN_MB;
+    private static final long BYTES_IN_TB = 1024*BYTES_IN_GB;
+    
+    public enum Scale {
+        B(1),
+        KiB(BYTES_IN_KB),
+        MiB(BYTES_IN_MB),
+        GiB(BYTES_IN_GB),
+        TiB(BYTES_IN_TB);
+
+        private long numBytes;
+
+        private Scale(long numBytes) {
+            this.numBytes = numBytes;
+        }
+
+        public long getNumBytes() {
+            return numBytes;
+        }
+
+        public static double convertTo(Scale scale, final long bytes) {
+            
+            return ((double) bytes) / ((double) scale.numBytes);
+        }
+        
+        public static double convertTo(Scale scale, final long bytes, long roundTo) {
+            
+            double result = ((double) bytes) / ((double) scale.numBytes);
+            result = ((double) Math.round(result * roundTo)) / roundTo;
+            
+            return result;
+        }
+
+        public static Scale getScale(final long bytes) {
+            if (bytes < BYTES_IN_KB) {
+                return Scale.B;
+            } else if (bytes < BYTES_IN_MB) {
+                return Scale.KiB;
+            } else if (bytes < BYTES_IN_GB) {
+                return Scale.MiB;
+            } else if (bytes < BYTES_IN_TB) {
+                return Scale.GiB;
+            } else {
+                return Scale.TiB;
+            }
+        }
+    }
+    
+    private static final String DOUBLE_FORMAT_STRING = "%.1f";
+
+    private DisplayableValues() {} // Not to be instantiated.
+
+    public static String[] bytes(final long bytes) {
+        if (bytes < BYTES_IN_KB) {
+            return new String[] { String.valueOf(bytes), Scale.B.name() };
+        } else if (bytes < BYTES_IN_MB) {
+            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_KB), Scale.KiB.name() };
+        } else if (bytes < BYTES_IN_GB) {
+            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_MB), Scale.MiB.name() };
+        } else if (bytes < BYTES_IN_TB) {
+            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_GB), Scale.GiB.name() };
+        } else {
+            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_TB), Scale.TiB.name() };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggedExternalProcess.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.tools.ApplicationException;
+import com.redhat.thermostat.common.tools.ProcessStartException;
+
+/**
+ * Runs a process and logs it's output. The process's output and error streams
+ * will be unreadable.
+ */
+public class LoggedExternalProcess extends Thread {
+
+    private static final Logger logger = LoggingUtils.getLogger(LoggedExternalProcess.class);
+    private BufferedReader reader;
+    private String[] commands;
+
+    public LoggedExternalProcess(List<String> commands) {
+        this(commands.toArray(new String[0]));
+    }
+    
+    public LoggedExternalProcess(String[] commands) {
+        this.commands = Arrays.copyOf(commands, commands.length);
+        setDaemon(true);
+    }
+
+    public int runAndReturnResult() throws IOException, InterruptedException, ApplicationException{
+        Process p = runAndReturnProcess();
+        return p.waitFor();
+    }
+
+    public Process runAndReturnProcess() throws IOException, ApplicationException {
+        ProcessBuilder b = new ProcessBuilder(commands);
+        b.redirectErrorStream(true);
+        Process p = null;
+        try {
+            p = b.start();
+        } catch (IOException ioe) {
+            throw new ProcessStartException(commands[0], ioe);
+        }
+        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        this.start();
+        return p;
+    }
+
+    @Override
+    public void run() {
+        try {
+            String output = null;
+            while ((output = reader.readLine()) != null) {
+                logger.info(output);
+            }
+        } catch (IOException ex) {
+            logger.warning("Error reading external program output.");
+        } finally {
+            try {
+                reader.close();
+            } catch (IOException ex) {
+                logger.warning("Error closing stream from external program.");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.LogFormatter;
+import com.redhat.thermostat.common.config.ConfigUtils;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+
+/**
+ * A few helper functions to facilitate using loggers
+ * <p>
+ * It would be good idea to call {@link LogManager#readConfiguration()} with a
+ * properties file that sets an appropriate value for ".level"
+ */
+public final class LoggingUtils {
+
+    private static Logger root = null;
+    private static final String ROOTNAME = "com.redhat.thermostat";
+
+    private LoggingUtils() {
+        /* should not be instantiated */
+    }
+
+    /**
+     * Pretty much every one of the utility methods in this static class should call this method before doing anything else.
+     */
+    private static void ensureRootLogger() {
+        if (root == null) {
+            root = Logger.getLogger(ROOTNAME);
+            root.setUseParentHandlers(false);
+            for (Handler handler : root.getHandlers()) {
+                handler.setFormatter(new LogFormatter());
+                // This is workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4462908
+                handler.setLevel(Level.ALL);
+            }
+        }
+    }
+
+    /**
+     * Set the log level for the logger at the root of the "com.redhat.thermostat" namespace
+     * 
+     * @param level the minimum level at which logging statements should appear in the logs
+     */
+    public static void setGlobalLogLevel(Level level) {
+        ensureRootLogger();
+        root.setLevel(level);
+    }
+
+    /**
+     * Returns an appropriate logger to be used by class klass.
+     */
+    public static Logger getLogger(Class<?> klass) {
+        ensureRootLogger();
+        Logger logger = Logger.getLogger(klass.getPackage().getName());
+        logger.setLevel(null); // Will inherit from root logger
+        return logger;
+    }
+
+    /**
+     * Ensures log messages are written to the console as well
+     */
+    public static void useDevelConsole() {
+        ensureRootLogger();
+        ConsoleHandler handler = new ConsoleHandler();
+        handler.setFormatter(new LogFormatter());
+        // This is workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4462908
+        handler.setLevel(Level.ALL);
+        root.addHandler(handler);
+    }
+
+    public static void loadGlobalLoggingConfig() throws InvalidConfigurationException {
+        File thermostatEtcDir = new File(ConfigUtils.getThermostatHome(), "etc");
+        File loggingPropertiesFile = new File(thermostatEtcDir, "logging.properties");
+        if (loggingPropertiesFile.isFile()) {
+            readLoggingProperties(loggingPropertiesFile);
+        }
+    }
+
+    public static void loadUserLoggingConfig() throws InvalidConfigurationException {
+        File thermostatUserDir = new File(ConfigUtils.getThermostatUserHome());
+        File loggingPropertiesFile = new File(thermostatUserDir, "logging.properties");
+        if (loggingPropertiesFile.isFile()) {
+            readLoggingProperties(loggingPropertiesFile);
+        }
+    }
+
+    private static void readLoggingProperties(File loggingPropertiesFile)
+            throws InvalidConfigurationException {
+        try (FileInputStream fis = new FileInputStream(loggingPropertiesFile)){
+            LogManager.getLogManager().readConfiguration(fis);
+        } catch (SecurityException | IOException e) {
+            throw new InvalidConfigurationException("Could not read logging.properties", e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/StringUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+public class StringUtils {
+
+    private StringUtils() {
+        /* should not be instantiated */
+    }
+
+    public static InputStream toInputStream(String toConvert) {
+        try {
+            return new ByteArrayInputStream(toConvert.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalStateException("UTF-8 not supported");
+        }
+    }
+
+    public static String quote(String toQuote) {
+        return "\"" + toQuote + "\"";
+    }
+
+    public static String repeat(String text, int times) {
+        StringBuilder builder = new StringBuilder(text.length() * times);
+        for (int i = 0; i < times; i++) {
+            builder.append(text);
+        }
+        return builder.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/test/Bug.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.AppContextSetup;
+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 CommandRegistry commandRegistry = new TestCommandRegistry();
+
+    private AppContextSetup appContextSetup = new AppContextSetup() {
+
+        @Override
+        public void setupAppContext(String dbUrl) {
+            // We do nothing for now.
+        }
+    };
+
+    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 commandRegistry;
+            }
+
+            @Override
+            public AppContextSetup getAppContextSetup() {
+                return TestCommandContextFactory.this.getAppContextSetup();
+            }
+
+            @Override
+            public CommandContextFactory getCommandContextFactory() {
+                return TestCommandContextFactory.this;
+            }
+            
+        };
+    }
+
+    @Override
+    public CommandRegistry getCommandRegistry() {
+        return commandRegistry;
+    }
+
+    @Override
+    protected AppContextSetup getAppContextSetup() {
+        return appContextSetup;
+    }
+
+    public String getOutput() {
+        return new String(out.toByteArray());
+    }
+
+    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/test/TestCommandRegistry.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.common.cli.BaseCommandRegistry;
+import com.redhat.thermostat.common.cli.Command;
+
+class TestCommandRegistry extends BaseCommandRegistry {
+
+    private static class TestServiceRegistration implements ServiceRegistration {
+
+        @Override
+        public ServiceReference getReference() {
+            // Nothing to do for now.
+            return null;
+        }
+
+        @Override
+        public void setProperties(Dictionary properties) {
+            // Nothing to do for now.
+        }
+
+        @Override
+        public void unregister() {
+            // Nothing to do for now.
+        }
+
+    }
+
+    private Map<String, Command> commands = new HashMap<>();
+
+    public Command getCommand(String name) {
+        return commands.get(name);
+    }
+
+    public Collection<Command> getRegisteredCommands() {
+        return commands.values();
+    }
+
+    protected ServiceRegistration registerCommand(Command cmd) {
+        commands.put(cmd.getName(), cmd);
+        return new TestServiceRegistration();
+    }
+
+    @Override
+    public void unregisterCommands() {
+        commands.clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/test/TestTimerFactory.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,1 @@
+com.redhat.thermostat.common.cli.HelpCommand
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ActionEventTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ActionEventTest {
+
+    private enum TestId {
+        TEST_ID1, TEST_ID2
+    }
+
+    @Test
+    public void testGetActionId() {
+        ActionEvent<TestId> viewActionEvent = new ActionEvent<>(new Object(), TestId.TEST_ID1);
+        assertEquals(TestId.TEST_ID1, viewActionEvent.getActionId());
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void verifyThatNullActionIdThrowsNPE() {
+        new ActionEvent<>(new Object(), null);
+    }
+
+    @Test
+    public void testEqualsEquals() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID1);
+        assertTrue(action1.equals(action2));
+    }
+
+    @Test
+    public void testEqualsDifferentSource() {
+        Object source1 = new Object();
+        Object source2 = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source1, TestId.TEST_ID1);
+        ActionEvent<TestId> action2 = new ActionEvent<>(source2, TestId.TEST_ID1);
+        assertFalse(action1.equals(action2));
+    }
+
+    @Test
+    public void testEqualsDifferentId() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID2);
+        assertFalse(action1.equals(action2));
+    }
+
+    @Test
+    public void testEqualsNull() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        assertFalse(action1.equals(null));
+    }
+
+    @Test
+    public void testEqualsSame() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        assertTrue(action1.equals(action1));
+    }
+
+    @Test
+    public void testEqualsOtherType() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        assertFalse(action1.equals("test"));
+    }
+
+    @Test
+    public void testHashCodeEquals() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID1);
+        assertTrue(action1.hashCode() == action2.hashCode());
+    }
+
+    @Test
+    public void testHashCodeStaysSame() {
+        Object source = new Object();
+        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
+        int hashCode1 = action1.hashCode();
+        int hashCode2 = action1.hashCode();
+        assertTrue(hashCode1 == hashCode2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ActionNotifierTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+
+public class ActionNotifierTest {
+
+    private enum TestId {
+        TEST_ID1
+    }
+
+
+    @Test
+    public void verifySingleListenerNotification() {
+
+        Object source = new Object();
+        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
+        @SuppressWarnings("unchecked")
+        ActionListener<TestId> listener = mock(ActionListener.class);
+        viewActionSupport.addActionListener(listener);
+
+        viewActionSupport.fireAction(TestId.TEST_ID1);
+
+        verify(listener).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
+    }
+
+    @Test
+    public void verifyMultiListenerNotification() {
+
+        Object source = new Object();
+        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
+        @SuppressWarnings("unchecked")
+        ActionListener<TestId> listener1 = mock(ActionListener.class);
+        @SuppressWarnings("unchecked")
+        ActionListener<TestId> listener2 = mock(ActionListener.class);
+        @SuppressWarnings("unchecked")
+        ActionListener<TestId> listener3 = mock(ActionListener.class);
+        viewActionSupport.addActionListener(listener1);
+        viewActionSupport.addActionListener(listener2);
+        viewActionSupport.addActionListener(listener3);
+
+        viewActionSupport.fireAction(TestId.TEST_ID1);
+
+        verify(listener1).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
+        verify(listener2).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
+        verify(listener3).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
+    }
+
+    @Test
+    public void verifyRemoveListener() {
+        Object source = new Object();
+        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
+        @SuppressWarnings("unchecked")
+        ActionListener<TestId> listener = mock(ActionListener.class);
+        viewActionSupport.addActionListener(listener);
+        viewActionSupport.removeActionListener(listener);
+
+        viewActionSupport.fireAction(TestId.TEST_ID1);
+
+        verify(listener, never()).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
+    }
+
+    @Test
+    public void testRemoveWhileNotifying() {
+        Object source = new Object();
+        final ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
+        final boolean[] listenerCalled = new boolean[] { false };
+
+        final ActionListener<TestId> listener = new ActionListener<TestId>() {
+
+            @Override
+            public void actionPerformed(ActionEvent<TestId> viewActionEvent) {
+                viewActionSupport.removeActionListener(this);
+                listenerCalled[0] = true;
+            }
+            
+        };
+        viewActionSupport.addActionListener(listener);
+
+        viewActionSupport.fireAction(TestId.TEST_ID1);
+
+        assertTrue(listenerCalled[0]);
+
+        listenerCalled[0] = false;
+        viewActionSupport.fireAction(TestId.TEST_ID1);
+        assertFalse(listenerCalled[0]);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ActivatorTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+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.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.HelpCommand;
+import com.redhat.thermostat.common.cli.Launcher;
+
+public class ActivatorTest {
+
+    @Test
+    public void testRegisterServices() throws Exception {
+        final Map<ServiceRegistration, Object> regs = new HashMap<>();
+        BundleContext bCtx = mock(BundleContext.class);
+        when(bCtx.registerService(anyString(), any(), any(Dictionary.class))).then(new Answer<ServiceRegistration>() {
+
+            @Override
+            public ServiceRegistration answer(InvocationOnMock invocation) throws Throwable {
+                ServiceRegistration reg = mock(ServiceRegistration.class);
+                when(reg.getReference()).thenReturn(mock(ServiceReference.class));
+                regs.put(reg, invocation.getArguments()[1]);
+                return reg;
+            }
+        });
+        when(bCtx.getService(isA(ServiceReference.class))).then(new Answer<Object>() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                ServiceReference ref = (ServiceReference) invocation.getArguments()[0];
+                for (Entry<ServiceRegistration,Object> registration: regs.entrySet()) {
+                    if (registration.getKey().getReference().equals(ref)) {
+                        return registration.getValue();
+                    }
+                }
+                return null;
+            }
+        });
+
+        Activator activator = new Activator();
+
+        activator.start(bCtx);
+
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put(Command.NAME, "help");
+        verify(bCtx).registerService(eq(Command.class.getName()), isA(HelpCommand.class), eq(props));
+
+        verify(bCtx).registerService(eq(Launcher.class.getName()), isA(Launcher.class), any(Dictionary.class));
+
+        activator.stop(bCtx);
+
+        for (ServiceRegistration reg : regs.keySet()) {
+            verify(reg).unregister();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/TestUtils.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.Properties;
+import java.util.Random;
+
+public class TestUtils {
+
+    public static int getProcessId() {
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        String pidPart = name.split("@")[0];
+        return Integer.parseInt(pidPart);
+    }
+
+    public static boolean isLinux() {
+        return (System.getProperty("os.name").toLowerCase().contains("linux"));
+    }
+        
+    public static String setupAgentConfigs() throws IOException {
+        // need to create dummy config files for the tests
+        Random random = new Random();
+
+        String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar +
+                Math.abs(random.nextInt()) + File.separatorChar;
+
+        System.setProperty("THERMOSTAT_HOME", tmpDir);
+        File agent = new File(tmpDir, "agent");
+        agent.mkdirs();
+
+        File tmpConfigs = new File(agent, "agent.properties");
+
+        new File(agent, "run").mkdirs();
+        new File(agent, "logs").mkdirs();
+
+        File backends = new File(tmpDir, "backends");
+        File system = new File(backends, "system");
+        system.mkdirs();
+        
+        Properties props = new Properties();            
+
+        props.setProperty("BACKENDS", "system");
+        props.setProperty("LOG_LEVEL", "WARNING");
+
+        props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties");
+
+        // now write the configs for the backends
+        tmpConfigs = new File(system, "backend.properties");
+        props = new Properties();
+        props.setProperty("BACKEND_CLASS",
+                          "com.redhat.thermostat.backend.system.SystemBackend");
+        props.setProperty("DESCRIPTION",
+                          "fluff backend for tests");
+        props.setProperty("VENDOR",
+                          "Red Hat, Inc.");
+        props.setProperty("VERSION",
+                          "1.0");
+        props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties");
+        
+        return tmpDir;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.test.Bug;
+
+public class ThreadPoolTimerFactoryTest {
+
+    private static final long DELAY = 200;
+
+    private Timer timer;
+
+    private ThreadGroup threadGroup;
+
+    private TimerFactory timerFactory;
+
+    @Before
+    public void setUp() {
+        threadGroup = new ThreadGroup("test");
+        timerFactory = new ThreadPoolTimerFactory(1, threadGroup);
+        timer = timerFactory.createTimer();
+    }
+
+    @After
+    public void tearDown() {
+        
+        timer = null;
+        timerFactory.shutdown();
+        timerFactory = null;
+        threadGroup = null;
+    }
+
+    @Test
+    public void testDefault() throws InterruptedException {
+        Runnable action = mock(Runnable.class);
+        timer.setAction(action);
+        timer.start();
+        Thread.sleep(DELAY / 2);
+        verify(action).run();
+    }
+
+    @Test
+    public void testNullAction() {
+        timer.setAction(null);
+        timer.start();
+        // Good when no NPE is thrown.
+    }
+
+    @Test
+    public void testDefaultWithDelay() throws InterruptedException {
+        Runnable action = mock(Runnable.class);
+        timer.setAction(action);
+        timer.setInitialDelay(DELAY);
+        timer.start();
+        Thread.sleep(DELAY / 2);
+        verify(action, never()).run();
+        Thread.sleep(DELAY);
+        verify(action).run();
+        Thread.sleep(DELAY);
+        verify(action).run();
+    }
+
+    @Test
+    public void testTimeUnitSecond() throws InterruptedException {
+        Runnable action = mock(Runnable.class);
+        timer.setAction(action);
+        timer.setInitialDelay(1);
+        timer.setTimeUnit(TimeUnit.SECONDS);
+        timer.start();
+        Thread.sleep(500);
+        verify(action, never()).run();
+        Thread.sleep(1000);
+        verify(action).run();
+        Thread.sleep(1000);
+        verify(action).run();
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testNullType() throws InterruptedException {
+        timer.setSchedulingType(null);
+    }
+
+    @Test
+    public void testWithFixedRate() throws InterruptedException {
+        Runnable action = mock(Runnable.class);
+        doAnswer(new Answer<Void>() {
+
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                // Wait a little less than delay to
+                // 1. Verify more easily that the duration of the task does not push back the activation of next task.
+                // 2. Not congest the timer thread (which would happen if we take >= DELAY).
+                Thread.sleep(DELAY * 9 / 10 );
+                return null;
+            }
+            
+        }).when(action).run();
+        timer.setAction(action);
+        timer.setInitialDelay(DELAY);
+        timer.setDelay(DELAY);
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+        timer.start();
+        Thread.sleep(DELAY / 2);
+        verify(action, never()).run();
+        Thread.sleep(DELAY);
+        verify(action).run();
+        Thread.sleep(DELAY);
+        verify(action, times(2)).run();
+        timer.stop();
+        Thread.sleep(DELAY);
+        verify(action, times(2)).run();
+    }
+
+    @Test
+    public void testStopWithoutStart() {
+        timer.stop();
+        // Good when no exception is thrown.
+    }
+
+    @Test
+    public void testWithFixedDelay() throws InterruptedException {
+        Runnable action = mock(Runnable.class);
+        doAnswer(new Answer<Void>() {
+
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Thread.sleep(DELAY / 2);
+                return null;
+            }
+            
+        }).when(action).run();
+        timer.setAction(action);
+        timer.setInitialDelay(DELAY);
+        timer.setDelay(DELAY);
+        timer.setSchedulingType(SchedulingType.FIXED_DELAY);
+        timer.start();
+        Thread.sleep(DELAY / 2);
+        verify(action, never()).run();
+        Thread.sleep(DELAY);
+        verify(action).run();
+        Thread.sleep(DELAY / 2);
+        verify(action).run();
+        Thread.sleep(DELAY);
+        verify(action, times(2)).run();
+        Thread.sleep(DELAY / 2);
+        verify(action, times(2)).run();
+        timer.stop();
+        Thread.sleep(DELAY);
+        verify(action, times(2)).run();
+    }
+
+    @Bug(id="957",
+         summary="Thermostat GUI doesn't exit when closed, needs killing",
+         url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=957")
+    @Test
+    public void verifyShutdownKillsThreads() throws InterruptedException {
+
+        Runnable action = mock(Runnable.class);
+        timer.setAction(action);
+        timer.setInitialDelay(DELAY / 2);
+        timer.start();
+
+        assertTrue(threadGroup.activeCount() > 0);
+
+        timerFactory.shutdown();
+
+        Thread.sleep(DELAY);
+
+        assertEquals(0, threadGroup.activeCount());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/appctx/ApplicationContextTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.appctx;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.DAOFactory;
+
+public class ApplicationContextTest {
+
+    @Before
+    public void setUp() {
+        ApplicationContext.reset();
+    }
+
+    @After
+    public void tearDown() {
+        ApplicationContext.reset();
+    }
+
+    @Test
+    public void verifyGetInstanceNotNull() {
+        ApplicationContext ctx = ApplicationContext.getInstance();
+        assertNotNull(ctx);
+    }
+
+    @Test
+    public void  testDAOFactorySetGet() {
+        DAOFactory daoFactory = mock(DAOFactory.class);
+        ApplicationContext ctx = ApplicationContext.getInstance();
+        ctx.setDAOFactory(daoFactory);
+
+        DAOFactory actual1 = ctx.getDAOFactory();
+        assertSame(daoFactory, actual1);
+    }
+
+    @Test
+    public void  verifyDAOFactoryIsNullWhenNotInitialized() {
+        ApplicationContext ctx = ApplicationContext.getInstance();
+
+        DAOFactory actual = ctx.getDAOFactory();
+        assertNull(actual);
+    }
+
+    @Test
+    public void  verifyDAOFactoryStaysSame() {
+        DAOFactory daoFactory = mock(DAOFactory.class);
+        ApplicationContext ctx = ApplicationContext.getInstance();
+        ctx.setDAOFactory(daoFactory);
+
+        ApplicationContext ctx2 = ApplicationContext.getInstance();
+        DAOFactory actual2 = ctx2.getDAOFactory();
+        assertSame(daoFactory, actual2);
+    }
+
+    @Test
+    public void  testTimerFactorySetGet() {
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        ApplicationContext ctx = ApplicationContext.getInstance();
+        ctx.setTimerFactory(timerFactory);
+
+        TimerFactory actual1 = ctx.getTimerFactory();
+        assertSame(timerFactory, actual1);
+    }
+
+    @Test
+    public void  verifyTimerFactoryIsNullWhenNotInitialized() {
+        ApplicationContext ctx = ApplicationContext.getInstance();
+
+        TimerFactory actual = ctx.getTimerFactory();
+        assertNull(actual);
+    }
+
+    @Test
+    public void  verifyTimerFactoryStaysSame() {
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        ApplicationContext ctx = ApplicationContext.getInstance();
+        ctx.setTimerFactory(timerFactory);
+
+        ApplicationContext ctx2 = ApplicationContext.getInstance();
+        TimerFactory actual2 = ctx2.getTimerFactory();
+        assertSame(timerFactory, actual2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/CommandContextFactoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+public class CommandContextFactoryTest {
+
+    private BundleContext bundleContext;
+    private CommandContextFactory cmdCtxFactory;
+
+    @Before
+    public void setUp() {
+        bundleContext = mock(BundleContext.class);
+        cmdCtxFactory = new CommandContextFactory(bundleContext);
+    }
+
+    @After
+    public void tearDown() {
+        cmdCtxFactory = null;
+        bundleContext = null;
+    }
+
+    @Test
+    public void testCreateContext() {
+        Arguments args = mock(Arguments.class);
+        CommandContext ctx = cmdCtxFactory.createContext(args);
+        assertSame(args, ctx.getArguments());
+        assertNotNull(ctx.getAppContextSetup());
+        assertSame(cmdCtxFactory, ctx.getCommandContextFactory());
+        assertSame(cmdCtxFactory.getCommandRegistry(), ctx.getCommandRegistry());
+        assertSame(cmdCtxFactory.getConsole(), ctx.getConsole());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/CommandExceptionTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.CommandException;
+
+public class CommandExceptionTest {
+
+    @Test
+    public void testDefaultConstructor() {
+        CommandException ce = new CommandException();
+        verifyMessageAndCause(ce, null, null);
+    }
+
+    @Test
+    public void testMessageConstructor() {
+        CommandException ce = new CommandException("test");
+        verifyMessageAndCause(ce, "test", null);
+    }
+
+    @Test
+    public void testCauseConstructor() {
+        Exception cause = new Exception("test fluff");
+        CommandException ce = new CommandException(cause);
+        verifyMessageAndCause(ce, "java.lang.Exception: test fluff", cause);
+    }
+
+    @Test
+    public void testCombinedConstructor() {
+        Exception cause = new Exception("test fluff");
+        CommandException ce = new CommandException("test", cause);
+        verifyMessageAndCause(ce, "test", cause);
+    }
+
+    private void verifyMessageAndCause(CommandException ce, String message, Exception cause) {
+        assertEquals(message, ce.getMessage());
+        assertSame(cause, ce.getCause());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParserTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CommandLineArgumentsParserTest {
+
+    private CommandLineArgumentsParser parser;
+
+    private ArgumentSpec arg3;
+
+    @Before
+    public void setUp() {
+        parser = new CommandLineArgumentsParser();
+
+        ArgumentSpec arg1 = mock(ArgumentSpec.class);
+        when(arg1.getName()).thenReturn("test1");
+        when(arg1.getShortOption()).thenReturn("t");
+        when(arg1.isRequired()).thenReturn(true);
+
+        ArgumentSpec arg2 = mock(ArgumentSpec.class);
+        when(arg2.getName()).thenReturn("test2");
+        when(arg2.isRequired()).thenReturn(false);
+
+        arg3 = mock(ArgumentSpec.class);
+        when(arg3.getName()).thenReturn("test3");
+        when(arg3.isRequired()).thenReturn(false);
+        when(arg3.isUsingAdditionalArgument()).thenReturn(true);
+
+        parser.addArguments(Arrays.asList(arg1, arg2, arg3));
+    }
+
+    @After
+    public void tearDown() {
+       parser = null; 
+       arg3 = null;
+    }
+
+    @Test
+    public void testSimpleArgs() throws CommandLineArgumentParseException {
+        Arguments args = parser.parse(new String[] { "--test1", "--test2" });
+
+        assertTrue(args.hasArgument("test1"));
+        assertEquals(null, args.getArgument("test1"));
+        assertTrue(args.hasArgument("test2"));
+        assertEquals(null, args.getArgument("test2"));
+    }
+
+    @Test
+    public void testShortArgs() throws CommandLineArgumentParseException {
+        Arguments args = parser.parse(new String[] { "-t", "--test2" });
+
+        assertTrue(args.hasArgument("test1"));
+        assertTrue(args.hasArgument("t"));
+        assertEquals(null, args.getArgument("test1"));
+        assertTrue(args.hasArgument("test2"));
+        assertEquals(null, args.getArgument("test2"));
+    }
+
+    @Test(expected=CommandLineArgumentParseException.class)
+    public void testNoMatchingArgs() throws CommandLineArgumentParseException {
+        parser.parse(new String[] { "--test1", "--no-match" });
+    }
+
+    @Test
+    public void testMissingRequiredArgument() throws CommandLineArgumentParseException {
+        try {
+          parser.parse(new String[] { "--test2" });
+          fail();
+        } catch (CommandLineArgumentParseException ex) {
+            String msg = ex.getMessage();
+            assertEquals("Missing required option: -t", msg);
+        }
+    }
+
+    @Test
+    public void testMissingRequiredArguments() throws CommandLineArgumentParseException {
+        ArgumentSpec arg4 = mock(ArgumentSpec.class);
+        when(arg4.getName()).thenReturn("test4");
+        when(arg4.isRequired()).thenReturn(true);
+        parser.addArguments(Arrays.asList(arg4));
+
+        try {
+          parser.parse(new String[] { "--test2" });
+          fail();
+        } catch (CommandLineArgumentParseException ex) {
+            String msg = ex.getMessage();
+            assertEquals("Missing required options: -t, --test4", msg);
+        }
+    }
+
+    @Test
+    public void testArgumentWithAdditionalArgument() throws CommandLineArgumentParseException {
+        Arguments args = parser.parse(new String[] { "--test3", "parameter", "--test1" } );
+        assertTrue(args.hasArgument("test3"));
+        assertEquals("parameter", args.getArgument("test3"));
+        assertTrue(args.hasArgument("test1"));
+    }
+
+    @Test(expected=CommandLineArgumentParseException.class)
+    public void testMissingAdditionalArgument() throws CommandLineArgumentParseException {
+        parser.parse(new String[] { "--test3" });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/CommandRegistryImplTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+public class CommandRegistryImplTest {
+
+    private CommandRegistryImpl commandRegistry;
+
+    private BundleContext bundleContext;
+
+    @Before
+    public void setUp() {
+        bundleContext = mock(BundleContext.class);
+        commandRegistry = new CommandRegistryImpl(bundleContext);
+    }
+
+    @After
+    public void tearDown() {
+        bundleContext = null;
+    }
+
+    @Test
+    public void testRegisterCommands() {
+        Command cmd1 = mock(Command.class);
+        when(cmd1.getName()).thenReturn("test1");
+        Command cmd2 = mock(Command.class);
+        when(cmd2.getName()).thenReturn("test2");
+
+        commandRegistry.registerCommands(Arrays.asList(cmd1, cmd2));
+
+        Hashtable<String,Object> props1 = new Hashtable<>();
+        props1.put(Command.NAME, "test1");
+        Hashtable<String,Object> props2 = new Hashtable<>();
+        props2.put(Command.NAME, "test2");
+        verify(bundleContext).registerService(Command.class.getName(), cmd1, props1);
+        verify(bundleContext).registerService(Command.class.getName(), cmd2, props2);
+
+        verifyNoMoreInteractions(bundleContext);
+
+    }
+
+    @Test
+    public void testUnregisterCommand() {
+        Command cmd1 = mock(Command.class);
+        when(cmd1.getName()).thenReturn("test1");
+        Command cmd2 = mock(Command.class);
+        when(cmd2.getName()).thenReturn("test2");
+
+        ServiceReference cmd1Reference = mock(ServiceReference.class);
+        ServiceReference cmd2Reference = mock(ServiceReference.class);
+
+        ServiceRegistration cmd1Reg = mock(ServiceRegistration.class);
+        when(cmd1Reg.getReference()).thenReturn(cmd1Reference);
+        ServiceRegistration cmd2Reg = mock(ServiceRegistration.class);
+        when(cmd2Reg.getReference()).thenReturn(cmd2Reference);
+
+        Hashtable<String,String> props1 = new Hashtable<>();
+        props1.put(Command.NAME, cmd1.getName());
+        Hashtable<String,String> props2 = new Hashtable<>();
+        props2.put(Command.NAME, cmd2.getName());
+
+        when(bundleContext.registerService(Command.class.getName(), cmd1, props1)).thenReturn(cmd1Reg);
+        when(bundleContext.registerService(Command.class.getName(), cmd2, props2)).thenReturn(cmd2Reg);
+
+        commandRegistry.registerCommands(Arrays.asList(cmd1, cmd2));
+
+        verify(bundleContext).registerService(Command.class.getName(), cmd1, props1);
+        verify(bundleContext).registerService(Command.class.getName(), cmd2, props2);
+
+        when(bundleContext.getService(eq(cmd1Reference))).thenReturn(cmd1);
+        when(bundleContext.getService(eq(cmd2Reference))).thenReturn(cmd2);
+
+        commandRegistry.unregisterCommands();
+
+        verify(bundleContext).getService(cmd1Reference);
+        verify(cmd1).disable();
+        verify(cmd1Reg).unregister();
+        verify(bundleContext).getService(cmd2Reference);
+        verify(cmd2).disable();
+        verify(cmd2Reg).unregister();
+
+        verifyNoMoreInteractions(bundleContext);
+    }
+
+    @Test
+    public void testGetCommand() throws InvalidSyntaxException {
+        ServiceReference ref1 = mock(ServiceReference.class);
+        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[] { ref1 });
+        Command cmd1 = mock(Command.class);
+        when(bundleContext.getService(ref1)).thenReturn(cmd1);
+
+        Command cmd = commandRegistry.getCommand("test1");
+
+        assertSame(cmd1, cmd);
+    }
+
+    @Test
+    public void testNotRegisteredCommand() throws InvalidSyntaxException {
+        ServiceReference ref1 = mock(ServiceReference.class);
+        Command cmd1 = mock(Command.class);
+        when(bundleContext.getService(ref1)).thenReturn(cmd1);
+
+        Command cmd = commandRegistry.getCommand("test1");
+
+        assertNull(cmd);
+    }
+
+    @Test
+    public void testNotRegisteredCommandEmptyList() throws InvalidSyntaxException {
+        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[0]);
+
+        Command cmd = commandRegistry.getCommand("test1");
+
+        assertNull(cmd);
+    }
+
+    @Test
+    public void testDoubleRegisteredCommand() throws InvalidSyntaxException {
+        ServiceReference ref1 = mock(ServiceReference.class);
+        ServiceReference ref2 = mock(ServiceReference.class);
+        Command cmd1 = mock(Command.class);
+        Command cmd2 = mock(Command.class);
+        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[] { ref1, ref2 });
+        when(bundleContext.getService(ref1)).thenReturn(cmd1);
+        when(bundleContext.getService(ref2)).thenReturn(cmd2);
+
+        Command cmd = commandRegistry.getCommand("test1");
+
+        assertSame(cmd1, cmd);
+    }
+
+    @Test(expected=InternalError.class)
+    public void testGetCommandInvalidSyntax() throws InvalidSyntaxException {
+        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenThrow(new InvalidSyntaxException("test", "test"));
+
+        commandRegistry.getCommand("test1");
+    }
+
+    @Test
+    public void testRegisteredCommands() throws InvalidSyntaxException {
+        ServiceReference ref1 = mock(ServiceReference.class);
+        ServiceReference ref2 = mock(ServiceReference.class);
+        Command cmd1 = mock(Command.class);
+        Command cmd2 = mock(Command.class);
+        when(bundleContext.getServiceReferences(Command.class.getName(), null)).thenReturn(new ServiceReference[] { ref1, ref2 });
+        when(bundleContext.getService(ref1)).thenReturn(cmd1);
+        when(bundleContext.getService(ref2)).thenReturn(cmd2);
+
+        Collection<Command> cmds = commandRegistry.getRegisteredCommands();
+
+        assertEquals(2, cmds.size());
+        assertTrue(cmds.contains(cmd1));
+        assertTrue(cmds.contains(cmd2));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/CommonCommandOptionsTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import org.junit.Test;
+
+public class CommonCommandOptionsTest {
+
+    @Test
+    public void verifyStorageCommandAddsDbUrlOption() {
+        TestCommand cmd = new TestCommand("test1");
+        cmd.setStorageRequired(true);
+
+        CommonCommandOptions commonOpts = new CommonCommandOptions();
+        Collection<ArgumentSpec> cmdOpts = commonOpts.getAcceptedOptionsFor(cmd);
+
+        assertTrue(cmdOpts.contains(new SimpleArgumentSpec("dbUrl", "d", "the URL of the storage to connect to", false, true)));
+    }
+
+    @Test
+    public void verifyLogLevelOption() {
+        TestCommand cmd = new TestCommand("test1");
+
+        CommonCommandOptions commonOpts = new CommonCommandOptions();
+        Collection<ArgumentSpec> cmdOpts = commonOpts.getAcceptedOptionsFor(cmd);
+
+        assertTrue(cmdOpts.contains(new SimpleArgumentSpec("logLevel", "log level", false, true)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/HelpCommandTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class HelpCommandTest {
+
+    private TestCommandContextFactory  ctxFactory;
+
+    @Before
+    public void setUp() {
+
+        ctxFactory = new TestCommandContextFactory();
+
+
+    }
+
+    @After
+    public void tearDown() {
+        ctxFactory = null;
+    }
+
+    @Test
+    public void testName() {
+        HelpCommand cmd = new HelpCommand();
+        assertEquals("help", cmd.getName());
+    }
+
+    @Test
+    public void verifyHelpNoArgPrintsListOfCommandsNoCommands() {
+
+        HelpCommand cmd = new HelpCommand();
+        Arguments args = mock(Arguments.class);
+        cmd.run(ctxFactory.createContext(args));
+        String expected = "list of commands:\n\n";
+        String actual = ctxFactory.getOutput();
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void verifyHelpNoArgPrintsListOfCommands2Commands() {
+
+        TestCommand cmd1 = new TestCommand("test1");
+        cmd1.setDescription("test command 1");
+        TestCommand cmd2 = new TestCommand("test2longname");
+        cmd2.setDescription("test command 2");
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1, cmd2));
+
+        HelpCommand cmd = new HelpCommand();
+        Arguments args = mock(Arguments.class);
+        cmd.run(ctxFactory.createContext(args));
+        String expected = "list of commands:\n\n"
+                        + " test1         test command 1\n"
+                        + " test2longname test command 2\n";
+        String actual = ctxFactory.getOutput();
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void verifyHelpKnownCmdPrintsCommandUsage() {
+        TestCommand cmd1 = new TestCommand("test1");
+        String usage = "test usage command 1";
+        cmd1.setUsage(usage);
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
+
+        HelpCommand cmd = new HelpCommand();
+        Arguments args = mock(Arguments.class);
+        when(args.getNonOptionArguments()).thenReturn(Arrays.asList("test1"));
+        cmd.run(ctxFactory.createContext(args));
+
+        String actual = ctxFactory.getOutput();
+        assertEquals("usage: test1 [--logLevel <arg>]\ntest usage command 1\n     --logLevel <arg>    log level\n", actual);
+    }
+
+    @Test
+    public void verifyHelpKnownStorageCmdPrintsCommandUsageWithDbUrl() {
+        TestCommand cmd1 = new TestCommand("test1");
+        String usage = "test usage command 1";
+        cmd1.setUsage(usage);
+        cmd1.setStorageRequired(true);
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
+
+        HelpCommand cmd = new HelpCommand();
+        Arguments args = mock(Arguments.class);
+        when(args.getNonOptionArguments()).thenReturn(Arrays.asList("test1"));
+        cmd.run(ctxFactory.createContext(args));
+
+        String actual = ctxFactory.getOutput();
+        assertEquals("usage: test1 [-d <arg>] [--logLevel <arg>]\ntest usage command 1\n  -d,--dbUrl <arg>       the URL of the storage to connect to\n     --logLevel <arg>    log level\n", actual);
+    }
+
+    @Test
+    public void verifyHelpUnknownCmdPrintsSummaries() {
+        TestCommand cmd1 = new TestCommand("test1");
+        cmd1.setUsage("test usage command 1");
+        cmd1.setDescription("test command 1");
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
+
+        HelpCommand cmd = new HelpCommand();
+        Arguments args = mock(Arguments.class);
+        cmd.run(ctxFactory.createContext(args));
+
+        String expected = "list of commands:\n\n"
+                        + " test1         test command 1\n";
+        String actual = ctxFactory.getOutput();
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testDescription() {
+        HelpCommand cmd = new HelpCommand();
+        assertEquals("show help for a given command or help overview", cmd.getDescription());
+    }
+
+    @Test
+    public void testUsage() {
+        HelpCommand cmd = new HelpCommand();
+        String expected = "show help for a given command or help overview";
+
+        assertEquals(expected, cmd.getUsage());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/LauncherTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+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.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.redhat.thermostat.test.TestTimerFactory;
+
+public class LauncherTest {
+
+    private static class TestCmd1 implements TestCommand.Handle {
+
+        @Override
+        public void run(CommandContext ctx) {
+            Arguments args = ctx.getArguments();
+            ctx.getConsole().getOutput().print(args.getArgument("arg1") + ", " + args.getArgument("arg2"));
+        }
+
+        @Override
+        public void stop() { /* N0-OP */ }
+
+    }
+
+    private static class TestCmd2 implements TestCommand.Handle {
+        @Override
+        public void run(CommandContext ctx) {
+            Arguments args = ctx.getArguments();
+            ctx.getConsole().getOutput().print(args.getArgument("arg4") + ": " + args.getArgument("arg3"));
+        }
+
+        @Override
+        public void stop() {
+            /* NO-OP */
+        }
+    }
+
+    private TestCommandContextFactory  ctxFactory;
+    private AppContextSetup appContextSetup;
+    private BundleContext bundleContext;
+    private TestTimerFactory timerFactory;
+
+    @Before
+    public void setUp() {
+
+        ApplicationContextUtil.resetApplicationContext();
+        timerFactory = new TestTimerFactory();
+        ApplicationContext.getInstance().setTimerFactory(timerFactory);
+        setupCommandContextFactory();
+
+        TestCommand cmd1 = new TestCommand("test1", new TestCmd1());
+        SimpleArgumentSpec arg1 = new SimpleArgumentSpec();
+        arg1.setName("arg1");
+        arg1.setUsingAdditionalArgument(true);
+        SimpleArgumentSpec arg2 = new SimpleArgumentSpec();
+        arg2.setName("arg2");
+        arg2.setUsingAdditionalArgument(true);
+        cmd1.addArguments(arg1, arg2);
+        cmd1.setDescription("description 1");
+        TestCommand cmd2 = new TestCommand("test2", new TestCmd2());
+        SimpleArgumentSpec arg3 = new SimpleArgumentSpec();
+        arg3.setName("arg3");
+        arg3.setUsingAdditionalArgument(true);
+        SimpleArgumentSpec arg4 = new SimpleArgumentSpec();
+        arg4.setName("arg4");
+        arg4.setUsingAdditionalArgument(true);
+        cmd2.addArguments(arg3, arg4);
+        cmd2.setDescription("description 2");
+
+        TestCommand cmd3 = new TestCommand("test3");
+        cmd3.setStorageRequired(true);
+        cmd3.setDescription("description 3");
+
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1, cmd2, cmd3, new HelpCommand()));
+
+    }
+
+    private void setupCommandContextFactory() {
+        appContextSetup = mock(AppContextSetup.class);
+        Bundle sysBundle = mock(Bundle.class);
+        bundleContext = mock(BundleContext.class);
+        when(bundleContext.getBundle(0)).thenReturn(sysBundle);
+        ctxFactory = new TestCommandContextFactory(bundleContext) {
+            @Override
+            protected AppContextSetup getAppContextSetup() {
+                return appContextSetup;
+            }
+        };
+    }
+
+
+    @After
+    public void tearDown() {
+        appContextSetup = null;
+        ctxFactory = null;
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @Test
+    public void testMain() {
+        runAndVerifyCommand(new String[] {"test1", "--arg1", "Hello", "--arg2", "World"}, "Hello, World");
+
+        ctxFactory.reset();
+
+        runAndVerifyCommand(new String[] {"test2", "--arg3", "Hello", "--arg4", "World"}, "World: Hello");
+    }
+
+    @Test
+    public void testMainNoArgs() {
+        String expected = "list of commands:\n\n"
+                        + " help          show help for a given command or help overview\n"
+                        + " test1         description 1\n"
+                        + " test2         description 2\n"
+                        + " test3         description 3\n";
+        runAndVerifyCommand(new String[0], expected);
+    }
+
+    @Test
+    public void verifySetLogLevel() {
+        runAndVerifyCommand(new String[] {"test1", "--logLevel", "WARNING", "--arg1", "Hello", "--arg2", "World"}, "Hello, World");
+        Logger globalLogger = Logger.getLogger("com.redhat.thermostat");
+        assertEquals(Level.WARNING, globalLogger.getLevel());
+    }
+
+    @Test
+    public void testMainBadCommand1() {
+        String expected = "unknown command '--help'\n"
+            + "list of commands:\n\n"
+            + " help          show help for a given command or help overview\n"
+            + " test1         description 1\n"
+            + " test2         description 2\n"
+            + " test3         description 3\n";
+        runAndVerifyCommand(new String[] {"--help"}, expected);
+    }
+
+    @Test
+    public void testMainBadCommand2() {
+        String expected = "unknown command '-help'\n"
+            + "list of commands:\n\n"
+            + " help          show help for a given command or help overview\n"
+            + " test1         description 1\n"
+            + " test2         description 2\n"
+            + " test3         description 3\n";
+        runAndVerifyCommand(new String[] {"-help"}, expected);
+    }
+
+    @Test
+    public void testMainBadCommand3() {
+        String expected = "unknown command 'foobarbaz'\n"
+            + "list of commands:\n\n"
+            + " help          show help for a given command or help overview\n"
+            + " test1         description 1\n"
+            + " test2         description 2\n"
+            + " test3         description 3\n";
+        runAndVerifyCommand(new String[] {"foobarbaz"}, expected);
+    }
+
+    @Test
+    public void testMainBadCommand4() {
+        String expected = "unknown command 'foo'\n"
+            + "list of commands:\n\n"
+            + " help          show help for a given command or help overview\n"
+            + " test1         description 1\n"
+            + " test2         description 2\n"
+            + " test3         description 3\n";
+        runAndVerifyCommand(new String[] {"foo",  "--bar", "baz"}, expected);
+    }
+
+    @Test
+    public void testMainExceptionInCommand() {
+        TestCommand errorCmd = new TestCommand("error", new TestCommand.Handle() {
+
+            @Override
+            public void run(CommandContext ctx) throws CommandException {
+                throw new CommandException("test error");
+            }
+
+            @Override
+            public void stop() { /* NO-OP */ }
+        });
+        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(errorCmd));
+
+        new LauncherImpl(ctxFactory).run(new String[] { "error" });
+        assertEquals("test error\n", ctxFactory.getError());
+
+    }
+
+    private void runAndVerifyCommand(String[] args, String expected) {
+        new LauncherImpl(ctxFactory).run(args);
+        assertEquals(expected, ctxFactory.getOutput());
+        assertTrue(timerFactory.isShutdown());
+    }
+
+    @Test
+    public void verifyStorageCommandSetsUpDAOFactory() {
+        new LauncherImpl(ctxFactory).run(new String[] { "test3" , "--dbUrl", "mongo://fluff:12345" });
+        verify(appContextSetup).setupAppContext("mongo://fluff:12345");
+    }
+
+    public void verifyPrefsAreUsed() {
+        ClientPreferences prefs = mock(ClientPreferences.class);
+        when(prefs.getConnectionUrl()).thenReturn("mongo://fluff:12345");
+        LauncherImpl l = new LauncherImpl(ctxFactory);
+        l.setPreferences(prefs);
+        l.run(new String[] { "test3" });
+        verify(appContextSetup).setupAppContext("mongo://fluff:12345");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentSpecTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimpleArgumentSpecTest {
+
+    private SimpleArgumentSpec spec;
+    private SimpleArgumentSpec other;
+
+    @Before
+    public void setUp() {
+        spec = new SimpleArgumentSpec();
+        other = new SimpleArgumentSpec();
+    }
+
+    @After
+    public void tearDown() {
+        spec = null;
+        other = null;
+    }
+
+    @Test
+    public void testName() {
+        spec.setName("test1");
+        assertEquals("test1", spec.getName());
+        spec.setName("test2");
+        assertEquals("test2", spec.getName());
+    }
+
+    @Test
+    public void testDescription() {
+        spec.setDescription("test1");
+        assertEquals("test1", spec.getDescription());
+        spec.setDescription("test2");
+        assertEquals("test2", spec.getDescription());
+    }
+
+    @Test
+    public void testRequired() {
+        spec.setRequired(true);
+        assertTrue(spec.isRequired());
+        spec.setRequired(false);
+        assertFalse(spec.isRequired());
+    }
+
+    @Test
+    public void testUsesAdditionalArgument() {
+        spec.setUsingAdditionalArgument(true);
+        assertTrue(spec.isUsingAdditionalArgument());
+        spec.setUsingAdditionalArgument(false);
+        assertFalse(spec.isUsingAdditionalArgument());
+    }
+
+    @Test
+    public void testShortOption() {
+        spec.setShortOption("test1");
+        assertEquals("test1", spec.getShortOption());
+        spec.setShortOption("test2");
+        assertEquals("test2", spec.getShortOption());
+    }
+
+    @Test
+    public void testEquals() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        assertTrue(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsUnequalName() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        other.setName("fluff");
+
+        assertFalse(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsUnequalDescription() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        other.setDescription("fluff");
+
+        assertFalse(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsUnequalUsingAdditionalArgument() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        other.setUsingAdditionalArgument(false);
+
+        assertFalse(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsUnequalRequired() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        other.setRequired(false);
+
+        assertFalse(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsUnequalShortOption() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        other.setShortOption("fluff");
+
+        assertFalse(spec.equals(other));
+    }
+
+    @Test
+    public void testEqualsNull() {
+        prepareSpecForEqualsTest(spec);
+
+        assertFalse(spec.equals(null));
+    }
+
+    @Test
+    public void testHashCode() {
+        prepareSpecForEqualsTest(spec);
+        prepareSpecForEqualsTest(other);
+
+        assertEquals(spec.hashCode(), other.hashCode());
+    }
+
+    private void prepareSpecForEqualsTest(SimpleArgumentSpec spec) {
+        spec.setName("test");
+        spec.setDescription("description");
+        spec.setUsingAdditionalArgument(true);
+        spec.setRequired(true);
+        spec.setShortOption("shortOption");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentsTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.SimpleArguments;
+
+public class SimpleArgumentsTest {
+
+    private SimpleArguments args;
+
+    @Before
+    public void setUp() {
+        args = new SimpleArguments();
+    }
+
+    @After
+    public void tearDown() {
+        args = null;
+    }
+
+    @Test
+    public void testSimpleArgs() {
+        args.addArgument("fluff", "fluffor");
+        assertTrue(args.hasArgument("fluff"));
+        assertEquals("fluffor", args.getArgument("fluff"));
+        assertFalse(args.hasArgument("foo"));
+        assertNull(args.getArgument("bar"));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/TestCommand.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.cli;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+
+class TestCommand implements Command {
+
+    private String name;
+    private Handle handle;
+    private String description;
+    private String usage;
+    private boolean storageRequired;
+
+    private List<ArgumentSpec> arguments = new LinkedList<ArgumentSpec>();
+
+    static interface Handle {
+        public void run(CommandContext ctx) throws CommandException;
+        public void stop();
+    }
+
+    TestCommand(String name) {
+        this(name, null);
+    }
+
+    TestCommand(String name, Handle r) {
+        this.name = name;
+        this.handle = r;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        if (handle != null) {
+            handle.run(ctx);
+        }
+    }
+
+    @Override
+    public void disable() {
+        if (handle != null) {
+            handle.stop();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    void setDescription(String desc) {
+        description = desc;
+    }
+
+    @Override
+    public String getUsage() {
+        return usage;
+    }
+
+    void setUsage(String usage) {
+        this.usage = usage;
+    }
+
+    @Override
+    public Collection<ArgumentSpec> getAcceptedArguments() {
+        return arguments;
+    }
+
+    void addArguments(ArgumentSpec... arguments) {
+        this.arguments.addAll(Arrays.asList(arguments));
+    }
+
+    public boolean isStorageRequired() {
+        return storageRequired;
+    }
+
+    void setStorageRequired(boolean storageRequired) {
+        this.storageRequired = storageRequired;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/config/ClientPreferencesTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+import static org.junit.Assert.assertEquals;
+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.util.prefs.Preferences;
+
+import org.junit.Test;
+
+public class ClientPreferencesTest {
+
+    @Test
+    public void testGetConnectionUrl() {
+
+        Preferences prefs = mock(Preferences.class);
+        when(prefs.get(eq("connection-url"), any(String.class))).thenReturn("mock-value");
+
+        ClientPreferences clientPrefs = new ClientPreferences(prefs);
+        String value = clientPrefs.getConnectionUrl();
+
+        assertEquals("mock-value", value);
+        verify(prefs).get(eq("connection-url"), any(String.class));
+    }
+
+    @Test
+    public void testSetConnectionUrl() {
+
+        Preferences prefs = mock(Preferences.class);
+
+        ClientPreferences clientPrefs = new ClientPreferences(prefs);
+        clientPrefs.setConnectionUrl("test");
+
+        verify(prefs).put(eq("connection-url"), eq("test"));
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/config/ConfigUtilsTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.config;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ConfigUtilsTest {
+    
+    @Before
+    public void setUp() throws IOException {
+        System.setProperty("THERMOSTAT_HOME", "/tmp/");
+    }
+    
+    @Test
+    public void testLocations() throws InvalidConfigurationException, IOException {
+        String path = System.getProperty("THERMOSTAT_HOME");
+        char s = File.separatorChar;
+        
+        Assert.assertEquals(path, ConfigUtils.getThermostatHome());
+        
+        Assert.assertEquals(path + "agent" + s + "agent.properties",
+                            ConfigUtils.getAgentConfigurationFile().getCanonicalPath());
+        Assert.assertEquals(path + "backends", ConfigUtils.getBackendsBaseDirectory().getCanonicalPath());
+        Assert.assertEquals(path + "client", ConfigUtils.getClientConfigurationDirectory().getCanonicalPath());
+        Assert.assertEquals(path + "client" + s + "cli-history", ConfigUtils.getHistoryFile().getCanonicalPath());
+        Assert.assertEquals(path + "storage", ConfigUtils.getStorageBaseDirectory().getCanonicalPath());
+        Assert.assertEquals(path + "storage" + s + "db.properties",
+                            ConfigUtils.getStorageConfigurationFile().getCanonicalPath());
+        Assert.assertEquals(path + "storage" + s + "db",
+                ConfigUtils.getStorageDirectory().getCanonicalPath());
+        Assert.assertEquals(path + "storage" + s + "logs" + s + "db.log",
+                ConfigUtils.getStorageLogFile().getCanonicalPath());
+        Assert.assertEquals(path + "storage" + s + "run" + s + "db.pid",
+                ConfigUtils.getStoragePidFile().getCanonicalPath());
+        
+        Assert.assertEquals(path + "backends" + s + "system" + s + "backend.properties",
+                            ConfigUtils.getBackendPropertyFile("system").getCanonicalPath());
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class CpuStatConverterTest {
+
+    @Test
+    public void testToChunk() {
+        CpuStat stat = new CpuStat(10, 5.0, 10.0, 15.0);
+        Chunk chunk = new CpuStatConverter().toChunk(stat);
+        assertNotNull(chunk);
+        assertEquals("cpu-stats", chunk.getCategory().getName());
+        assertEquals((Long) 10L, chunk.get(Key.TIMESTAMP));
+        assertEquals(5.0, chunk.get(CpuStatDAO.cpu5LoadKey), 0.001);
+        assertEquals(10.0, chunk.get(CpuStatDAO.cpu10LoadKey), 0.001);
+        assertEquals(15.0, chunk.get(CpuStatDAO.cpu15LoadKey), 0.001);
+    }
+
+    @Test
+    public void testFromChunk() {
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 10L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+        CpuStat stat = new CpuStatConverter().fromChunk(chunk);
+        assertNotNull(stat);
+        assertEquals(10L, stat.getTimeStamp());
+        assertEquals(5.0, stat.getLoad5(), 0.001);
+        assertEquals(10.0, stat.getLoad10(), 0.001);
+        assertEquals(15.0, stat.getLoad15(), 0.001);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+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.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class CpuStatDAOTest {
+
+    @Test
+    public void testCategory() {
+        assertEquals("cpu-stats", CpuStatDAO.cpuStatCategory.getName());
+        Collection<Key<?>> keys = CpuStatDAO.cpuStatCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<Double>("5load", false)));
+        assertTrue(keys.contains(new Key<Double>("10load", false)));
+        assertTrue(keys.contains(new Key<Double>("15load", false)));
+        assertEquals(5, keys.size());
+    }
+
+    @Test
+    public void testGetLatestCpuStats() {
+
+        Cursor cursor = mock(Cursor.class);
+        Storage storage = mock(Storage.class);
+        HostRef hostRef = mock(HostRef.class);
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        List<CpuStat> cpuStats = dao.getLatestCpuStats(hostRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, cpuStats.size());
+        CpuStat stat = cpuStats.get(0);
+        assertEquals(1234L, stat.getTimeStamp());
+        assertEquals(5.0, stat.getLoad5(), 0.001);
+        assertEquals(10.0, stat.getLoad10(), 0.001);
+        assertEquals(15.0, stat.getLoad15(), 0.001);
+    }
+
+    @Test
+    public void testGetLatestCpuStatsTwice() {
+
+        Cursor cursor = mock(Cursor.class);
+        Storage storage = mock(Storage.class);
+        HostRef hostRef = mock(HostRef.class);
+
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        dao.getLatestCpuStats(hostRef);
+        dao.getLatestCpuStats(hostRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 1234", arg.getValue().get(Key.WHERE));
+    }
+
+    @Test
+    public void testPutCpuStat() {
+        Storage storage = mock(Storage.class);
+        CpuStat stat = new CpuStat(1, 5.0, 15.0, 10.0);
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+        dao.putCpuStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(CpuStatDAO.cpuStatCategory, chunk.getCategory());
+        assertEquals((Long) 1L, chunk.get(Key.TIMESTAMP));
+        assertEquals((Double) 5.0, chunk.get(CpuStatDAO.cpu5LoadKey));
+        assertEquals((Double) 15.0, chunk.get(CpuStatDAO.cpu10LoadKey));
+        assertEquals((Double) 10.0, chunk.get(CpuStatDAO.cpu15LoadKey));
+    }
+
+    @Test
+    public void testGetCount() {
+        Storage storage = mock(Storage.class);
+        when(storage.getCount(any(Category.class))).thenReturn(5L);
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+        Long count = dao.getCount();
+        assertEquals((Long) 5L, count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class HostInfoConverterTest {
+
+    @Test
+    public void testHostInfoToChunk() {
+        HostInfo info = new HostInfo("a-host", "an-os", "a-kernel", "a-cpu", 9, 99);
+
+        Chunk chunk = new HostInfoConverter().toChunk(info);
+
+        assertEquals("host-info", chunk.getCategory().getName());
+        assertEquals("a-host", chunk.get(new Key<String>("hostname", true)));
+        assertEquals("an-os", chunk.get(new Key<String>("os_name", false)));
+        assertEquals("a-kernel", chunk.get(new Key<String>("os_kernel", false)));
+        assertEquals("a-cpu", chunk.get(new Key<String>("cpu_model", false)));
+        assertEquals((Integer)9, chunk.get(new Key<Integer>("cpu_num", false)));
+        assertEquals((Long) 99L, chunk.get(new Key<Long>("memory_total", false)));
+    }
+
+    @Test
+    public void testChunktoHostInfo() {
+        final String HOST_NAME = "a host name";
+        final String OS_NAME = "some os";
+        final String OS_KERNEL = "some kernel";
+        final String CPU_MODEL = "some cpu that runs fast";
+        final int CPU_NUM = -1;
+        final long MEMORY_TOTAL = 0xCAFEBABEl;
+
+
+        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        chunk.put(HostInfoDAO.hostNameKey, HOST_NAME);
+        chunk.put(HostInfoDAO.osNameKey, OS_NAME);
+        chunk.put(HostInfoDAO.osKernelKey, OS_KERNEL);
+        chunk.put(HostInfoDAO.cpuModelKey, CPU_MODEL);
+        chunk.put(HostInfoDAO.cpuCountKey, CPU_NUM);
+        chunk.put(HostInfoDAO.hostMemoryTotalKey, MEMORY_TOTAL);
+
+        HostInfo info = new HostInfoConverter().fromChunk(chunk);
+        assertNotNull(info);
+        assertEquals(HOST_NAME, info.getHostname());
+        assertEquals(OS_NAME, info.getOsName());
+        assertEquals(OS_KERNEL, info.getOsKernel());
+        assertEquals(CPU_MODEL, info.getCpuModel());
+        assertEquals(CPU_NUM, info.getCpuCount());
+        assertEquals(MEMORY_TOTAL, info.getTotalMemory());
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.times;
+
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.storage.AgentInformation;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class HostInfoDAOTest {
+
+    private static final String HOST_NAME = "a host name";
+    private static final String OS_NAME = "some os";
+    private static final String OS_KERNEL = "some kernel";
+    private static final String CPU_MODEL = "some cpu that runs fast";
+    private static final int CPU_NUM = -1;
+    private static final long MEMORY_TOTAL = 0xCAFEBABEl;
+
+    @Test
+    public void testCategory() {
+        assertEquals("host-info", HostInfoDAO.hostInfoCategory.getName());
+        Collection<Key<?>> keys = HostInfoDAO.hostInfoCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<String>("hostname", true)));
+        assertTrue(keys.contains(new Key<String>("os_name", false)));
+        assertTrue(keys.contains(new Key<String>("os_kernel", false)));
+        assertTrue(keys.contains(new Key<String>("cpu_model", false)));
+        assertTrue(keys.contains(new Key<Integer>("cpu_num", false)));
+        assertTrue(keys.contains(new Key<Long>("memory_total", false)));
+        assertEquals(7, keys.size());
+    }
+
+    @Test
+    public void testGetHostInfo() {
+
+        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        chunk.put(HostInfoDAO.hostNameKey, HOST_NAME);
+        chunk.put(HostInfoDAO.osNameKey, OS_NAME);
+        chunk.put(HostInfoDAO.osKernelKey, OS_KERNEL);
+        chunk.put(HostInfoDAO.cpuModelKey, CPU_MODEL);
+        chunk.put(HostInfoDAO.cpuCountKey, CPU_NUM);
+        chunk.put(HostInfoDAO.hostMemoryTotalKey, MEMORY_TOTAL);
+
+        Storage storage = mock(Storage.class);
+        when(storage.find(any(Chunk.class))).thenReturn(chunk);
+
+        HostInfo info = new HostInfoDAOImpl(storage).getHostInfo(new HostRef("some uid", HOST_NAME));
+        assertNotNull(info);
+        assertEquals(HOST_NAME, info.getHostname());
+        assertEquals(OS_NAME, info.getOsName());
+        assertEquals(OS_KERNEL, info.getOsKernel());
+        assertEquals(CPU_MODEL, info.getCpuModel());
+        assertEquals(CPU_NUM, info.getCpuCount());
+        assertEquals(MEMORY_TOTAL, info.getTotalMemory());
+    }
+
+    @Test
+    public void testGetHostsSingleHost() {
+
+        Storage storage = setupStorageForSingleHost();
+
+        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
+        Collection<HostRef> hosts = hostsDAO.getHosts();
+
+        assertEquals(1, hosts.size());
+        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
+    }
+
+    private Storage setupStorageForSingleHost() {
+
+        Chunk hostConfig = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig.put(HostInfoDAO.hostNameKey, "fluffhost1");
+        hostConfig.put(Key.AGENT_ID, "123");
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(hostConfig);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+        
+        return storage;
+    }
+
+    @Test
+    public void testGetHosts3Hosts() {
+
+        Storage storage = setupStorageFor3Hosts();
+
+        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
+        Collection<HostRef> hosts = hostsDAO.getHosts();
+
+        assertEquals(3, hosts.size());
+        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
+        assertTrue(hosts.contains(new HostRef("456", "fluffhost2")));
+        assertTrue(hosts.contains(new HostRef("789", "fluffhost3")));
+    }
+
+    private Storage setupStorageFor3Hosts() {
+
+        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
+        hostConfig1.put(Key.AGENT_ID, "123");
+        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
+        hostConfig2.put(Key.AGENT_ID, "456");
+        Chunk hostConfig3 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig3.put(HostInfoDAO.hostNameKey, "fluffhost3");
+        hostConfig3.put(Key.AGENT_ID, "789");
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(hostConfig1).thenReturn(hostConfig2).thenReturn(hostConfig3);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+        
+        return storage;
+    }
+
+    @Test
+    public void testPutHostInfo() {
+        Storage storage = mock(Storage.class);
+        HostInfo info = new HostInfo(HOST_NAME, OS_NAME, OS_KERNEL, CPU_MODEL, CPU_NUM, MEMORY_TOTAL);
+        HostInfoDAO dao = new HostInfoDAOImpl(storage);
+        dao.putHostInfo(info);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(HostInfoDAO.hostInfoCategory, chunk.getCategory());
+        assertEquals(HOST_NAME, chunk.get(HostInfoDAO.hostNameKey));
+        assertEquals(OS_NAME, chunk.get(HostInfoDAO.osNameKey));
+        assertEquals(OS_KERNEL, chunk.get(HostInfoDAO.osKernelKey));
+        assertEquals(CPU_MODEL, chunk.get(HostInfoDAO.cpuModelKey));
+        assertEquals((Integer) CPU_NUM, chunk.get(HostInfoDAO.cpuCountKey));
+        assertEquals((Long) MEMORY_TOTAL, chunk.get(HostInfoDAO.hostMemoryTotalKey));
+    }
+
+    @Test
+    public void testGetCount() {
+        Storage storage = mock(Storage.class);
+        when(storage.getCount(any(Category.class))).thenReturn(5L);
+        HostInfoDAO dao = new HostInfoDAOImpl(storage);
+        Long count = dao.getCount();
+        assertEquals((Long) 5L, count);
+    }
+    
+    @Test
+    public void getAliveHostSingle() {
+        Storage storage = setupStorageForSingleAliveHost();
+
+        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
+        Collection<HostRef> hosts = hostsDAO.getAliveHosts();
+
+        // cursor 3 from the above storage should not be used
+        assertEquals(1, hosts.size());
+        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
+        verify(storage, times(2)).findAll(any(Chunk.class));
+    }
+    
+    private Storage setupStorageForSingleAliveHost() {
+        
+        // agents
+        
+        Chunk agentConfig1 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
+        agentConfig1.put(Key.AGENT_ID, "123");
+        agentConfig1.put(AgentInformation.AGENT_ALIVE_KEY, true);
+        
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(agentConfig1);
+        
+        // hosts
+        
+        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
+        hostConfig1.put(Key.AGENT_ID, "123");
+        
+        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
+        hostConfig2.put(Key.AGENT_ID, "456");
+        
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(hostConfig1);
+
+        Cursor cursor3 = mock(Cursor.class);
+        when(cursor3.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor3.next()).thenReturn(hostConfig2);
+        
+        // storage
+        
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1).thenReturn(cursor2).thenReturn(cursor3);
+        
+        return storage;
+    }
+    
+    @Test
+    public void getAliveHost3() {
+        Storage storage = setupStorageForSingleAliveHost3();
+
+        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
+        Collection<HostRef> hosts = hostsDAO.getAliveHosts();
+
+        // cursor 3 from the above storage should not be used
+        assertEquals(3, hosts.size());
+        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
+        assertTrue(hosts.contains(new HostRef("456", "fluffhost2")));
+        assertTrue(hosts.contains(new HostRef("678", "fluffhost3")));
+        verify(storage, times(4)).findAll(any(Chunk.class));
+    }
+    
+    private Storage setupStorageForSingleAliveHost3() {
+        
+        // agents
+        
+        Chunk agentConfig1 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
+        agentConfig1.put(Key.AGENT_ID, "123");
+        agentConfig1.put(AgentInformation.AGENT_ALIVE_KEY, true);
+        
+        Chunk agentConfig2 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
+        agentConfig2.put(Key.AGENT_ID, "456");
+        agentConfig2.put(AgentInformation.AGENT_ALIVE_KEY, true);
+        
+        Chunk agentConfig3 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
+        agentConfig3.put(Key.AGENT_ID, "678");
+        agentConfig3.put(AgentInformation.AGENT_ALIVE_KEY, true);
+        
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(agentConfig1).thenReturn(agentConfig2).thenReturn(agentConfig3);
+        
+        // hosts
+        
+        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
+        hostConfig1.put(Key.AGENT_ID, "123");
+        
+        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
+        hostConfig2.put(Key.AGENT_ID, "456");
+        
+        Chunk hostConfig3 = new Chunk(HostInfoDAO.hostInfoCategory, false);
+        hostConfig3.put(HostInfoDAO.hostNameKey, "fluffhost3");
+        hostConfig3.put(Key.AGENT_ID, "678");
+        
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(hostConfig1);
+
+        Cursor cursor3 = mock(Cursor.class);
+        when(cursor3.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor3.next()).thenReturn(hostConfig2);
+        
+        Cursor cursor4 = mock(Cursor.class);
+        when(cursor4.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor4.next()).thenReturn(hostConfig3);
+        
+        // storage
+        
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1).
+                                                thenReturn(cursor2).
+                                                thenReturn(cursor3).
+                                                thenReturn(cursor4);
+        
+        return storage;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+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 static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.any;
+
+public class HostLatestPojoListGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final String CATEGORY_NAME = "hostcategory";
+    // Make this one static so we don't get IllegalStateException from trying
+    // to make category of same name while running tests in same classloader.
+    private static final Category cat =  new Category(CATEGORY_NAME);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+    private static long t3 = 10;
+
+    private static double load5_1 = 2.0;
+    private static double load5_2 = 6.0;
+    private static double load5_3 = 11.0;
+
+    private static double load10_1 = 3.0;
+    private static double load10_2 = 7.0;
+    private static double load10_3 = 12.0;
+
+    private static double load15_1 = 4.0;
+    private static double load15_2 = 8.0;
+    private static double load15_3 = 13.0;
+
+    private HostRef ref;
+    private Converter<CpuStat> converter;
+    private Chunk result1, result2, result3;
+
+    @Before
+    public void setUp() {
+        ref = new HostRef(AGENT_ID, HOSTNAME);
+        converter = new CpuStatConverter();
+        result1 = new Chunk(cat, false);
+        result1.put(Key.AGENT_ID, AGENT_ID);
+        result1.put(Key.TIMESTAMP, t1);
+        result1.put(CpuStatDAO.cpu5LoadKey, load5_1);
+        result1.put(CpuStatDAO.cpu10LoadKey, load10_1);
+        result1.put(CpuStatDAO.cpu15LoadKey, load15_1);
+        result2 = new Chunk(cat, false);
+        result2.put(Key.AGENT_ID, AGENT_ID);
+        result2.put(Key.TIMESTAMP, t2);
+        result2.put(CpuStatDAO.cpu5LoadKey, load5_2);
+        result2.put(CpuStatDAO.cpu10LoadKey, load10_2);
+        result2.put(CpuStatDAO.cpu15LoadKey, load15_2);
+        result3 = new Chunk(cat, false);
+        result3.put(Key.AGENT_ID, AGENT_ID);
+        result3.put(Key.TIMESTAMP, t3);
+        result3.put(CpuStatDAO.cpu5LoadKey, load5_3);
+        result3.put(CpuStatDAO.cpu10LoadKey, load10_3);
+        result3.put(CpuStatDAO.cpu15LoadKey, load15_3);
+    }
+
+    @Test
+    public void testBuildQuery() {
+        Storage storage = mock(Storage.class);
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(1, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertFalse(query.getKeys().contains(Key.WHERE));
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+    }
+
+    @Test
+    public void testBuildQueryPopulatesUpdateTimes() {
+        Storage storage = mock(Storage.class);
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        getter.buildQuery(); // Ignore first return value.
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(2, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.WHERE));
+        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
+    }
+
+    @Test
+    public void testGetLatest() {
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+
+        List<CpuStat> stats = getter.getLatest();
+
+        assertNotNull(stats);
+        assertEquals(2, stats.size());
+        CpuStat stat1 = stats.get(0);
+        assertEquals(t1, stat1.getTimeStamp());
+        assertEquals(load5_1, stat1.getLoad5(), 0.001);
+        assertEquals(load10_1, stat1.getLoad10(), 0.001);
+        assertEquals(load15_1, stat1.getLoad15(), 0.001);
+        CpuStat stat2 = stats.get(1);
+        assertEquals(t2, stat2.getTimeStamp());
+        assertEquals(load5_2, stat2.getLoad5(), 0.001);
+        assertEquals(load10_2, stat2.getLoad10(), 0.001);
+        assertEquals(load15_2, stat2.getLoad15(), 0.001);
+    }
+
+    @Test
+    public void testGetLatestMultipleCalls() {
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(result3);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
+
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        getter.getLatest();
+        getter.getLatest();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        List<Chunk> queries = arg.getAllValues();
+
+        assertEquals(2, queries.size());
+        Chunk query = queries.get(1);
+        assertNotNull(query);
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
+    }
+
+    @After
+    public void tearDown() {
+        ref = null;
+        converter = null;
+        result1 = null;
+        result2 = null;
+        result3 = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class MemoryStatConverterTest {
+
+    @Test
+    public void testMemoryStatToChunk() {
+        MemoryStat stat = new MemoryStat(0, 1, 2, 3, 4, 5, 6, 7);
+
+        Chunk chunk = new MemoryStatConverter().toChunk(stat);
+
+        assertEquals((Long) 0l, chunk.get(Key.TIMESTAMP));
+        assertEquals((Long) 1l, chunk.get(new Key<Long>("total", false)));
+        assertEquals((Long) 2l, chunk.get(new Key<Long>("free", false)));
+        assertEquals((Long) 3l, chunk.get(new Key<Long>("buffers", false)));
+        assertEquals((Long) 4l, chunk.get(new Key<Long>("cached", false)));
+        assertEquals((Long) 5l, chunk.get(new Key<Long>("swap-total", false)));
+        assertEquals((Long) 6l, chunk.get(new Key<Long>("swap-free", false)));
+        assertEquals((Long) 7l, chunk.get(new Key<Long>("commit-limit", false)));
+    }
+
+    @Test
+    public void testChunkToMemoryStat() {
+        long TIMESTAMP = 1;
+        long TOTAL = 2;
+        long FREE = 3;
+        long BUFFERS = 4;
+        long CACHED = 5;
+        long SWAP_TOTAL = 6;
+        long SWAP_FREE = 7;
+        long COMMIT_LIMIT = 8;
+
+        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
+        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
+        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
+        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
+        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
+        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
+        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
+
+        MemoryStat stat = new MemoryStatConverter().fromChunk(chunk);
+
+        assertEquals(TIMESTAMP, stat.getTimeStamp());
+        assertEquals(TOTAL, stat.getTotal());
+        assertEquals(FREE, stat.getFree());
+        assertEquals(BUFFERS, stat.getBuffers());
+        assertEquals(CACHED, stat.getCached());
+        assertEquals(SWAP_TOTAL, stat.getSwapTotal());
+        assertEquals(SWAP_FREE, stat.getSwapFree());
+        assertEquals(COMMIT_LIMIT, stat.getCommitLimit());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+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.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.MemoryStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class MemoryStatDAOTest {
+
+
+    private static long TIMESTAMP = 1;
+    private static long TOTAL = 2;
+    private static long FREE = 3;
+    private static long BUFFERS = 4;
+    private static long CACHED = 5;
+    private static long SWAP_TOTAL = 6;
+    private static long SWAP_FREE = 7;
+    private static long COMMIT_LIMIT = 8;
+
+    @Test
+    public void testCategory() {
+        assertEquals("memory-stats", MemoryStatDAO.memoryStatCategory.getName());
+        Collection<Key<?>> keys = MemoryStatDAO.memoryStatCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<Long>("total", false)));
+        assertTrue(keys.contains(new Key<Long>("free", false)));
+        assertTrue(keys.contains(new Key<Long>("buffers", false)));
+        assertTrue(keys.contains(new Key<Long>("cached", false)));
+        assertTrue(keys.contains(new Key<Long>("swap-total", false)));
+        assertTrue(keys.contains(new Key<Long>("swap-free", false)));
+        assertTrue(keys.contains(new Key<Long>("commit-limit", false)));
+        assertEquals(9, keys.size());
+
+    }
+
+    @Test
+    public void testGetLatestMemoryStats() {
+
+        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
+        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
+        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
+        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
+        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
+        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
+        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        List<MemoryStat> memoryStats = dao.getLatestMemoryStats(hostRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, memoryStats.size());
+        MemoryStat stat = memoryStats.get(0);
+
+        assertEquals(TIMESTAMP, stat.getTimeStamp());
+        assertEquals(TOTAL, stat.getTotal());
+        assertEquals(FREE, stat.getFree());
+        assertEquals(BUFFERS, stat.getBuffers());
+        assertEquals(CACHED, stat.getCached());
+        assertEquals(SWAP_TOTAL, stat.getSwapTotal());
+        assertEquals(SWAP_FREE, stat.getSwapFree());
+        assertEquals(COMMIT_LIMIT, stat.getCommitLimit());
+    }
+
+    @Test
+    public void testGetLatestMemoryStatsTwice() {
+
+        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
+        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
+        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
+        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
+        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
+        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
+        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        dao.getLatestMemoryStats(hostRef);
+        dao.getLatestMemoryStats(hostRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 1", arg.getValue().get(new Key<String>("$where", false)));
+    }
+
+    @Test
+    public void testPutHostInfo() {
+        Storage storage = mock(Storage.class);
+        MemoryStat stat = new MemoryStat(TIMESTAMP, TOTAL, FREE, BUFFERS, CACHED, SWAP_TOTAL, SWAP_FREE, COMMIT_LIMIT);
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        dao.putMemoryStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(MemoryStatDAO.memoryStatCategory, chunk.getCategory());
+        assertEquals((Long) TIMESTAMP, chunk.get(Key.TIMESTAMP));
+        assertEquals((Long) TOTAL, chunk.get(MemoryStatDAO.memoryTotalKey));
+        assertEquals((Long) FREE, chunk.get(MemoryStatDAO.memoryFreeKey));
+        assertEquals((Long) BUFFERS, chunk.get(MemoryStatDAO.memoryBuffersKey));
+        assertEquals((Long) CACHED, chunk.get(MemoryStatDAO.memoryCachedKey));
+        assertEquals((Long) SWAP_TOTAL, chunk.get(MemoryStatDAO.memorySwapTotalKey));
+        assertEquals((Long) SWAP_FREE, chunk.get(MemoryStatDAO.memorySwapFreeKey));
+        assertEquals((Long) COMMIT_LIMIT, chunk.get(MemoryStatDAO.memoryCommitLimitKey));
+    }
+
+    @Test
+    public void testGetCount() {
+        Storage storage = mock(Storage.class);
+        when(storage.getCount(any(Category.class))).thenReturn(5L);
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        Long count = dao.getCount();
+        assertEquals((Long) 5L, count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Storage;
+import com.redhat.thermostat.common.storage.StorageProvider;
+
+public class MongoDAOFactoryTest {
+
+    private Storage storage;
+    private Connection connection;
+    private StorageProvider provider;
+    private DAOFactory daoFactory;
+    HostRef hostRef;
+    VmRef vmRef;
+
+    @Before
+    public void setUp() {
+        storage = mock(Storage.class);
+        connection = mock(Connection.class);
+        when(storage.getConnection()).thenReturn(connection);
+        when(connection.isConnected()).thenReturn(true);
+        provider = mock(StorageProvider.class);
+        when(provider.createStorage()).thenReturn(storage);
+        hostRef = mock(HostRef.class);
+        vmRef = mock(VmRef.class);
+        daoFactory = new MongoDAOFactory(provider);
+    }
+
+    @Test
+    public void testGetConnection() {
+        assertSame(storage, daoFactory.getStorage());
+    }
+
+    @Test
+    public void testGetVmClassStatsDAO() {
+        VmClassStatDAO dao = daoFactory.getVmClassStatsDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetVmGcStatDAO() {
+        VmGcStatDAO dao = daoFactory.getVmGcStatDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetVmInfoDAO() {
+        VmInfoDAO dao = daoFactory.getVmInfoDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetVmMemoryStatDAO() {
+        VmMemoryStatDAO dao = daoFactory.getVmMemoryStatDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetHostInfoDAO() {
+        HostInfoDAO dao = daoFactory.getHostInfoDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetCpuStatDAO() {
+        CpuStatDAO dao = daoFactory.getCpuStatDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetMemoryStatDAO() {
+        MemoryStatDAO dao = daoFactory.getMemoryStatDAO();
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetNetworkInterfaceInfoDAO() {
+        NetworkInterfaceInfoDAO dao = daoFactory.getNetworkInterfaceInfoDAO();
+        assertNotNull(dao);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class NetworkInterfaceInfoConverterTest {
+
+    @Test
+    public void testNetworkInfoToChunk() {
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo("eth0");
+        info.setIp4Addr("4");
+        info.setIp6Addr("6");
+
+        Chunk chunk = new NetworkInterfaceInfoConverter().toChunk(info);
+
+        assertEquals("network-info", chunk.getCategory().getName());
+        assertEquals("eth0", chunk.get(new Key<String>("iface", true)));
+        assertEquals("4", chunk.get(new Key<String>("ipv4addr", false)));
+        assertEquals("6", chunk.get(new Key<String>("ipv6addr", false)));
+
+    }
+
+    @Test
+    public void testChunkToNetworkInfo() {
+        final String INTERFACE_NAME = "some interface. maybe eth0";
+        final String IPV4_ADDR = "256.256.256.256";
+        final String IPV6_ADDR = "100:100:100::::1";
+
+        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, false);
+        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, INTERFACE_NAME);
+        chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, IPV4_ADDR);
+        chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, IPV6_ADDR);
+
+        NetworkInterfaceInfo info = new NetworkInterfaceInfoConverter().fromChunk(chunk);
+        assertNotNull(info);
+        assertEquals(INTERFACE_NAME, info.getInterfaceName());
+        assertEquals(IPV4_ADDR, info.getIp4Addr());
+        assertEquals(IPV6_ADDR, info.getIp6Addr());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class NetworkInterfaceInfoDAOTest {
+
+    private static final String INTERFACE_NAME = "some interface. maybe eth0";
+    private static final String IPV4_ADDR = "256.256.256.256";
+    private static final String IPV6_ADDR = "100:100:100::::1";
+
+    @Test
+    public void testCategory() {
+        Collection<Key<?>> keys;
+
+        assertEquals("network-info", NetworkInterfaceInfoDAO.networkInfoCategory.getName());
+        keys = NetworkInterfaceInfoDAO.networkInfoCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<String>("iface", true)));
+        assertTrue(keys.contains(new Key<String>("ipv4addr", false)));
+        assertTrue(keys.contains(new Key<String>("ipv6addr", false)));
+        assertEquals(5, keys.size());
+    }
+
+    @Test
+    public void testGetNetworkInterfaces() {
+
+        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, false);
+        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, INTERFACE_NAME);
+        chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, IPV4_ADDR);
+        chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, IPV6_ADDR);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage);
+        List<NetworkInterfaceInfo> netInfo = dao.getNetworkInterfaces(hostRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, netInfo.size());
+
+        NetworkInterfaceInfo info = netInfo.get(0);
+
+        assertEquals(INTERFACE_NAME, info.getInterfaceName());
+        assertEquals(IPV4_ADDR, info.getIp4Addr());
+        assertEquals(IPV6_ADDR, info.getIp6Addr());
+    }
+
+    @Test
+    public void testPutNetworkInterfaceInfo() {
+        Storage storage = mock(Storage.class);
+        NetworkInterfaceInfo info = new NetworkInterfaceInfo(INTERFACE_NAME);
+        info.setIp4Addr(IPV4_ADDR);
+        info.setIp6Addr(IPV6_ADDR);
+        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage);
+        dao.putNetworkInterfaceInfo(info);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(NetworkInterfaceInfoDAO.networkInfoCategory, chunk.getCategory());
+        assertEquals(INTERFACE_NAME, chunk.get(NetworkInterfaceInfoDAO.ifaceKey));
+        assertEquals(IPV4_ADDR, chunk.get(NetworkInterfaceInfoDAO.ip4AddrKey));
+        assertEquals(IPV6_ADDR, chunk.get(NetworkInterfaceInfoDAO.ip6AddrKey));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmClassStatConverterTest {
+
+    @Test
+    public void testVmClassStatToChunk() {
+        VmClassStat stat = new VmClassStat(123, 1234L, 12345L);
+
+        VmClassStatConverter dao = new VmClassStatConverter();
+        Chunk chunk = dao.toChunk(stat);
+
+        assertEquals("vm-class-stats", chunk.getCategory().getName());
+        assertEquals((Long) 1234L, chunk.get(Key.TIMESTAMP));
+        assertEquals((Integer) 123, chunk.get(new Key<Integer>("vm-id", false)));
+        assertEquals((Long) 12345L, chunk.get(new Key<Long>("loadedClasses", false)));
+    }
+
+    @Test
+    public void testChunkToVmClassStat() {
+        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
+        chunk.put(Key.VM_ID, 123);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
+
+        VmClassStat stat = new VmClassStatConverter().fromChunk(chunk);
+
+        assertEquals(123, stat.getVmId());
+        assertEquals(1234L, stat.getTimeStamp());
+        assertEquals(12345L, stat.getLoadedClasses());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class VmClassStatDAOTest {
+
+    private static final Long TIMESTAMP = 1234L;
+    private static final Integer VM_ID = 123;
+    private static final Long LOADED_CLASSES = 12345L;
+
+    @Test
+    public void testCategory() {
+        assertEquals("vm-class-stats", VmClassStatDAO.vmClassStatsCategory.getName());
+        Collection<Key<?>> keys = VmClassStatDAO.vmClassStatsCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<Long>("loadedClasses", false)));
+        assertEquals(4, keys.size());
+
+    }
+
+    @Test
+    public void testGetLatestClassStatsBasic() {
+
+        Chunk chunk = getChunk();
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+
+        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
+        List<VmClassStat> vmClassStats = dao.getLatestClassStats(vmRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, vmClassStats.size());
+        VmClassStat stat = vmClassStats.get(0);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+    }
+
+    @Test
+    public void testGetLatestClassStatsTwice() {
+
+        Chunk chunk = getChunk();
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+
+        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
+        dao.getLatestClassStats(vmRef);
+
+        dao.getLatestClassStats(vmRef);
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
+    }
+
+    private Chunk getChunk() {
+        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmClassStatDAO.loadedClassesKey, LOADED_CLASSES);
+        return chunk;
+    }
+
+    @Test
+    public void testPutVmClassStat() {
+
+        Storage storage = mock(Storage.class);
+        VmClassStat stat = new VmClassStat(VM_ID, TIMESTAMP, LOADED_CLASSES);
+        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
+        dao.putVmClassStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmClassStatDAO.vmClassStatsCategory, chunk.getCategory());
+        assertEquals((Long) TIMESTAMP, chunk.get(Key.TIMESTAMP));
+        assertEquals((Integer) VM_ID, chunk.get(Key.VM_ID));
+        assertEquals((Long) LOADED_CLASSES, chunk.get(VmClassStatDAO.loadedClassesKey));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmCpuStatConverterTest {
+
+    final long TIMESTAMP = 12345l;
+    final int VM_ID = 678;
+    final double PROCESSOR_USAGE = 9.9;
+
+    @Test
+    public void testVmCpuStatToChunk() {
+
+        VmCpuStat vmCpuStat = new VmCpuStat(TIMESTAMP, VM_ID, PROCESSOR_USAGE);
+        Chunk chunk = new VmCpuStatConverter().toChunk(vmCpuStat);
+        assertNotNull(chunk);
+        assertEquals("vm-cpu-stats", chunk.getCategory().getName());
+        assertEquals((Long)TIMESTAMP, chunk.get(Key.TIMESTAMP));
+        assertEquals((Integer) VM_ID, chunk.get(new Key<Long>("vm-id", false)));
+        assertEquals(PROCESSOR_USAGE, chunk.get(new Key<Double>("processor-usage", false)), 0.001);
+
+    }
+
+    @Test
+    public void testChunkToVmCpuStat() {
+        Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmCpuStatDAO.vmCpuLoadKey, PROCESSOR_USAGE);
+
+        VmCpuStat stat = new VmCpuStatConverter().fromChunk(chunk);
+        assertNotNull(stat);
+        assertEquals(TIMESTAMP, stat.getTimeStamp());
+        assertEquals(VM_ID, stat.getVmId());
+        assertEquals(PROCESSOR_USAGE, stat.getCpuLoad(), 0.001);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.util.Collection;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmCpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class VmCpuStatDAOTest {
+
+    private static final Long TIMESTAMP = 1234L;
+    private static final String AGENT_ID = "test-agent-id";
+    private static final Integer VM_ID = 321;
+    private static final Double CPU_LOAD = 9.9;
+
+    private Chunk chunk;
+
+    @Before
+    public void setUp() {
+        chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.AGENT_ID, AGENT_ID);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmCpuStatDAO.vmCpuLoadKey, CPU_LOAD);
+    }
+
+    @Test
+    public void testCategory() {
+        assertEquals("vm-cpu-stats", VmCpuStatDAO.vmCpuStatCategory.getName());
+        Collection<Key<?>> keys = VmCpuStatDAO.vmCpuStatCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
+        assertTrue(keys.contains(new Key<Integer>("processor-usage", false)));
+        assertEquals(4, keys.size());
+    }
+
+    @Test
+    public void testGetLatestCpuStatsBasic() {
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(VM_ID);
+
+
+        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
+        List<VmCpuStat> vmCpuStats = dao.getLatestVmCpuStats(vmRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, vmCpuStats.size());
+        VmCpuStat stat = vmCpuStats.get(0);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(CPU_LOAD, stat.getCpuLoad(), 0.001);
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+    }
+
+    @Test
+    public void testGetLatestCpuStatsTwice() {
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
+        dao.getLatestVmCpuStats(vmRef);
+
+        dao.getLatestVmCpuStats(vmRef);
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
+    }
+
+    @Test
+    public void testPutVmCpuStat() {
+        Storage storage = mock(Storage.class);
+        VmCpuStat stat = new VmCpuStat(TIMESTAMP, VM_ID, CPU_LOAD);
+        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
+        dao.putVmCpuStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmCpuStatDAO.vmCpuStatCategory, chunk.getCategory());
+        assertEquals(TIMESTAMP, chunk.get(Key.TIMESTAMP));
+        assertEquals(VM_ID, chunk.get(Key.VM_ID));
+        assertEquals(CPU_LOAD, chunk.get(VmCpuStatDAO.vmCpuLoadKey));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmGcStatConverterTest {
+
+    @Test
+    public void testVmGcStatToChunk() {
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
+        Chunk chunk = new VmGcStatConverter().toChunk(stat);
+
+        assertNotNull(chunk);
+        assertEquals("vm-gc-stats", chunk.getCategory().getName());
+        assertEquals(TIMESTAMP, chunk.get(new Key<Long>("timestamp", false)));
+        assertEquals(VM_ID, chunk.get(new Key<Integer>("vm-id", false)));
+        assertEquals(COLLECTOR, chunk.get(new Key<String>("collector", false)));
+        assertEquals(RUN_COUNT, chunk.get(new Key<Long>("runtime-count", false)));
+        assertEquals(WALL_TIME, chunk.get(new Key<Long>("wall-time", false)));
+    }
+
+    @Test
+    public void testChunkToVmGcStat() {
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
+        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
+        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
+        VmGcStat stat = new VmGcStatConverter().fromChunk(chunk);
+
+        assertNotNull(stat);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+        assertEquals(COLLECTOR, stat.getCollectorName());
+        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
+        assertEquals(WALL_TIME, (Long) stat.getWallTime());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmGcStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class VmGcStatDAOTest {
+
+    private static final Integer VM_ID = 123;
+    private static final Long TIMESTAMP = 456L;
+    private static final String COLLECTOR = "collector1";
+    private static final Long RUN_COUNT = 10L;
+    private static final Long WALL_TIME = 9L;
+
+    @Test
+    public void testCategory() {
+        assertEquals("vm-gc-stats", VmGcStatDAO.vmGcStatCategory.getName());
+        Collection<Key<?>> keys = VmGcStatDAO.vmGcStatCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<String>("collector", false)));
+        assertTrue(keys.contains(new Key<Long>("runtime-count", false)));
+        assertTrue(keys.contains(new Key<Long>("wall-time", false)));
+        assertEquals(6, keys.size());
+    }
+
+    @Test
+    public void testGetLatestVmGcStatsBasic() {
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
+        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
+        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
+        List<VmGcStat> vmGcStats = dao.getLatestVmGcStats(vmRef);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, vmGcStats.size());
+        VmGcStat stat = vmGcStats.get(0);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+        assertEquals(COLLECTOR, stat.getCollectorName());
+        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
+        assertEquals(WALL_TIME, (Long) stat.getWallTime());
+    }
+
+    @Test
+    public void testGetLatestVmGcStatsTwice() {
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
+        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
+        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
+        dao.getLatestVmGcStats(vmRef);
+
+        dao.getLatestVmGcStats(vmRef);
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 456", arg.getValue().get(new Key<String>("$where", false)));
+    }
+
+    @Test
+    public void testPutVmGcStat() {
+        Storage storage = mock(Storage.class);
+        VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
+        dao.putVmGcStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmGcStatDAO.vmGcStatCategory, chunk.getCategory());
+        assertEquals(TIMESTAMP, chunk.get(Key.TIMESTAMP));
+        assertEquals(VM_ID, chunk.get(Key.VM_ID));
+        assertEquals(COLLECTOR, chunk.get(VmGcStatDAO.collectorKey));
+        assertEquals(RUN_COUNT, chunk.get(VmGcStatDAO.runCountKey));
+        assertEquals(WALL_TIME, chunk.get(VmGcStatDAO.wallTimeKey));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+public class VmInfoConverterTest {
+
+    private int vmId;
+    private long startTime;
+    private long stopTime;
+    private String jVersion;
+    private String jHome;
+    private String mainClass;
+    private String commandLine;
+    private String vmName;
+    private String vmInfo;
+    private String vmVersion;
+    private String vmArgs;
+    private Map<String, String> props;
+    private Map<String, String> env;
+    private List<String> libs;
+
+    @Before
+    public void setUp() {
+        vmId = 1;
+        startTime = 2;
+        stopTime = 3;
+        jVersion = "java 1.0";
+        jHome = "/path/to/jdk/home";
+        mainClass = "Hello.class";
+        commandLine = "World";
+        vmArgs = "-XX=+FastestJITPossible";
+        vmName = "Hotspot";
+        vmInfo = "Some info";
+        vmVersion = "1.0";
+        props = new HashMap<>();
+        env = new HashMap<>();
+        libs = new ArrayList<>();
+    }
+
+    @Test
+    public void testVmInfoToChunk() {
+        VmInfo info = new VmInfo(vmId, startTime, stopTime,
+                jVersion, jHome, mainClass, commandLine,
+                vmName, vmInfo, vmVersion, vmArgs,
+                props, env, libs);
+
+        Chunk chunk = new VmInfoConverter().toChunk(info);
+
+        assertNotNull(chunk);
+        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
+        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
+        assertEquals((Long) startTime, chunk.get(VmInfoDAO.startTimeKey));
+        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
+        assertEquals(jVersion, chunk.get(VmInfoDAO.runtimeVersionKey));
+        assertEquals(jHome, chunk.get(VmInfoDAO.javaHomeKey));
+        assertEquals(mainClass, chunk.get(VmInfoDAO.mainClassKey));
+        assertEquals(commandLine, chunk.get(VmInfoDAO.commandLineKey));
+        assertEquals(vmName, chunk.get(VmInfoDAO.vmNameKey));
+        assertEquals(vmInfo, chunk.get(VmInfoDAO.vmInfoKey));
+        assertEquals(vmVersion, chunk.get(VmInfoDAO.vmVersionKey));
+        assertEquals(vmArgs, chunk.get(VmInfoDAO.vmArgumentsKey));
+
+        // FIXME test environment, properties and loaded native libraries later
+    }
+
+    @Test
+    public void testChunkToVmInfo() {
+        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
+
+        chunk.put(VmInfoDAO.vmIdKey, vmId);
+        chunk.put(VmInfoDAO.vmPidKey, vmId);
+        chunk.put(VmInfoDAO.startTimeKey, startTime);
+        chunk.put(VmInfoDAO.stopTimeKey, stopTime);
+        chunk.put(VmInfoDAO.runtimeVersionKey, jVersion);
+        chunk.put(VmInfoDAO.javaHomeKey, jHome);
+        chunk.put(VmInfoDAO.mainClassKey, mainClass);
+        chunk.put(VmInfoDAO.commandLineKey, commandLine);
+        chunk.put(VmInfoDAO.vmNameKey, vmName);
+        chunk.put(VmInfoDAO.vmInfoKey, vmInfo);
+        chunk.put(VmInfoDAO.vmVersionKey, vmVersion);
+        chunk.put(VmInfoDAO.vmArgumentsKey, vmArgs);
+        chunk.put(VmInfoDAO.propertiesKey, props);
+        chunk.put(VmInfoDAO.environmentKey, env);
+        chunk.put(VmInfoDAO.librariesKey, libs);
+
+        VmInfo info = new VmInfoConverter().fromChunk(chunk);
+
+        assertNotNull(info);
+        assertEquals((Integer) vmId, (Integer) info.getVmId());
+        assertEquals((Integer) vmId, (Integer) info.getVmPid());
+        assertEquals((Long) startTime, (Long) info.getStartTimeStamp());
+        assertEquals((Long) stopTime, (Long) info.getStopTimeStamp());
+        assertEquals(jVersion, info.getJavaVersion());
+        assertEquals(jHome, info.getJavaHome());
+        assertEquals(mainClass, info.getMainClass());
+        assertEquals(commandLine, info.getJavaCommandLine());
+        assertEquals(vmName, info.getVmName());
+        assertEquals(vmInfo, info.getVmInfo());
+        assertEquals(vmVersion, info.getVmVersion());
+        assertEquals(vmArgs, info.getVmArguments());
+
+        // FIXME test environment, properties and loaded native libraries later
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmInfo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class VmInfoDAOTest {
+
+    private int vmId;
+    private long startTime;
+    private long stopTime;
+    private String jVersion;
+    private String jHome;
+    private String mainClass;
+    private String commandLine;
+    private String vmName;
+    private String vmInfo;
+    private String vmVersion;
+    private String vmArgs;
+    private Map<String, String> props;
+    private Map<String, String> env;
+    private List<String> libs;
+    private VmInfoDAO dao;
+
+    @Before
+    public void setUp() {
+        vmId = 1;
+        startTime = 2;
+        stopTime = 3;
+        jVersion = "java 1.0";
+        jHome = "/path/to/jdk/home";
+        mainClass = "Hello.class";
+        commandLine = "World";
+        vmArgs = "-XX=+FastestJITPossible";
+        vmName = "Hotspot";
+        vmInfo = "Some info";
+        vmVersion = "1.0";
+        props = new HashMap<>();
+        env = new HashMap<>();
+        libs = new ArrayList<>();
+        Storage storage = setupStorageForSingleVM();
+        dao = new VmInfoDAOImpl(storage);
+    }
+
+    @After
+    public void tearDown() {
+        dao = null;
+    }
+
+    @Test
+    public void testCategory() {
+        assertEquals("vm-info", VmInfoDAO.vmInfoCategory.getName());
+        Collection<Key<?>> keys = VmInfoDAO.vmInfoCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Integer>("vm-id", true)));
+        assertTrue(keys.contains(new Key<Integer>("vm-pid", false)));
+        assertTrue(keys.contains(new Key<String>("runtime-version", false)));
+        assertTrue(keys.contains(new Key<String>("java-home", false)));
+        assertTrue(keys.contains(new Key<String>("main-class", false)));
+        assertTrue(keys.contains(new Key<String>("command-line", false)));
+        assertTrue(keys.contains(new Key<String>("vm-arguments", false)));
+        assertTrue(keys.contains(new Key<String>("vm-name", false)));
+        assertTrue(keys.contains(new Key<String>("vm-info", false)));
+        assertTrue(keys.contains(new Key<String>("vm-version", false)));
+        assertTrue(keys.contains(new Key<Map<String, String>>("properties", false)));
+        assertTrue(keys.contains(new Key<Map<String, String>>("environment", false)));
+        assertTrue(keys.contains(new Key<List<String>>("libraries", false)));
+        assertTrue(keys.contains(new Key<Long>("start-time", false)));
+        assertTrue(keys.contains(new Key<Long>("stop-time", false)));
+        assertEquals(16, keys.size());
+    }
+
+    @Test
+    public void testGetVmInfo() {
+        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
+        chunk.put(VmInfoDAO.vmIdKey, vmId);
+        chunk.put(VmInfoDAO.vmPidKey, vmId);
+        chunk.put(VmInfoDAO.startTimeKey, startTime);
+        chunk.put(VmInfoDAO.stopTimeKey, stopTime);
+        chunk.put(VmInfoDAO.runtimeVersionKey, jVersion);
+        chunk.put(VmInfoDAO.javaHomeKey, jHome);
+        chunk.put(VmInfoDAO.mainClassKey, mainClass);
+        chunk.put(VmInfoDAO.commandLineKey, commandLine);
+        chunk.put(VmInfoDAO.vmNameKey, vmName);
+        chunk.put(VmInfoDAO.vmInfoKey, vmInfo);
+        chunk.put(VmInfoDAO.vmVersionKey, vmVersion);
+        chunk.put(VmInfoDAO.vmArgumentsKey, vmArgs);
+        chunk.put(VmInfoDAO.propertiesKey, props);
+        chunk.put(VmInfoDAO.environmentKey, env);
+        chunk.put(VmInfoDAO.librariesKey, libs);
+
+        Storage storage = mock(Storage.class);
+        when(storage.find(any(Chunk.class))).thenReturn(chunk);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        VmInfo info = dao.getVmInfo(vmRef);
+
+        assertNotNull(info);
+        assertEquals((Integer) vmId, (Integer) info.getVmId());
+        assertEquals((Integer) vmId, (Integer) info.getVmPid());
+        assertEquals((Long) startTime, (Long) info.getStartTimeStamp());
+        assertEquals((Long) stopTime, (Long) info.getStopTimeStamp());
+        assertEquals(jVersion, info.getJavaVersion());
+        assertEquals(jHome, info.getJavaHome());
+        assertEquals(mainClass, info.getMainClass());
+        assertEquals(commandLine, info.getJavaCommandLine());
+        assertEquals(vmName, info.getVmName());
+        assertEquals(vmInfo, info.getVmInfo());
+        assertEquals(vmVersion, info.getVmVersion());
+        assertEquals(vmArgs, info.getVmArguments());
+
+        // FIXME test environment, properties and loaded native libraries later
+    }
+
+    @Test
+    public void testGetVmInfoUnknownVM() {
+
+        Storage storage = mock(Storage.class);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        try {
+            dao.getVmInfo(vmRef);
+            fail();
+        } catch (DAOException ex) {
+            assertEquals("Unknown VM: host:system;vm:321", ex.getMessage());
+        }
+
+    }
+
+    private Storage setupStorageForSingleVM() {
+        Chunk query1 = new Chunk(VmInfoDAO.vmInfoCategory, false);
+        query1.put(Key.AGENT_ID, "123");
+
+        Chunk query2 = new Chunk(VmInfoDAO.vmInfoCategory, false);
+        query2.put(Key.AGENT_ID, "456");
+
+        Chunk vm1 = new Chunk(VmInfoDAO.vmInfoCategory, false);
+        vm1.put(VmInfoDAO.vmIdKey, 123);
+        vm1.put(VmInfoDAO.mainClassKey, "mainClass1");
+
+        Chunk vm2 = new Chunk(VmInfoDAO.vmInfoCategory, false);
+        vm2.put(VmInfoDAO.vmIdKey, 456);
+        vm2.put(VmInfoDAO.mainClassKey, "mainClass2");
+
+        Cursor singleVMCursor = mock(Cursor.class);
+        when(singleVMCursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(singleVMCursor.next()).thenReturn(vm1);
+
+        Cursor multiVMsCursor = mock(Cursor.class);
+        when(multiVMsCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(multiVMsCursor.next()).thenReturn(vm1).thenReturn(vm2);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(query1)).thenReturn(singleVMCursor);
+        when(storage.findAll(query2)).thenReturn(multiVMsCursor);
+        return storage;
+    }
+
+    @Test
+    public void testSingleVM() {
+        HostRef host = new HostRef("123", "fluffhost");
+
+        Collection<VmRef> vms = dao.getVMs(host);
+
+        assertCollection(vms, new VmRef(host, 123, "mainClass1"));
+    }
+
+    @Test
+    public void testMultiVMs() {
+        HostRef host = new HostRef("456", "fluffhost");
+
+        Collection<VmRef> vms = dao.getVMs(host);
+
+        assertCollection(vms, new VmRef(host, 123, "mainClass1"), new VmRef(host, 456, "mainClass2"));
+    }
+
+    private void assertCollection(Collection<VmRef> vms, VmRef... expectedVMs) {
+        assertEquals(expectedVMs.length, vms.size());
+        for (VmRef expectedVM : expectedVMs) {
+            assertTrue(vms.contains(expectedVM));
+        }
+    }
+
+    @Test
+    public void testGetCount() {
+        Storage storage = mock(Storage.class);
+        when(storage.getCount(any(Category.class))).thenReturn(5L);
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        Long count = dao.getCount();
+        assertEquals((Long) 5L, count);
+    }
+
+    @Test
+    public void testPutVmInfo() {
+
+        Storage storage = mock(Storage.class);
+        VmInfo info = new VmInfo(vmId, startTime, stopTime, jVersion, jHome,
+                mainClass, commandLine, vmName, vmInfo, vmVersion, vmArgs,
+                props, env, libs);
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        dao.putVmInfo(info);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmInfoDAO.vmInfoCategory, chunk.getCategory());
+        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
+        assertEquals((Long) startTime, chunk.get(VmInfoDAO.startTimeKey));
+        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
+        assertEquals(jVersion, chunk.get(VmInfoDAO.runtimeVersionKey));
+        assertEquals(jHome, chunk.get(VmInfoDAO.javaHomeKey));
+        assertEquals(mainClass, chunk.get(VmInfoDAO.mainClassKey));
+        assertEquals(commandLine, chunk.get(VmInfoDAO.commandLineKey));
+        assertEquals(vmName, chunk.get(VmInfoDAO.vmNameKey));
+        assertEquals(vmInfo, chunk.get(VmInfoDAO.vmInfoKey));
+        assertEquals(vmVersion, chunk.get(VmInfoDAO.vmVersionKey));
+        assertEquals(vmArgs, chunk.get(VmInfoDAO.vmArgumentsKey));
+        assertEquals(props, chunk.get(VmInfoDAO.propertiesKey));
+        assertEquals(env, chunk.get(VmInfoDAO.environmentKey));
+        assertEquals(libs, chunk.get(VmInfoDAO.librariesKey));
+    }
+
+    @Test
+    public void testPutVmStoppedTime() {
+        Storage storage = mock(Storage.class);
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        dao.putVmStoppedTime(vmId, stopTime);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).updateChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmInfoDAO.vmInfoCategory, chunk.getCategory());
+        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
+        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+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.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class VmLatestPojoListGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final int VM_PID = 123;
+    private static final String MAIN_CLASS = "Foo.class";
+    private static final String CATEGORY_NAME = "vmcategory";
+    // Make this one static so we don't get IllegalStateException from trying
+    // to make category of same name while running tests in same classloader.
+    private static final Category cat =  new Category(CATEGORY_NAME);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+    private static long t3 = 10;
+
+    private static long lc1 = 10;
+    private static long lc2 = 20;
+    private static long lc3 = 30;
+
+    private HostRef hostRef;
+    private VmRef vmRef;
+    private Converter<VmClassStat> converter;
+    private Chunk result1, result2, result3;
+
+    @Before
+    public void setUp() {
+        hostRef = new HostRef(AGENT_ID, HOSTNAME);
+        vmRef = new VmRef(hostRef, VM_PID, MAIN_CLASS);
+        converter = new VmClassStatConverter();
+        result1 = new Chunk(cat, false);
+        result1.put(Key.AGENT_ID, AGENT_ID);
+        result1.put(Key.VM_ID, VM_PID);
+        result1.put(Key.TIMESTAMP, t1);
+        result1.put(VmClassStatDAO.loadedClassesKey, lc1);
+        result2 = new Chunk(cat, false);
+        result2.put(Key.AGENT_ID, AGENT_ID);
+        result2.put(Key.VM_ID, VM_PID);
+        result2.put(Key.TIMESTAMP, t2);
+        result2.put(VmClassStatDAO.loadedClassesKey, lc2);
+        result3 = new Chunk(cat, false);
+        result3.put(Key.AGENT_ID, AGENT_ID);
+        result3.put(Key.VM_ID, VM_PID);
+        result3.put(Key.TIMESTAMP, t3);
+        result3.put(VmClassStatDAO.loadedClassesKey, lc3);
+    }
+
+    @Test
+    public void testBuildQuery() {
+        Storage storage = mock(Storage.class);
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(2, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.VM_ID));
+        assertFalse(query.getKeys().contains(Key.WHERE));
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
+    }
+
+    @Test
+    public void testBuildQueryPopulatesUpdateTimes() {
+        Storage storage = mock(Storage.class);
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        getter.buildQuery(); // Ignore first return value.
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(3, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.VM_ID));
+        assertTrue(query.getKeys().contains(Key.WHERE));
+        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
+    }
+
+    @Test
+    public void testGetLatest() {
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+
+        List<VmClassStat> stats = getter.getLatest();
+
+        assertNotNull(stats);
+        assertEquals(2, stats.size());
+        VmClassStat stat1 = stats.get(0);
+        assertEquals(t1, stat1.getTimeStamp());
+        assertEquals(lc1, stat1.getLoadedClasses());
+        VmClassStat stat2 = stats.get(1);
+        assertEquals(t2, stat2.getTimeStamp());
+        assertEquals(lc2, stat2.getLoadedClasses());
+    }
+
+    @Test
+    public void testGetLatestMultipleCalls() {
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(result3);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
+
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        getter.getLatest();
+        getter.getLatest();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        List<Chunk> queries = arg.getAllValues();
+
+        assertEquals(2, queries.size());
+        Chunk query = queries.get(1);
+        assertNotNull(query);
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
+        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+
+public class VmMemoryStatConverterTest {
+
+    @Test
+    public void testVmMemoryStatToChunk() {
+        List<Generation> generations = new ArrayList<Generation>();
+
+        int i = 0;
+        for (String genName: new String[] { "new", "old", "perm" }) {
+            Generation gen = new Generation();
+            gen.name = genName;
+            gen.collector = gen.name;
+            generations.add(gen);
+            List<Space> spaces = new ArrayList<Space>();
+            gen.spaces = spaces;
+            String[] spaceNames = null;
+            if (genName.equals("new")) {
+                spaceNames = new String[] { "eden", "s0", "s1" };
+            } else if (genName.equals("old")) {
+                spaceNames = new String[] { "old" };
+            } else {
+                spaceNames = new String[] { "perm" };
+            }
+            for (String spaceName: spaceNames) {
+                Space space = new Space();
+                space.name = spaceName;
+                space.index = 0;
+                space.used = i++;
+                space.capacity = i++;
+                space.maxCapacity = i++;
+                spaces.add(space);
+            }
+        }
+
+        VmMemoryStat stat = new VmMemoryStat(1, 2, generations);
+
+        Chunk chunk = new VmMemoryStatConverter().toChunk(stat);
+
+        assertNotNull(chunk);
+        assertEquals((Long) 1l, chunk.get(new Key<Long>("timestamp", false)));
+        assertEquals((Integer) 2, chunk.get(new Key<Integer>("vm-id", false)));
+        assertEquals("new", chunk.get(new Key<String>("eden.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("eden.collector", false)));
+        assertEquals((Long) 0l, chunk.get(new Key<Long>("eden.used", false)));
+        assertEquals((Long) 1l, chunk.get(new Key<Long>("eden.capacity", false)));
+        assertEquals((Long) 2l, chunk.get(new Key<Long>("eden.max-capacity", false)));
+        assertEquals("new", chunk.get(new Key<String>("s0.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("s0.collector", false)));
+        assertEquals((Long) 3l, chunk.get(new Key<Long>("s0.used", false)));
+        assertEquals((Long) 4l, chunk.get(new Key<Long>("s0.capacity", false)));
+        assertEquals((Long) 5l, chunk.get(new Key<Long>("s0.max-capacity", false)));
+        assertEquals("new", chunk.get(new Key<String>("s1.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("s1.collector", false)));
+        assertEquals((Long) 6l, chunk.get(new Key<Long>("s1.used", false)));
+        assertEquals((Long) 7l, chunk.get(new Key<Long>("s1.capacity", false)));
+        assertEquals((Long) 8l, chunk.get(new Key<Long>("s1.max-capacity", false)));
+        assertEquals("old", chunk.get(new Key<String>("old.gen", false)));
+        assertEquals("old", chunk.get(new Key<String>("old.collector", false)));
+        assertEquals((Long) 9l, chunk.get(new Key<Long>("old.used", false)));
+        assertEquals((Long) 10l, chunk.get(new Key<Long>("old.capacity", false)));
+        assertEquals((Long) 11l, chunk.get(new Key<Long>("old.max-capacity", false)));
+        assertEquals("perm", chunk.get(new Key<String>("perm.gen", false)));
+        assertEquals("perm", chunk.get(new Key<String>("perm.collector", false)));
+        assertEquals((Long) 12l, chunk.get(new Key<Long>("perm.used", false)));
+        assertEquals((Long) 13l, chunk.get(new Key<Long>("perm.capacity", false)));
+        assertEquals((Long) 14l, chunk.get(new Key<Long>("perm.max-capacity", false)));
+
+    }
+
+    @Test
+    public void testChunkToVmMemoryStat() {
+        final long TIMESTAMP = 1234l;
+        final int VM_ID = 4567;
+
+        final long EDEN_USED = 1;
+        final long EDEN_CAPACITY = 2;
+        final long EDEN_MAX_CAPACITY = 3;
+        
+        final long S0_USED = 4;
+        final long S0_CAPACITY = 5;
+        final long S0_MAX_CAPACITY = 6;
+        
+        final long S1_USED = 7;
+        final long S1_CAPACITY = 8;
+        final long S1_MAX_CAPACITY = 9;
+        
+        final long OLD_USED = 10;
+        final long OLD_CAPACITY = 11;
+        final long OLD_MAX_CAPACITY = 12;
+        
+        final long PERM_USED = 13;
+        final long PERM_CAPACITY = 14;
+        final long PERM_MAX_CAPACITY = 15;
+        
+        Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
+
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(Key.VM_ID, VM_ID);
+
+        chunk.put(VmMemoryStatDAO.edenGenKey, "new");
+        chunk.put(VmMemoryStatDAO.edenCollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.edenUsedKey, EDEN_USED);
+        chunk.put(VmMemoryStatDAO.edenCapacityKey, EDEN_CAPACITY);
+        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, EDEN_MAX_CAPACITY);
+
+        chunk.put(VmMemoryStatDAO.s0GenKey, "new");
+        chunk.put(VmMemoryStatDAO.s0CollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.s0UsedKey, S0_USED);
+        chunk.put(VmMemoryStatDAO.s0CapacityKey, S0_CAPACITY);
+        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, S0_MAX_CAPACITY);
+
+        chunk.put(VmMemoryStatDAO.s1GenKey, "new");
+        chunk.put(VmMemoryStatDAO.s1CollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.s1UsedKey, S1_USED);
+        chunk.put(VmMemoryStatDAO.s1CapacityKey, S1_CAPACITY);
+        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, S1_MAX_CAPACITY);
+
+        chunk.put(VmMemoryStatDAO.oldGenKey, "old");
+        chunk.put(VmMemoryStatDAO.oldCollectorKey, "old-collector");
+        chunk.put(VmMemoryStatDAO.oldUsedKey, OLD_USED);
+        chunk.put(VmMemoryStatDAO.oldCapacityKey, OLD_CAPACITY);
+        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, OLD_MAX_CAPACITY);
+
+        chunk.put(VmMemoryStatDAO.permGenKey, "perm");
+        chunk.put(VmMemoryStatDAO.permCollectorKey, "perm-collector");
+        chunk.put(VmMemoryStatDAO.permUsedKey, PERM_USED);
+        chunk.put(VmMemoryStatDAO.permCapacityKey, PERM_CAPACITY);
+        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, PERM_MAX_CAPACITY);
+
+        VmMemoryStat stat = new VmMemoryStatConverter().fromChunk(chunk);
+
+        assertNotNull(stat);
+        assertEquals(TIMESTAMP, stat.getTimeStamp());
+        assertEquals(VM_ID, stat.getVmId());
+
+        assertEquals(3, stat.getGenerations().size());
+
+        Generation newGen = stat.getGeneration("new");
+        assertNotNull(newGen);
+        assertEquals(3, newGen.spaces.size());
+        assertEquals("new-collector", newGen.collector);
+        
+        Space eden = newGen.getSpace("eden");
+        assertNotNull(eden);
+        assertEquals(EDEN_USED, eden.used);
+        assertEquals(EDEN_CAPACITY, eden.capacity);
+        assertEquals(EDEN_MAX_CAPACITY, eden.maxCapacity);
+        
+        Space s0 = newGen.getSpace("s0");
+        assertNotNull(s0);
+        assertEquals(S0_USED, s0.used);
+        assertEquals(S0_CAPACITY, s0.capacity);
+        assertEquals(S0_MAX_CAPACITY, s0.maxCapacity);
+        
+        Space s1 = newGen.getSpace("s1");
+        assertNotNull(s1);
+        assertEquals(S1_USED, s1.used);
+        assertEquals(S1_CAPACITY, s1.capacity);
+        assertEquals(S1_MAX_CAPACITY, s1.maxCapacity);
+        
+        Generation oldGen = stat.getGeneration("old");
+        assertNotNull(oldGen);
+        assertEquals(1, oldGen.spaces.size());
+        assertEquals("old-collector", oldGen.collector);
+
+        Space old = oldGen.getSpace("old");
+        assertNotNull(old);
+        assertEquals(OLD_USED, old.used);
+        assertEquals(OLD_CAPACITY, old.capacity);
+        assertEquals(OLD_MAX_CAPACITY, old.maxCapacity);
+        
+        Generation permGen = stat.getGeneration("perm");
+        assertNotNull(permGen);
+        assertEquals(1, permGen.spaces.size());
+        assertEquals("perm-collector", permGen.collector);
+        
+        Space permSpace = permGen.getSpace("perm");
+        assertNotNull(permSpace);
+        assertEquals(PERM_USED, permSpace.used);
+        assertEquals(PERM_CAPACITY, permSpace.capacity);
+        assertEquals(PERM_MAX_CAPACITY, permSpace.maxCapacity);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Cursor.SortDirection;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+public class VmMemoryStatDAOTest {
+    @Test
+    public void testCategories() {
+        Collection<Key<?>> keys;
+
+        assertEquals("vm-memory-stats", VmMemoryStatDAO.vmMemoryStatsCategory.getName());
+        keys = VmMemoryStatDAO.vmMemoryStatsCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agent-id", false)));
+        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
+        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
+        assertTrue(keys.contains(new Key<String>("eden.gen", false)));
+        assertTrue(keys.contains(new Key<String>("eden.collector", false)));
+        assertTrue(keys.contains(new Key<Long>("eden.capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("eden.max-capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("eden.used", false)));
+        assertTrue(keys.contains(new Key<String>("s0.gen", false)));
+        assertTrue(keys.contains(new Key<String>("s0.collector", false)));
+        assertTrue(keys.contains(new Key<Long>("s0.capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("s0.max-capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("s0.used", false)));
+        assertTrue(keys.contains(new Key<String>("s1.gen", false)));
+        assertTrue(keys.contains(new Key<String>("s1.collector", false)));
+        assertTrue(keys.contains(new Key<Long>("s1.capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("s1.max-capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("s1.used", false)));
+        assertTrue(keys.contains(new Key<String>("old.gen", false)));
+        assertTrue(keys.contains(new Key<String>("old.collector", false)));
+        assertTrue(keys.contains(new Key<Long>("old.capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("old.max-capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("old.used", false)));
+        assertTrue(keys.contains(new Key<String>("perm.gen", false)));
+        assertTrue(keys.contains(new Key<String>("perm.collector", false)));
+        assertTrue(keys.contains(new Key<Long>("perm.capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("perm.max-capacity", false)));
+        assertTrue(keys.contains(new Key<Long>("perm.used", false)));
+        assertEquals(28, keys.size());
+    }
+
+    @Test
+    public void testGetLatest() {
+        final int VM_ID = 0xcafe;
+        final String AGENT_ID = "agent";
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn(AGENT_ID);
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(VM_ID);
+
+        Storage storage = mock(Storage.class);
+
+        final Object[] savedQuery = new Object[1];
+        final Cursor cursor = mock(Cursor.class);
+        when(storage.findAll(any(Chunk.class))).thenAnswer(new Answer<Cursor>() {
+            @Override
+            public Cursor answer(InvocationOnMock invocation) throws Throwable {
+                savedQuery[0] = invocation.getArguments()[0];
+                return cursor;
+            }
+
+        });
+        when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor);
+        when(cursor.limit(any(Integer.class))).thenReturn(cursor);
+        when(cursor.hasNext()).thenReturn(false);
+
+        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
+        impl.getLatestMemoryStat(vmRef);
+
+        @SuppressWarnings("rawtypes")
+        ArgumentCaptor<Key> sortKey = ArgumentCaptor.forClass(Key.class);
+        ArgumentCaptor<SortDirection> sortDirection = ArgumentCaptor.forClass(SortDirection.class);
+        verify(cursor).sort(sortKey.capture(), sortDirection.capture());
+
+        Chunk query = (Chunk) savedQuery[0];
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals((Integer)VM_ID, query.get(Key.VM_ID));
+
+        assertTrue(sortKey.getValue().equals(Key.TIMESTAMP));
+        assertTrue(sortDirection.getValue().equals(SortDirection.DESCENDING));
+    }
+
+    @Test
+    public void testGetLatestReturnsNullWhenStorageEmpty() {
+        final int VM_ID = 0xcafe;
+        final String AGENT_ID = "agent";
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn(AGENT_ID);
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(VM_ID);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor);
+        when(cursor.limit(any(Integer.class))).thenReturn(cursor);
+        when(cursor.hasNext()).thenReturn(false);
+        when(cursor.next()).thenReturn(null);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
+        VmMemoryStat latest = impl.getLatestMemoryStat(vmRef);
+        assertTrue(latest == null);
+    }
+
+    @Test
+    public void testPutVmMemoryStat() {
+
+        List<Generation> generations = new ArrayList<Generation>();
+
+        int i = 0;
+        for (String genName: new String[] { "new", "old", "perm" }) {
+            Generation gen = new Generation();
+            gen.name = genName;
+            gen.collector = gen.name;
+            generations.add(gen);
+            List<Space> spaces = new ArrayList<Space>();
+            gen.spaces = spaces;
+            String[] spaceNames = null;
+            if (genName.equals("new")) {
+                spaceNames = new String[] { "eden", "s0", "s1" };
+            } else if (genName.equals("old")) {
+                spaceNames = new String[] { "old" };
+            } else {
+                spaceNames = new String[] { "perm" };
+            }
+            for (String spaceName: spaceNames) {
+                Space space = new Space();
+                space.name = spaceName;
+                space.index = 0;
+                space.used = i++;
+                space.capacity = i++;
+                space.maxCapacity = i++;
+                spaces.add(space);
+            }
+        }
+        VmMemoryStat stat = new VmMemoryStat(1, 2, generations);
+
+        Storage storage = mock(Storage.class);
+        VmMemoryStatDAO dao = new VmMemoryStatDAOImpl(storage);
+        dao.putVmMemoryStat(stat);
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).putChunk(arg.capture());
+        Chunk chunk = arg.getValue();
+
+        assertEquals(VmMemoryStatDAO.vmMemoryStatsCategory, chunk.getCategory());
+        assertEquals((Long) 1l, chunk.get(new Key<Long>("timestamp", false)));
+        assertEquals((Integer) 2, chunk.get(new Key<Integer>("vm-id", false)));
+        assertEquals("new", chunk.get(new Key<String>("eden.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("eden.collector", false)));
+        assertEquals((Long) 0l, chunk.get(new Key<Long>("eden.used", false)));
+        assertEquals((Long) 1l, chunk.get(new Key<Long>("eden.capacity", false)));
+        assertEquals((Long) 2l, chunk.get(new Key<Long>("eden.max-capacity", false)));
+        assertEquals("new", chunk.get(new Key<String>("s0.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("s0.collector", false)));
+        assertEquals((Long) 3l, chunk.get(new Key<Long>("s0.used", false)));
+        assertEquals((Long) 4l, chunk.get(new Key<Long>("s0.capacity", false)));
+        assertEquals((Long) 5l, chunk.get(new Key<Long>("s0.max-capacity", false)));
+        assertEquals("new", chunk.get(new Key<String>("s1.gen", false)));
+        assertEquals("new", chunk.get(new Key<String>("s1.collector", false)));
+        assertEquals((Long) 6l, chunk.get(new Key<Long>("s1.used", false)));
+        assertEquals((Long) 7l, chunk.get(new Key<Long>("s1.capacity", false)));
+        assertEquals((Long) 8l, chunk.get(new Key<Long>("s1.max-capacity", false)));
+        assertEquals("old", chunk.get(new Key<String>("old.gen", false)));
+        assertEquals("old", chunk.get(new Key<String>("old.collector", false)));
+        assertEquals((Long) 9l, chunk.get(new Key<Long>("old.used", false)));
+        assertEquals((Long) 10l, chunk.get(new Key<Long>("old.capacity", false)));
+        assertEquals((Long) 11l, chunk.get(new Key<Long>("old.max-capacity", false)));
+        assertEquals("perm", chunk.get(new Key<String>("perm.gen", false)));
+        assertEquals("perm", chunk.get(new Key<String>("perm.collector", false)));
+        assertEquals((Long) 12l, chunk.get(new Key<Long>("perm.used", false)));
+        assertEquals((Long) 13l, chunk.get(new Key<Long>("perm.capacity", false)));
+        assertEquals((Long) 14l, chunk.get(new Key<Long>("perm.max-capacity", false)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelatorTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Iterator;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.model.TimeStampedPojoCorrelator.Correlation;
+
+public class TimeStampedPojoCorrelatorTest {
+
+    private static class TestTimeStampedPojo implements TimeStampedPojo {
+
+        private long timestamp;
+
+        private TestTimeStampedPojo(long timestamp) {
+            this.timestamp = timestamp;
+        }
+
+        @Override
+        public long getTimeStamp() {
+            return timestamp;
+        }
+        
+    }
+
+    @Test
+    public void testOneSeries() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(1);
+        correlator.add(0, new TestTimeStampedPojo(3));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(2));
+
+        Iterator<Correlation> i = correlator.iterator();
+
+        assertTrue(i.hasNext());
+        Correlation correlation1 = i.next();
+        assertEquals(1, correlation1.get(0).getTimeStamp());
+        assertEquals(1, correlation1.getTimeStamp());
+        assertTrue(i.hasNext());
+        Correlation correlation2 = i.next();
+        assertEquals(2, correlation2.get(0).getTimeStamp());
+        assertEquals(2, correlation2.getTimeStamp());
+        assertTrue(i.hasNext());
+        Correlation correlation3 = i.next();
+        assertEquals(3, correlation3.get(0).getTimeStamp());
+        assertEquals(3, correlation3.getTimeStamp());
+        assertFalse(i.hasNext());
+    }
+
+    @Test(expected=UnsupportedOperationException.class)
+    public void testOneSeriesRemove() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(1);
+        correlator.add(0, new TestTimeStampedPojo(3));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(2));
+
+        Iterator<Correlation> i = correlator.iterator();
+        i.next();
+        i.remove();
+    }
+
+    @Test
+    public void test3SeriesInterleaving() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(9));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(4));
+        correlator.add(1, new TestTimeStampedPojo(8));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(5));
+        correlator.add(2, new TestTimeStampedPojo(7));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(6));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 4, 4l, 2l, 3l);
+        assertNextCorrelation(i, 5, 4l, 5l, 3l);
+        assertNextCorrelation(i, 6, 4l, 5l, 6l);
+        assertNextCorrelation(i, 7, 4l, 5l, 7l);
+        assertNextCorrelation(i, 8, 4l, 8l, 7l);
+        assertNextCorrelation(i, 9, 9l, 8l, 7l);
+        assertFalse(i.hasNext());
+    }
+
+    @Test
+    public void test3SeriesColliding() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(3));
+        correlator.add(0, new TestTimeStampedPojo(2));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(1));
+        correlator.add(1, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(1));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(2));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, 1l, 1l);
+        assertNextCorrelation(i, 2, 2l, 2l, 2l);
+        assertNextCorrelation(i, 3, 3l, 3l, 3l);
+        assertFalse(i.hasNext());
+    }
+
+    @Test
+    public void test3SeriesMissing1() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(3));
+        correlator.add(0, new TestTimeStampedPojo(2));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(1));
+        correlator.add(1, new TestTimeStampedPojo(3));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, 1l, null);
+        assertNextCorrelation(i, 2, 2l, 2l, null);
+        assertNextCorrelation(i, 3, 3l, 3l, null);
+        assertFalse(i.hasNext());
+    }
+
+    @Test
+    public void test3SeriesEquals() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(3));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertFalse(i.hasNext());
+    }
+
+    @Test
+    public void test3SeriesContinuous() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(9));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(4));
+        correlator.add(1, new TestTimeStampedPojo(8));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(5));
+        correlator.add(2, new TestTimeStampedPojo(7));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(6));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 4, 4l, 2l, 3l);
+        assertNextCorrelation(i, 5, 4l, 5l, 3l);
+        assertNextCorrelation(i, 6, 4l, 5l, 6l);
+        assertNextCorrelation(i, 7, 4l, 5l, 7l);
+        assertNextCorrelation(i, 8, 4l, 8l, 7l);
+        assertNextCorrelation(i, 9, 9l, 8l, 7l);
+        assertFalse(i.hasNext());
+
+        correlator.clear();
+        correlator.add(0, new TestTimeStampedPojo(10));
+        correlator.add(1, new TestTimeStampedPojo(11));
+        correlator.add(2, new TestTimeStampedPojo(12));
+
+        Iterator<Correlation> i2 = correlator.iterator();
+        assertNextCorrelation(i2, 10, 10l, 8l, 7l);
+        assertNextCorrelation(i2, 11, 10l, 11l, 7l);
+        assertNextCorrelation(i2, 12, 10l, 11l, 12l);
+        assertFalse(i2.hasNext());
+    }
+
+    @Test
+    public void test3SeriesContinuousNoData() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(9));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(4));
+        correlator.add(1, new TestTimeStampedPojo(8));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(5));
+        correlator.add(2, new TestTimeStampedPojo(7));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(6));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 4, 4l, 2l, 3l);
+        assertNextCorrelation(i, 5, 4l, 5l, 3l);
+        assertNextCorrelation(i, 6, 4l, 5l, 6l);
+        assertNextCorrelation(i, 7, 4l, 5l, 7l);
+        assertNextCorrelation(i, 8, 4l, 8l, 7l);
+        assertNextCorrelation(i, 9, 9l, 8l, 7l);
+        assertFalse(i.hasNext());
+
+        correlator.clear();
+
+        Iterator<Correlation> i2 = correlator.iterator();
+        assertFalse(i2.hasNext());
+    }
+
+    @Test
+    public void test3SeriesContinuousOnlySingleSeries() {
+        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
+        correlator.add(0, new TestTimeStampedPojo(9));
+        correlator.add(0, new TestTimeStampedPojo(1));
+        correlator.add(0, new TestTimeStampedPojo(4));
+        correlator.add(1, new TestTimeStampedPojo(8));
+        correlator.add(1, new TestTimeStampedPojo(2));
+        correlator.add(1, new TestTimeStampedPojo(5));
+        correlator.add(2, new TestTimeStampedPojo(7));
+        correlator.add(2, new TestTimeStampedPojo(3));
+        correlator.add(2, new TestTimeStampedPojo(6));
+
+        Iterator<Correlation> i = correlator.iterator();
+        assertNextCorrelation(i, 1, 1l, null, null);
+        assertNextCorrelation(i, 2, 1l, 2l, null);
+        assertNextCorrelation(i, 3, 1l, 2l, 3l);
+        assertNextCorrelation(i, 4, 4l, 2l, 3l);
+        assertNextCorrelation(i, 5, 4l, 5l, 3l);
+        assertNextCorrelation(i, 6, 4l, 5l, 6l);
+        assertNextCorrelation(i, 7, 4l, 5l, 7l);
+        assertNextCorrelation(i, 8, 4l, 8l, 7l);
+        assertNextCorrelation(i, 9, 9l, 8l, 7l);
+        assertFalse(i.hasNext());
+
+        correlator.clear();
+        correlator.add(0, new TestTimeStampedPojo(10));
+
+        Iterator<Correlation> i2 = correlator.iterator();
+        assertNextCorrelation(i2, 10, 10l, 8l, 7l);
+        assertFalse(i2.hasNext());
+    }
+
+    private void assertNextCorrelation(Iterator<Correlation> iter, long timestamp, Long... timestamps) {
+        assertTrue(iter.hasNext());
+        Correlation correlation = iter.next();
+        assertEquals(timestamp, correlation.getTimeStamp());
+        for (int i = 0 ; i < timestamps.length; i++) {
+            if (timestamps[i] == null) {
+                assertEquals(null, correlation.get(i));
+            } else {
+                assertEquals(timestamps[i].longValue(), correlation.get(i).getTimeStamp());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/BackendInformationTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+public class BackendInformationTest {
+
+    @Test
+    public void testConfigurationNotNull() {
+        BackendInformation backendInfo = new BackendInformation();
+        Map<String,String> config = backendInfo.getConfiguration();
+        assertNotNull(config);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/CategoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collection;
+
+import org.junit.Test;
+
+public class CategoryTest {
+
+    @Test
+    public void testHasBeenRegistered() {
+        Category category1 = new Category("testHasBeenRegistered");
+        assertFalse(category1.hasBeenRegistered());
+        ConnectionKey connKey = new ConnectionKey(){};
+        category1.setConnectionKey(connKey);
+        assertTrue(category1.hasBeenRegistered());
+    }
+
+    @Test
+    public void testGetKey() {
+        Key<String> key1 = new Key<String>("key1", false);
+        Category category = new Category("testGetKey", key1);
+        assertEquals(key1, category.getKey("key1"));
+    }
+
+    @Test
+    public void testGetNonExistingKey() {
+        Key<String> key1 = new Key<String>("key1", false);
+        Category category = new Category("testGetNonExistingKey", key1);
+        assertNull(category.getKey("key2"));
+    }
+
+    @Test
+    public void testGetKeys() {
+        Key<String> key1 = new Key<String>("key1", false);
+        Key<String> key2 = new Key<String>("key2", false);
+        Key<String> key3 = new Key<String>("key3", false);
+        Key<String> key4 = new Key<String>("key4", false);
+        Category category = new Category("testGetKeys", key1, key2, key3, key4);
+        assertEquals(4, category.getKeys().size());
+        assertTrue(category.getKeys().contains(key1));
+        assertTrue(category.getKeys().contains(key2));
+        assertTrue(category.getKeys().contains(key3));
+        assertTrue(category.getKeys().contains(key4));
+    }
+
+    @Test(expected=UnsupportedOperationException.class)
+    public void verifyThatKeysAreUnmodifiable() {
+        Key<String> key1 = new Key<String>("key1", false);
+        Key<String> key2 = new Key<String>("key2", false);
+        Key<String> key3 = new Key<String>("key3", false);
+        Category category = new Category("verifyThatKeysAreUnmodifiable", key1, key2, key3);
+
+        Collection<Key<?>> keys = category.getKeys();
+
+        keys.remove(key1);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/ChunkConverterTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+
+public class ChunkConverterTest {
+
+    private static final Key<String> key1 = new Key<>("key1", false);
+    private static final Key<String> key2 = new Key<>("key2", false);
+    private static final Key<String> key3 = new Key<>("key3", false);
+    private static final Key<String> key4 = new Key<>("key4", false);
+    private static final Key<String> key5 = new Key<>("key5", false);
+
+    private static final Key<String> key1_key1 = new Key<>("key1.key1", false);
+    private static final Key<String> key1_key2 = new Key<>("key1.key2", false);
+    private static final Key<String> key1_key2_key1 = new Key<>("key1.key2.key1", false);
+    private static final Key<String> key1_key2_key2 = new Key<>("key1.key2.key2", false);
+    private static final Key<String> key1_key2_key3 = new Key<>("key1.key2.key3", false);
+    private static final Key<String> key2_key1 = new Key<>("key2.key1", false);
+    private static final Key<String> key2_key2 = new Key<>("key2.key2", false);
+    private static final Key<String> key2_key3 = new Key<>("key2.key3", false);
+
+    private static final String mongoId = "_id";
+    private static final Key<String> invalidMongoIdKey = new Key<>(mongoId, false);
+
+    private static final Category testCategory = new Category("ChunkConverterTest", key1, key2, key3, key4, key5,
+                                                             key1_key1, key1_key2, key2_key1, key2_key2, key2_key3,
+                                                             key1_key2_key1, key1_key2_key2, key1_key2_key3);
+    private static final Category smallerCategory = new Category("SmallerTest", key1, key2);
+
+    @Test
+    public void verifyBasicChunkToDBObject() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, "test1");
+
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbObject = converter.chunkToDBObject(chunk);
+
+        assertEquals(1, dbObject.keySet().size());
+        assertTrue(dbObject.keySet().contains("key1"));
+        assertEquals("test1", dbObject.get("key1"));
+    }
+
+    @Test
+    public void verifyChunkToDBObjectInOrder() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key5, "test1");
+        chunk.put(key4, "test2");
+        chunk.put(key3, "test3");
+        chunk.put(key2, "test4");
+        chunk.put(key1, "test5");
+
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbObject = converter.chunkToDBObject(chunk);
+
+        assertEquals(5, dbObject.keySet().size());
+        assertArrayEquals(new String[]{"key5", "key4", "key3", "key2", "key1"}, dbObject.keySet().toArray());
+    }
+
+    @Test
+    public void verifyBasicDBObjectToChunk() {
+        BasicDBObject dbObject = new BasicDBObject();
+        dbObject.put("key1", "test1");
+
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
+
+        assertSame(testCategory, chunk.getCategory());
+        assertEquals(1, chunk.getKeys().size());
+        assertTrue(chunk.getKeys().contains(key1));
+        assertEquals("test1", chunk.get(key1));
+
+    }
+
+    @Test
+    public void verifyDBObjectToChunkInOrder() {
+        BasicDBObject dbObject = new BasicDBObject();
+        dbObject.put("key5", "test1");
+        dbObject.put("key4", "test2");
+        dbObject.put("key3", "test3");
+        dbObject.put("key2", "test4");
+        dbObject.put("key1", "test5");
+
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
+
+        assertSame(testCategory, chunk.getCategory());
+        assertEquals(5, chunk.getKeys().size());
+        assertArrayEquals(new Key<?>[]{ key5, key4, key3, key2, key1 }, chunk.getKeys().toArray());
+        assertEquals("test5", chunk.get(key1));
+        assertEquals("test4", chunk.get(key2));
+        assertEquals("test3", chunk.get(key3));
+        assertEquals("test2", chunk.get(key4));
+        assertEquals("test1", chunk.get(key5));
+
+    }
+
+    @Test
+    public void verifySimpleNestedChunkToObject() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1_key1, "test1");
+
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbObject = converter.chunkToDBObject(chunk);
+
+        assertEquals(1, dbObject.keySet().size());
+        assertTrue(dbObject.keySet().contains("key1"));
+        DBObject nested = (DBObject) dbObject.get("key1");
+        assertEquals(1, nested.keySet().size());
+        assertTrue(nested.keySet().contains("key1"));
+        assertEquals("test1", nested.get("key1"));
+    }
+
+    @Test
+    public void verifyComplexNestedChunkToObject() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1_key1, "test1");
+        chunk.put(key1_key2, "test2");
+        chunk.put(key2_key1, "test3");
+        chunk.put(key2_key2, "test4");
+        chunk.put(key2_key3, "test5");
+        chunk.put(key3, "test6");
+
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbObject = converter.chunkToDBObject(chunk);
+
+        assertEquals(3, dbObject.keySet().size());
+        assertTrue(dbObject.keySet().contains("key1"));
+        assertTrue(dbObject.keySet().contains("key2"));
+        assertTrue(dbObject.keySet().contains("key3"));
+        assertEquals("test6", dbObject.get("key3"));
+
+        DBObject nested1 = (DBObject) dbObject.get("key1");
+        assertEquals(2, nested1.keySet().size());
+        assertTrue(nested1.keySet().contains("key1"));
+        assertTrue(nested1.keySet().contains("key2"));
+        assertEquals("test1", nested1.get("key1"));
+        assertEquals("test2", nested1.get("key2"));
+
+        DBObject nested2 = (DBObject) dbObject.get("key2");
+        assertEquals(3, nested2.keySet().size());
+        assertTrue(nested2.keySet().contains("key1"));
+        assertTrue(nested2.keySet().contains("key2"));
+        assertTrue(nested2.keySet().contains("key3"));
+        assertEquals("test3", nested2.get("key1"));
+        assertEquals("test4", nested2.get("key2"));
+        assertEquals("test5", nested2.get("key3"));
+    }
+
+    @Test
+    public void verifyComplex3LevelChunkToObject() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1_key1, "test1");
+        chunk.put(key1_key2_key1, "test3");
+        chunk.put(key1_key2_key2, "test4");
+        chunk.put(key1_key2_key3, "test5");
+        chunk.put(key3, "test6");
+
+        ChunkConverter converter = new ChunkConverter();
+        DBObject dbObject = converter.chunkToDBObject(chunk);
+
+        assertEquals(2, dbObject.keySet().size());
+        assertTrue(dbObject.keySet().contains("key1"));
+        assertTrue(dbObject.keySet().contains("key3"));
+        assertEquals("test6", dbObject.get("key3"));
+
+        DBObject nested1 = (DBObject) dbObject.get("key1");
+        assertEquals(2, nested1.keySet().size());
+        assertTrue(nested1.keySet().contains("key1"));
+        assertTrue(nested1.keySet().contains("key2"));
+        assertEquals("test1", nested1.get("key1"));
+
+        DBObject nested2 = (DBObject) nested1.get("key2");
+        assertEquals(3, nested2.keySet().size());
+        assertTrue(nested2.keySet().contains("key1"));
+        assertTrue(nested2.keySet().contains("key2"));
+        assertTrue(nested2.keySet().contains("key3"));
+        assertEquals("test3", nested2.get("key1"));
+        assertEquals("test4", nested2.get("key2"));
+        assertEquals("test5", nested2.get("key3"));
+    }
+
+    @Test
+    public void verifySimpleNestedObjectToChunk() {
+        BasicDBObject nested = new BasicDBObject();
+        nested.put("key1", "test1");
+        BasicDBObject dbObject = new BasicDBObject();
+        dbObject.put("key1", nested);
+
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
+
+        assertSame(testCategory, chunk.getCategory());
+        assertEquals(1, chunk.getKeys().size());
+        assertTrue(chunk.getKeys().contains(key1_key1));
+        assertEquals("test1", chunk.get(key1_key1));
+    }
+
+    @Test
+    public void verifyComplexNestedObjectToChunk() {
+        BasicDBObject nested1 = new BasicDBObject();
+        nested1.put("key1", "test1");
+        nested1.put("key2", "test2");
+
+        BasicDBObject nested2 = new BasicDBObject();
+        nested2.put("key1", "test3");
+        nested2.put("key2", "test4");
+        nested2.put("key3", "test5");
+
+        BasicDBObject dbObject = new BasicDBObject();
+        dbObject.put("key1", nested1);
+        dbObject.put("key2", nested2);
+        dbObject.put("key3", "test6");
+
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
+
+        assertSame(testCategory, chunk.getCategory());
+
+        assertEquals(6, chunk.getKeys().size());
+        assertTrue(chunk.getKeys().contains(key1_key1));
+        assertTrue(chunk.getKeys().contains(key1_key2));
+        assertTrue(chunk.getKeys().contains(key2_key1));
+        assertTrue(chunk.getKeys().contains(key2_key2));
+        assertTrue(chunk.getKeys().contains(key2_key3));
+        assertTrue(chunk.getKeys().contains(key3));
+        assertEquals("test1", chunk.get(key1_key1));
+        assertEquals("test2", chunk.get(key1_key2));
+        assertEquals("test3", chunk.get(key2_key1));
+        assertEquals("test4", chunk.get(key2_key2));
+        assertEquals("test5", chunk.get(key2_key3));
+        assertEquals("test6", chunk.get(key3));
+    }
+
+    @Test
+    public void verifyComplex3LevelObjectToChunk() {
+
+        BasicDBObject nested2 = new BasicDBObject();
+        nested2.put("key1", "test3");
+        nested2.put("key2", "test4");
+        nested2.put("key3", "test5");
+
+        BasicDBObject nested1 = new BasicDBObject();
+        nested1.put("key1", "test1");
+        nested1.put("key2", nested2);
+
+        BasicDBObject dbObject = new BasicDBObject();
+        dbObject.put("key1", nested1);
+        dbObject.put("key3", "test6");
+
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
+
+        assertSame(testCategory, chunk.getCategory());
+
+        assertEquals(5, chunk.getKeys().size());
+        assertTrue(chunk.getKeys().contains(key1_key1));
+        assertTrue(chunk.getKeys().contains(key1_key2_key1));
+        assertTrue(chunk.getKeys().contains(key1_key2_key2));
+        assertTrue(chunk.getKeys().contains(key1_key2_key3));
+        assertTrue(chunk.getKeys().contains(key3));
+
+        assertEquals("test1", chunk.get(key1_key1));
+        assertEquals("test3", chunk.get(key1_key2_key1));
+        assertEquals("test4", chunk.get(key1_key2_key2));
+        assertEquals("test5", chunk.get(key1_key2_key3));
+        assertEquals("test6", chunk.get(key3));
+    }
+
+    @Test
+    public void verifyDBObjectToChunkIgnoresMongoID() {
+        DBObject obj = new BasicDBObject(mongoId, "mongo_private_info");
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(obj, new Category("invalidCategory", invalidMongoIdKey));
+
+        assertEquals(0, chunk.getKeys().size());
+    }
+
+    @Test
+    public void verifyDBObjectToChunkAvoidsNonExistentKeys() {
+        DBObject obj = new BasicDBObject("key1", "data1");
+        obj.put("key2", "data2");
+        obj.put("key3", "data3"); // This one is not a part of smallerCategory
+        ChunkConverter converter = new ChunkConverter();
+        Chunk chunk = converter.dbObjectToChunk(obj, smallerCategory);
+
+        assertEquals(2, chunk.getKeys().size());
+        assertFalse(chunk.getKeys().contains(key3));
+        assertTrue(chunk.getKeys().contains(key1));
+        assertTrue(chunk.getKeys().contains(key2));
+        assertEquals("data1", chunk.get(key1));
+        assertEquals("data2", chunk.get(key2));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/ChunkTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ChunkTest {
+
+    private static final Key<String> key1 = new Key<>("key1", false);
+    private static final Key<String> key2 = new Key<>("key2", false);
+    private static final Key<String> key3 = new Key<>("key3", false);
+    private static final Key<String> key4 = new Key<>("key4", false);
+    private static final Key<String> key5 = new Key<>("key5", false);
+    private static final Key<Integer> key6 = new Key<>("key6", false);
+    private static final Key<Object> key7 = new Key<>("key7", false);
+
+    private static final String value1 = "test1";
+    private static final String value2 = "test2";
+    private static final String value3 = "test3";
+    private static final String value4 = "test4";
+    private static final String value5 = "test5";
+    private static final int value6 = 12345;
+    private static final Object value7 = "test7";
+
+    private static final Category testCategory = new Category("ChunkTest", key1, key2, key3, key4, key5);
+    private static final Category testCategory2 = new Category("ChunkTest2", key1, key2, key3, key4, key5);
+
+    @Test
+    public void verifyGetCategoryNotNull() {
+        Chunk chunk = new Chunk(testCategory, false);
+        Category cat = chunk.getCategory();
+        assertNotNull(cat);
+    }
+
+    @Test
+    public void verifyGetCategoryReturnsCorrectCategory() {
+        Chunk chunk = new Chunk(testCategory, false);
+        Category cat = chunk.getCategory();
+        assertEquals(cat, testCategory);
+    }
+
+    @Test
+    public void verifyGetReplaceReturnsCorrectValue() {
+        Chunk chunk = new Chunk(testCategory, false);
+        boolean replace = chunk.getReplace();
+        assertFalse(replace);
+        chunk = new Chunk(testCategory, true);
+        replace = chunk.getReplace();
+        assertTrue(replace);
+    }
+
+    @Test
+    public void verifyPutActuallyPuts() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, value1);
+        int pieces = chunk.getKeys().size();
+        assertEquals(pieces, 1);
+    }
+
+    @Test
+    public void verifyPutPutsCorrectly() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, value1);
+        String value = chunk.get(key1);
+        assertEquals(value, value1);
+    }
+
+    @Test
+    public void verifyPutAcceptsVariousTypes() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, value1);
+        chunk.put(key5, value5);
+        chunk.put(key6, value6);
+        chunk.put(key7, value7);
+        int pieces = chunk.getKeys().size();
+        assertEquals(pieces, 4);
+    }
+
+    @Test
+    public void verifyEntriesAreKeptInOrder() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key5, value5);
+        chunk.put(key4, value4);
+        chunk.put(key3, value3);
+        chunk.put(key2, value2);
+        chunk.put(key1, value1);
+
+        assertArrayEquals(new Key<?>[]{key5, key4, key3, key2, key1}, chunk.getKeys().toArray());
+    }
+
+    @Test
+    public void verifyGetNotNull() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, value1);
+        String value = chunk.get(key1);
+        assertNotNull(value);
+    }
+
+    @Test
+    public void verifyGetNullWhenExpected() {
+        Chunk chunk = new Chunk(testCategory, false);
+        chunk.put(key1, value1);
+        String value = chunk.get(key2);
+        assertNull(value);
+    }
+
+
+    @Test
+    public void testEqualsBasicEquals() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        Chunk chunk2 = new Chunk(testCategory, false);
+        assertTrue(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsDifferentCategory() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        Chunk chunk2 = new Chunk(testCategory2, false);
+        assertFalse(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsDifferentReplace() {
+        // TODO: Do we want to differentiate chunks by that flag? I think not. Maybe it doesn't even belong in chunk.
+        Chunk chunk1 = new Chunk(testCategory, false);
+        Chunk chunk2 = new Chunk(testCategory, true);
+        assertTrue(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsDifferentType() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        assertFalse(chunk1.equals("fluff"));
+    }
+
+    @Test
+    public void testEqualsNull() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        assertFalse(chunk1.equals(null));
+    }
+
+    @Test
+    public void testEqualsDifferentNumberOfValues() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        chunk1.put(key1, "value1");
+        chunk1.put(key2, "value2");
+        Chunk chunk2 = new Chunk(testCategory, true);
+        chunk2.put(key1, "value1");
+        assertFalse(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsDifferentKeys() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        chunk1.put(key1, "value1");
+        chunk1.put(key2, "value2");
+        Chunk chunk2 = new Chunk(testCategory, true);
+        chunk2.put(key1, "value1");
+        chunk2.put(key3, "value2");
+        assertFalse(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsDifferentValues() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        chunk1.put(key1, "value1");
+        chunk1.put(key2, "value2.1");
+        Chunk chunk2 = new Chunk(testCategory, true);
+        chunk2.put(key1, "value1");
+        chunk2.put(key2, "value2.2");
+        assertFalse(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsSameValues() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        chunk1.put(key1, "value1");
+        chunk1.put(key2, "value2");
+        Chunk chunk2 = new Chunk(testCategory, true);
+        chunk2.put(key1, "value1");
+        chunk2.put(key2, "value2");
+        assertTrue(chunk1.equals(chunk2));
+    }
+
+    @Test
+    public void testEqualsNullValues() {
+        Chunk chunk1 = new Chunk(testCategory, false);
+        chunk1.put(key1, "value1");
+        chunk1.put(key2, null);
+        Chunk chunk2 = new Chunk(testCategory, true);
+        chunk2.put(key1, "value1");
+        chunk2.put(key2, null);
+        assertTrue(chunk1.equals(chunk2));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+
+public class ConnectionTest {
+
+    private Connection connection;
+
+    private Connection.ConnectionListener listener1;
+    private Connection.ConnectionListener listener2;
+
+    @Before
+    public void setUp() {
+
+        connection = new Connection() {
+            
+            @Override
+            public void disconnect() {
+                // TODO Auto-generated method stub
+                
+            }
+            
+            @Override
+            public void connect() {
+                // TODO Auto-generated method stub
+                
+            }
+        };
+        listener1 = mock(Connection.ConnectionListener.class);
+        listener2 = mock(Connection.ConnectionListener.class);
+        connection.addListener(listener1);
+        connection.addListener(listener2);
+    }
+
+    @After
+    public void tearDown() {
+        connection = null;
+        listener1 = null;
+        listener2 = null;
+    }
+
+    @Test
+    public void testListenersConnecting() throws Exception {
+        verifyListenersStatus(ConnectionStatus.CONNECTING);
+    }
+
+    @Test
+    public void testListenersConnected() throws Exception {
+        verifyListenersStatus(ConnectionStatus.CONNECTED);
+    }
+
+    @Test
+    public void testListenersFailedToConnect() throws Exception {
+        verifyListenersStatus(ConnectionStatus.FAILED_TO_CONNECT);
+    }
+
+    @Test
+    public void testListenersDisconnected() throws Exception {
+        verifyListenersStatus(ConnectionStatus.DISCONNECTED);
+    }
+
+    private void verifyListenersStatus(ConnectionStatus status) {
+        connection.fireChanged(status);
+        verify(listener1).changed(status);
+        verify(listener2).changed(status);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/KeyTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class KeyTest {
+    private static final String name1 = "key1";
+    private static final String name2 = "key2";
+    private static final String name3 = "key3";
+
+    private static final Key<String> key1 = new Key<>(name1, true);
+    private static final Key<String> key2 = new Key<>(name2, true);
+    private static final Key<String> key3 = new Key<>(name3, false);
+    private static final Key<String> key4 = new Key<>(name1, false);
+    private static final Key<String> key5 = new Key<>(name1, true);
+
+    @Test
+    public void verifyConstructorResultsInExpectedValues() {
+        Key<String> key = new Key<>(name1, true);
+        assertEquals(key.getName(), name1);
+        assertTrue(key.isPartialCategoryKey());
+        key = new Key<>(name2, false);
+        assertEquals(key.getName(), name2);
+        assertFalse(key.isPartialCategoryKey());
+    }
+
+    @Test (expected=IllegalArgumentException.class)
+    public void verifyConstructorThrowsExceptionOnNullName() {
+        @SuppressWarnings("unused")
+        Key<String> key = new Key<>(null, true);
+    }
+
+    @Test (expected=IllegalArgumentException.class)
+    public void verifyConstructorThrowsExceptionZeroLengthName() {
+        @SuppressWarnings("unused")
+        Key<String> key = new Key<>("", true);
+    }
+
+    @Test
+    public void verifyGetNameNotNull() {
+        String name = key1.getName();
+        assertNotNull(name);
+    }
+
+    @Test
+    public void verifyGetNameReturnsCorrectName() {
+        String name = key1.getName();
+        assertEquals(name, name1);
+        name = key2.getName();
+        assertEquals(name, name2);
+    }
+
+    @Test
+    public void verifyIsPartialCategoryKeyReturnsCorrectValue() {
+        boolean value = key1.isPartialCategoryKey();
+        assertTrue(value);
+        value = key3.isPartialCategoryKey();
+        assertFalse(value);
+    }
+
+    @Test
+    public void verifyEqualsReturnsCorrectValue() {
+        assertThat(key1, not(equalTo(key2)));
+        assertThat(key1, not(equalTo(key3)));
+        assertThat(key1, not(equalTo(key4)));
+        assertThat(key1, equalTo(key5));
+    }
+
+    @Test
+    public void verifyHashCodeReturnsValidCode() {
+        int key1hash1 = key1.hashCode();
+        int key1hash2 = key1.hashCode();
+        assertEquals(key1hash1, key1hash2);
+        int key5hash1 = key5.hashCode();
+        assertEquals(key1hash1, key5hash1);
+    }
+
+    @Test
+    public void toStringNotNull() {
+        String string1 = key1.toString();
+        assertNotNull(string1);
+    }
+
+    @Test
+    public void toStringReturnsExpectedString() {
+        String string1 = key1.toString();
+        assertEquals(string1, "Key: key1");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+import com.mongodb.MongoURI;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+
+@PrepareForTest(MongoConnection.class)
+@RunWith(PowerMockRunner.class)
+public class MongoConnectionTest {
+
+    private MongoConnection conn;
+    private ConnectionListener listener;
+
+    @Before
+    public void setUp() {
+        StartupConfiguration conf = mock(StartupConfiguration.class);
+        when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518");
+        conn = new MongoConnection(conf);
+        listener = mock(ConnectionListener.class);
+        conn.addListener(listener);
+    }
+
+    @After
+    public void tearDown() {
+        conn = null;
+    }
+
+    @Test
+    public void testConnectSuccess() throws Exception {
+        DBCollection collection = mock(DBCollection.class);
+        DB db = mock(DB.class);
+        when(db.getCollection("agent-config")).thenReturn(collection);
+        Mongo m = mock(Mongo.class);
+        when(m.getDB(StorageConstants.THERMOSTAT_DB_NAME)).thenReturn(db);
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        conn.connect();
+
+        verify(listener).changed(ConnectionStatus.CONNECTED);
+    }
+
+    @Test
+    public void testConnectIOException() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new IOException());
+        boolean exceptionThrown = false;
+        try {
+            conn.connect();
+        } catch (ConnectionException ex) {
+            exceptionThrown = true;
+        }
+        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
+        assertTrue(exceptionThrown);
+    }
+
+    @Test
+    public void testConnectMongoException() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new MongoException("fluff"));
+        boolean exceptionThrown = false;
+        try {
+            conn.connect();
+        } catch (ConnectionException ex) {
+            exceptionThrown = true;
+        }
+
+        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
+        assertTrue(exceptionThrown);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+
+public class MongoCursorTest {
+
+    private static final Key<String> key1 = new Key<>("key1", false);
+    private static final Key<String> key2 = new Key<>("key2", false);
+    private static final Key<String> key3 = new Key<>("key3", false);
+    private static final Key<String> key4 = new Key<>("key4", false);
+
+    private static final Category testCategory = new Category("MongoCursorTest", key1, key2, key3, key4);
+
+    private DBCursor dbCursor;
+    private Cursor cursor;
+
+    @Before
+    public void setUp() {
+        
+        BasicDBObject value1 = new BasicDBObject();
+        value1.put("key1", "test1");
+        value1.put("key2", "test2");
+        BasicDBObject value2 = new BasicDBObject();
+        value2.put("key3", "test3");
+        value2.put("key4", "test4");
+
+        dbCursor = mock(DBCursor.class);
+        when(dbCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(dbCursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
+        when(dbCursor.sort(any(DBObject.class))).thenReturn(dbCursor);
+        when(dbCursor.limit(anyInt())).thenReturn(dbCursor);
+        cursor = new MongoCursor(dbCursor, testCategory);
+
+    }
+
+    @After
+    public void tearDown() {
+        dbCursor = null;
+        cursor = null;
+    }
+
+    @Test
+    public void verifySimpleCursor() {
+
+        assertTrue(cursor.hasNext());
+        Chunk chunk1 = cursor.next();
+        assertArrayEquals(new Key<?>[]{key1, key2}, chunk1.getKeys().toArray());
+        assertEquals("test1", chunk1.get(key1));
+        assertEquals("test2", chunk1.get(key2));
+
+        assertTrue(cursor.hasNext());
+        Chunk chunk2 = cursor.next();
+        assertArrayEquals(new Key<?>[]{key3, key4}, chunk2.getKeys().toArray());
+        assertEquals("test3", chunk2.get(key3));
+        assertEquals("test4", chunk2.get(key4));
+
+        assertFalse(cursor.hasNext());
+        assertNull(cursor.next());
+    }
+
+    @Test
+    public void verifyCursorSort() {
+        ArgumentCaptor<DBObject> arg = ArgumentCaptor.forClass(DBObject.class);
+        Cursor sorted = cursor.sort(key1, Cursor.SortDirection.ASCENDING);
+
+        verify(dbCursor).sort(arg.capture());
+        DBObject orderByDBObject = arg.getValue();
+        assertEquals(1, orderByDBObject.keySet().size());
+        assertEquals((Integer) Cursor.SortDirection.ASCENDING.getValue(), orderByDBObject.get(key1.getName()));
+        // Verify that the sorted cursor is still return the same number of items. We leave the actual
+        // sorting to Mongo and won't check it here.
+        assertTrue(sorted.hasNext());
+        sorted.next();
+        assertTrue(sorted.hasNext());
+        sorted.next();
+        assertFalse(sorted.hasNext());
+    }
+
+    @Test
+    public void verifyCursorLimit() {
+
+        Cursor sorted = cursor.limit(1);
+
+        verify(dbCursor).limit(1);
+
+        // We cannot really test if the cursor really got limited, this is up to the mongo implementation.
+        // In any case, we can verify that the returned cursor actually is 'active'.
+        assertTrue(sorted.hasNext());
+        sorted.next();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+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.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import com.mongodb.Mongo;
+import com.mongodb.MongoURI;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ DBCollection.class, DB.class, Mongo.class, MongoStorage.class, MongoConnection.class })
+public class MongoStorageTest {
+
+    private static final Key<String> key1 = new Key<>("key1", false);
+    private static final Key<String> key2 = new Key<>("key2", false);
+    private static final Key<String> key3 = new Key<>("key3", false);
+    private static final Key<String> key4 = new Key<>("key4", false);
+    private static final Key<String> key5 = new Key<>("key5", false);
+    private static final Category testCategory = new Category("MongoStorageTest", key1, key2, key3, key4, key5);
+    private static final Category emptyTestCategory = new Category("MongoEmptyCategory");
+
+    private StartupConfiguration conf;
+    private Chunk multiKeyQuery;
+    private Mongo m;
+    private DB db;
+    private DBCollection testCollection, emptyTestCollection, mockedCollection;
+
+    private MongoStorage makeStorage() throws Exception {
+        MongoStorage storage = new MongoStorage(conf);
+        storage.mapCategoryToDBCollection(testCategory, testCollection);
+        storage.mapCategoryToDBCollection(emptyTestCategory, emptyTestCollection);
+        return storage;
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        conf = mock(StartupConfiguration.class);
+        when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518");
+        db = PowerMockito.mock(DB.class);
+        m = PowerMockito.mock(Mongo.class);
+        mockedCollection = mock(DBCollection.class);
+        when(m.getDB(anyString())).thenReturn(db);
+        when(db.getCollection("agent-config")).thenReturn(mockedCollection);
+        when(db.collectionExists(anyString())).thenReturn(true);
+
+        BasicDBObject value1 = new BasicDBObject();
+        value1.put("key1", "test1");
+        value1.put("key2", "test2");
+        BasicDBObject value2 = new BasicDBObject();
+        value2.put("key3", "test3");
+        value2.put("key4", "test4");
+
+        multiKeyQuery = new Chunk(testCategory, false);
+        multiKeyQuery.put(key5, "test1");
+        multiKeyQuery.put(key4, "test2");
+        multiKeyQuery.put(key3, "test3");
+        multiKeyQuery.put(key2, "test4");
+        multiKeyQuery.put(key1, "test5");
+
+        DBCursor cursor = mock(DBCursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
+
+        testCollection = PowerMockito.mock(DBCollection.class);
+        when(testCollection.find(any(DBObject.class))).thenReturn(cursor);
+        when(testCollection.find()).thenReturn(cursor);
+        when(testCollection.findOne(any(DBObject.class))).thenReturn(value1);
+        when(testCollection.getCount()).thenReturn(2L);
+        emptyTestCollection = PowerMockito.mock(DBCollection.class);
+        when(emptyTestCollection.getCount()).thenReturn(0L);
+        when(db.collectionExists(anyString())).thenReturn(false);
+        when(db.createCollection(anyString(), any(DBObject.class))).thenReturn(testCollection);
+    }
+
+    @After
+    public void tearDown() {
+        conf = null;
+        m = null;
+        db = null;
+        testCollection = null;
+        emptyTestCollection = null;
+        multiKeyQuery = null;
+    }
+
+    @Test
+    public void testCreateConnectionKey() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        storage.getConnection().connect();
+        Category category = new Category("testCreateConnectionKey");
+        ConnectionKey connKey = storage.createConnectionKey(category);
+        assertNotNull(connKey);
+    }
+
+    @Test 
+    public void verifyFindAllReturnsCursor() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        Cursor cursor = storage.findAll(query);
+        assertNotNull(cursor);
+    }
+
+    @Test
+    public void verifyFindReturnsChunk() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        query.put(key1, "test1");
+        Chunk result = storage.find(query);
+        assertNotNull(result);
+    }
+
+    @Test
+    public void verifyFindAllCallsDBCollectionFind() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        storage.findAll(query);
+        verify(testCollection).find(any(DBObject.class));
+    }
+
+    @Test
+    public void verifyFindCallsDBCollectionFindOne() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        storage.find(query);
+        verify(testCollection).findOne(any(DBObject.class));
+    }
+
+    @Test
+    public void verifyFindAllCallsDBCollectionFindWithCorrectQuery() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        query.put(key1, "test");
+        storage.findAll(query);
+
+        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).find(findArg.capture());
+
+        DBObject arg = findArg.getValue();
+        assertEquals(1, arg.keySet().size());
+        assertTrue(arg.keySet().contains("key1"));
+        assertEquals("test", arg.get("key1"));
+    }
+
+    @Test
+    public void verifyFindCallsDBCollectionFindOneWithCorrectQuery() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Chunk query = new Chunk(testCategory, false);
+        query.put(key1, "test");
+        storage.find(query);
+
+        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).findOne(findArg.capture());
+
+        DBObject arg = findArg.getValue();
+        assertEquals(1, arg.keySet().size());
+        assertTrue(arg.keySet().contains("key1"));
+        assertEquals("test", arg.get("key1"));
+    }
+
+    @Test
+    public void verifyFindAllWithMultiKeys() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        storage.findAll(multiKeyQuery);
+
+        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).find(findArg.capture());
+
+        DBObject arg = findArg.getValue();
+        assertArrayEquals(new String[]{ "key5", "key4", "key3", "key2", "key1" }, arg.keySet().toArray());
+    }
+
+    @Test
+    public void verifyFindWithMultiKeys() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        storage.find(multiKeyQuery);
+
+        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
+        verify(testCollection).findOne(findArg.capture());
+
+        DBObject arg = findArg.getValue();
+        assertArrayEquals(new String[]{ "key5", "key4", "key3", "key2", "key1" }, arg.keySet().toArray());
+    }
+
+    @Test
+    public void verifyFindReturnsCorrectChunk() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        // TODO find a way to test this that isn't just testing mock and converters
+        Chunk query = new Chunk(testCategory, false);
+        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
+        query.put(key5, "test1");
+
+        Chunk result = storage.find(query);
+
+        assertNotNull(result);
+        assertArrayEquals(new Key<?>[]{key1, key2}, result.getKeys().toArray());
+        assertEquals("test1", result.get(key1));
+        assertEquals("test2", result.get(key2));
+    }
+
+    @Test
+    public void verifyFindAllReturnsCorrectCursor() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        // TODO find a way to test this that isn't just testing MongoCursor
+        Chunk query = new Chunk(testCategory, false);
+        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
+        query.put(key5, "test1");
+
+        Cursor cursor = storage.findAll(query);
+
+        verifyDefaultCursor(cursor);
+    }
+
+    @Test
+    public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        storage.findAllFromCategory(testCategory);
+        verify(testCollection).find();
+    }
+
+    @Test
+    public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        Cursor cursor = storage.findAllFromCategory(testCategory);
+
+        verifyDefaultCursor(cursor);
+    }
+
+    @Test
+    public void verifyGetCount() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        long count = storage.getCount(testCategory);
+        assertEquals(2, count);
+    }
+
+    @Test
+    public void verifyGetCountForEmptyCategory() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        long count = storage.getCount(emptyTestCategory);
+        assertEquals(0, count);
+    }
+
+    @Test
+    public void verifyGetCountForNonexistentCategory() throws Exception {
+        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
+        MongoStorage storage = makeStorage();
+        storage.getConnection().connect();
+        long count = storage.getCount(new Category("NonExistent"));
+        assertEquals(0, count);
+    }
+
+    private void verifyDefaultCursor(Cursor cursor) {
+        assertTrue(cursor.hasNext());
+        Chunk chunk1 = cursor.next();
+        assertArrayEquals(new Key<?>[]{key1, key2}, chunk1.getKeys().toArray());
+        assertEquals("test1", chunk1.get(key1));
+        assertEquals("test2", chunk1.get(key2));
+
+        assertTrue(cursor.hasNext());
+        Chunk chunk2 = cursor.next();
+        assertArrayEquals(new Key<?>[]{key3, key4}, chunk2.getKeys().toArray());
+        assertEquals("test3", chunk2.get(key3));
+        assertEquals("test4", chunk2.get(key4));
+
+        assertFalse(cursor.hasNext());
+        assertNull(cursor.next());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/StorageTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.storage;
+
+import static org.junit.Assert.assertSame;
+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.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StorageTest {
+
+    private Storage storage;
+    private ConnectionKey connKey;
+
+    @Before
+    public void setUp() {
+        storage = mock(Storage.class);
+        connKey = new ConnectionKey(){};
+        when(storage.createConnectionKey(any(Category.class))).thenReturn(connKey);
+    }
+
+    @After
+    public void tearDown() {
+        storage = null;
+        connKey = null;
+    }
+
+    @Test
+    public void testRegisterCategory() {
+        Category category = new Category("testRegisterCategory");
+        storage.registerCategory(category);
+
+        verify(storage).createConnectionKey(category);
+        assertSame(connKey, category.getConnectionKey());
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testRegisterCategoryTwice() {
+
+        Category category = new Category("test");
+        storage.registerCategory(category);
+        storage.registerCategory(category);
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testRegisterCategorySameName() {
+
+        Category category1 = new Category("test");
+        storage.registerCategory(category1);
+        Category category2 = new Category("test");
+        storage.registerCategory(category2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/tools/BasicCommandTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.tools;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collection;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.ArgumentSpec;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.config.StartupConfiguration;
+import com.redhat.thermostat.common.tools.BasicCommand;
+
+public class BasicCommandTest {
+
+    private BasicCommand application;
+
+    @Before
+    public void setUp() {
+        application = new BasicCommand() {
+
+            @Override
+            public void run(CommandContext ctx) throws CommandException {
+                // Nothing to do here.
+            }
+
+            @Override
+            public void disable() {
+                // Move along
+            }
+
+            @Override
+            public String getName() {
+                return null;
+            }
+
+            @Override
+            public String getDescription() {
+                return null;
+            }
+
+            @Override
+            public String getUsage() {
+                return null;
+            }
+
+            @Override
+            public StartupConfiguration getConfiguration() {
+                return null;
+            }
+
+            @Override
+            public Collection<ArgumentSpec> getAcceptedArguments() {
+                return null;
+            }
+
+            @Override
+            public boolean isStorageRequired() {
+                return false;
+            }
+        };
+    }
+
+    @After
+    public void tearDown() {
+        application = null;
+    }
+
+    @Test
+    public void testNotfier() {
+        assertNotNull(application.getNotifier());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/utils/DisplayableValuesTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.utils.DisplayableValues.Scale;
+
+public class DisplayableValuesTest {
+
+    private static Locale defaultLocale;
+
+    @BeforeClass
+    public static void setUp() {
+        defaultLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        Locale.setDefault(defaultLocale);
+    }
+
+    @Test
+    public void testBytes() {
+        testBytesOutput("1", "B", DisplayableValues.bytes(1));
+        testBytesOutput("1023", "B", DisplayableValues.bytes(1023));
+        testBytesOutput("1.0", "KiB", DisplayableValues.bytes(1024));
+        testBytesOutput("1024.0", "KiB", DisplayableValues.bytes(1_048_575));
+        testBytesOutput("1.0", "MiB", DisplayableValues.bytes(1_048_576));
+        testBytesOutput("10.0", "MiB", DisplayableValues.bytes(10_480_000));
+        testBytesOutput("42.0", "MiB", DisplayableValues.bytes(44_040_000));
+        testBytesOutput("99.9", "MiB", DisplayableValues.bytes(104_752_742));
+        testBytesOutput("100.0", "MiB", DisplayableValues.bytes(104_857_600));
+        testBytesOutput("500.0", "MiB", DisplayableValues.bytes(524_288_000));
+        testBytesOutput("900.0", "MiB", DisplayableValues.bytes(943_718_400));
+        testBytesOutput("999.9", "MiB", DisplayableValues.bytes(1_048_471_000));
+        testBytesOutput("1.0", "GiB", DisplayableValues.bytes(1_073_741_824));
+        testBytesOutput("1.1", "GiB", DisplayableValues.bytes(1_181_116_000));
+        testBytesOutput("9.9", "GiB", DisplayableValues.bytes(10_630_044_000l));
+        testBytesOutput("99.9", "GiB", DisplayableValues.bytes(107_266_808_000l));
+        testBytesOutput("1.0", "TiB", DisplayableValues.bytes(1_099_511_627_776l));
+    }
+
+    private void testBytesOutput(String number, String units, String[] output) {
+        assertEquals(2, output.length);
+        assertEquals(number, output[0]);
+        assertEquals(units, output[1]);
+    }
+    
+    @Test
+    public void testScales() {
+        
+        double value = Scale.convertTo(Scale.KiB, 1024);
+        assertEquals(1, value, 0);
+        
+        value = Scale.convertTo(Scale.KiB, 2048);
+        assertEquals(2, value, 0);
+        
+        value = Scale.convertTo(Scale.KiB, 524_288);
+        assertEquals(512, value, 0);
+        
+        value = Scale.convertTo(Scale.MiB, 524_288_000);
+        assertEquals(500, value, 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/test/ExceptionThrowingInputStreamTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/test/TestCommandContextFactoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/test/TestTimerFactoryTest.java	Tue Jun 12 14:02:16 2012 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are 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/common/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/common/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -44,45 +44,11 @@
     <artifactId>thermostat</artifactId>
     <version>0.3-SNAPSHOT</version>
   </parent>
-  
+
   <artifactId>thermostat-common</artifactId>
-  <packaging>bundle</packaging>
+  <packaging>pom</packaging>
 
   <name>Thermostat Common</name>
-  <url>${project.parent.url}</url>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>1.4.0</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.common.Activator</Bundle-Activator>
-            <Export-Package>
-              com.redhat.thermostat.common.cli,
-              com.redhat.thermostat.common.tools,
-              com.redhat.thermostat.common,
-              com.redhat.thermostat.common.appctx,
-              com.redhat.thermostat.common.config,
-              com.redhat.thermostat.common.dao,
-              com.redhat.thermostat.common.model,
-              com.redhat.thermostat.common.storage,
-              com.redhat.thermostat.common.utils,
-            </Export-Package>
-            <Private-Package>
-              com.redhat.thermostat.test,
-              com.redhat.thermostat.tools,
-            </Private-Package>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-
-  </build>
 
   <dependencies>
     <dependency>
@@ -90,40 +56,11 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.powermock</groupId>
-      <artifactId>powermock-api-mockito</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.powermock</groupId>
-      <artifactId>powermock-module-junit4</artifactId>
-      <scope>test</scope>
-    </dependency>
+  </dependencies>
 
-    <dependency>
-      <groupId>org.mongodb</groupId>
-      <artifactId>mongo-java-driver</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-cli</groupId>
-      <artifactId>commons-cli</artifactId>
-    </dependency>
-    
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    
-  </dependencies>
-  
-  <properties>
-  	<argLine>-XX:-UseSplitVerifier</argLine>
-  </properties>
+  <modules>
+    <module>core</module>
+    <module>command</module>
+  </modules>
+
 </project>
--- a/common/src/main/java/com/redhat/thermostat/common/ActionEvent.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.EventObject;
-
-public class ActionEvent<T extends Enum<?>> extends EventObject {
-
-    private static final long serialVersionUID = -8648206929150142342L;
-
-    private Object payload;
-    
-    public ActionEvent(Object source, T actionId) {
-        super(source);
-        if (actionId == null) {
-            throw new NullPointerException();
-        }
-        this.actionId = actionId;
-    }
-
-    private T actionId;
-
-    public T getActionId() {
-        return actionId;
-    }
-
-    public Object getPayload() {
-        return payload;
-    }
-    
-    public void setPayload(Object payload) {
-        this.payload = payload;
-    }
-    
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result
-                + actionId.hashCode();
-        result = prime * result + source.hashCode();
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        @SuppressWarnings("rawtypes")
-        ActionEvent other = (ActionEvent) obj;
-        if (! actionId.equals(other.actionId)) {
-            return false;
-        }
-        if (! source.equals(other.source)) {
-            return false;
-        }
-        return true;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/ActionListener.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public interface ActionListener<T extends Enum<?>> {
-
-    void actionPerformed(ActionEvent<T> actionEvent);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/ActionNotifier.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.Collection;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class ActionNotifier<T extends Enum<?>> {
-
-    public ActionNotifier(Object source) {
-        this.source = source;
-        listeners = new CopyOnWriteArrayList<ActionListener<T>>();
-    }
-
-    private final Collection<ActionListener<T>> listeners;
-
-    private final Object source;
-
-    public void addActionListener(ActionListener<T> listener) {
-        listeners.add(listener);
-    }
-
-    public void removeActionListener(ActionListener<T> listener) {
-        listeners.remove(listener);
-    }
-
-    public void fireAction(T actionId) {
-        ActionEvent<T> action = new ActionEvent<>(source, actionId);
-        for (ActionListener<T> listener : listeners) {
-            listener.actionPerformed(action);
-        }
-    }
-
-    public void fireAction(T actionId, Object payload) {
-        ActionEvent<T> action = new ActionEvent<>(source, actionId);
-        action.setPayload(payload);
-        for (ActionListener<T> listener : listeners) {
-            listener.actionPerformed(action);
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/Activator.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.ServiceLoader;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandContextFactory;
-import com.redhat.thermostat.common.cli.CommandRegistry;
-import com.redhat.thermostat.common.cli.CommandRegistryImpl;
-import com.redhat.thermostat.common.cli.Launcher;
-import com.redhat.thermostat.common.cli.LauncherImpl;
-
-public class Activator implements BundleActivator {
-
-    private ServiceRegistration launcherReg;
-    private CommandRegistry reg;
-
-    @Override
-    public void start(BundleContext context) throws Exception {
-        reg = new CommandRegistryImpl(context);
-        ServiceLoader<Command> cmds = ServiceLoader.load(Command.class, getClass().getClassLoader());
-        reg.registerCommands(cmds);
-
-        CommandContextFactory cmdCtxFactory = new CommandContextFactory(context);
-        Launcher launcher = new LauncherImpl(cmdCtxFactory);
-        launcherReg = context.registerService(Launcher.class.getName(), launcher, null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        launcherReg.unregister();
-        reg.unregisterCommands();
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/Clock.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public interface Clock {
-
-    /**
-     * Returns the current real time in milliseconds (measured since the UNIX epoch).
-     */
-    long getRealTimeMillis();
-
-    /**
-     * Returns a time value corresponding to a monotonic clock measuring time
-     * in nanoseconds since some unspecified epoch.
-     */
-    long getMonotonicTimeNanos();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/Constants.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-/**
- * A grab bag of constants. This could be cleaned up later, but lets throw
- * things here for now.
- */
-public class Constants {
-
-    public static final int EXIT_UNKNOWN_ERROR = 1;
-    public static final int EXIT_UNABLE_TO_CONNECT_TO_DATABASE = 2;
-    public static final int EXIT_UNABLE_TO_READ_PROPERTIES = 3;
-    public static final int EXIT_CONFIGURATION_ERROR = 4;
-    public static final int EXIT_BACKEND_LOAD_ERROR = 5;
-    public static final int EXIT_BACKEND_START_ERROR = 6;
-
-    public static final int SAMPLING_INTERVAL_UNKNOWN = -1;
-
-    public static final String AGENT_ARGUMENT_LOCAL = "--local";
-    public static final String AGENT_ARGUMENT_LOGLEVEL = "--loglevel";
-    public static final String AGENT_ARGUMENT_DEVEL = "--devel";
-    public static final String AGENT_ARGUMENT_PROPERTIES = "--properties";
-
-    public static final String AGENT_PROPERTY_MONGOS_PORT = "mongos_port";
-    public static final String AGENT_PROPERTY_MONGOD_PORT = "mongod_port";
-    public static final String AGENT_PROPERTY_MONGO_LAUNCH_SCRIPT = "mongo_launch_script";
-    public static final String AGENT_PROPERTY_BACKENDS = "backends";
-    public static final String AGENT_PROPERTY_BACKEND_ACTIVE = "active";
-
-    public static final String CLIENT_PROPERTY_AGENT_LAUNCH_SCRIPT = "agent_launch_script";
-
-    public static final String AGENT_LOCAL_HOSTNAME = "localhost";
-
-    public static final long KILOBYTES_TO_BYTES = 1000;
-
-    public static final int HOST_INFO_NETWORK_IPV4_INDEX = 0;
-    public static final int HOST_INFO_NETWORK_IPV6_INDEX = 1;
-
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/LaunchException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-/**
- * Exception that should be thrown when a condition is detected that prevents proper startup
- * of program.
- *
- */
-public class LaunchException extends Exception {
-
-    private static final long serialVersionUID = -6757521147558143649L;
-
-    public LaunchException(String message) {
-        super(message);
-    }
-
-    public LaunchException(String message, Exception cause) {
-        super(message, cause);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/LogFormatter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.logging.Formatter;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
-public class LogFormatter extends Formatter {
-
-    @Override
-    public synchronized String format(LogRecord record) {
-        StringBuilder sb = new StringBuilder();
-        Level level = record.getLevel();
-        if (level.intValue() >= Level.WARNING.intValue()) {
-            sb.append(level.toString() + " - ");
-        }
-        String[] fullLoggingClassName = record.getSourceClassName().split("\\.");
-        String loggingClassName = fullLoggingClassName[fullLoggingClassName.length - 1];
-        sb.append(loggingClassName);
-        sb.append(": ");
-        sb.append(record.getMessage());
-        sb.append("\n");
-        Throwable thrown = record.getThrown();
-        String indent = "  ";
-        while (thrown != null) {
-            sb.append(indent);
-            sb.append("Caused by:\n");
-            sb.append(indent);
-            sb.append(thrown.getClass().getCanonicalName());
-            sb.append(": ");
-            sb.append(thrown.getMessage());
-            sb.append("\n");
-            StackTraceElement[] stack = thrown.getStackTrace();
-            for (int i = 0; i < stack.length; i++) {
-                sb.append(indent);
-                sb.append(stack[i].toString());
-                sb.append("\n");
-            }
-            thrown = thrown.getCause();
-            indent = indent.concat("  ");
-        }
-        return sb.toString();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/NotImplementedException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public class NotImplementedException extends RuntimeException {
-
-    private static final long serialVersionUID = -1620198443624195618L;
-
-    public NotImplementedException(String message) {
-        super(message);
-    }
-
-    public NotImplementedException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/SystemClock.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public class SystemClock implements Clock {
-
-    @Override
-    public long getRealTimeMillis() {
-        return System.currentTimeMillis();
-    }
-
-    @Override
-    public long getMonotonicTimeNanos() {
-        return System.nanoTime();
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/ThreadPoolTimerFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-public class ThreadPoolTimerFactory implements TimerFactory {
-
-    public ThreadPoolTimerFactory(int poolSize) {
-        this(poolSize, Thread.currentThread().getThreadGroup());
-    }
-
-    ThreadPoolTimerFactory(int poolSize, final ThreadGroup group) {
-        timerThreadPool = Executors.newScheduledThreadPool(poolSize, new ThreadFactory() {
-            
-            @Override
-            public Thread newThread(Runnable r) {
-                return new Thread(group, r);
-            }
-        });
-    }
-
-    private class ThreadPoolTimer implements Timer {
-
-        private Runnable action;
-
-        private long delay;
-
-        private long period;
-
-        private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
-
-        private SchedulingType schedulingType = SchedulingType.ONCE;
-
-        private ScheduledFuture<?> timerTask;
-
-        @Override
-        public void start() {
-            if (action != null) {
-                startScheduling();
-            }          
-        }
-
-        private void startScheduling() {
-            switch (schedulingType) {
-            case FIXED_RATE:
-                timerTask = timerThreadPool.scheduleAtFixedRate(action, delay, period, timeUnit);
-                break;
-            case FIXED_DELAY:
-                timerTask = timerThreadPool.scheduleWithFixedDelay(action, delay, period, timeUnit);
-                break;
-            case ONCE:
-            default:
-                timerTask = timerThreadPool.schedule(action, delay, timeUnit);
-            }
-        }
-
-        @Override
-        public void stop() {
-            if (timerTask != null) {
-                timerTask.cancel(false);
-            }
-        }
-
-        @Override
-        public void setAction(Runnable action) {
-            this.action = action;
-        }
-
-        @Override
-        public void setInitialDelay(long delay) {
-            this.delay = delay;
-        }
-
-        @Override
-        public void setDelay(long period) {
-            this.period = period;
-        }
-
-        @Override
-        public void setSchedulingType(SchedulingType schedulingType) {
-            if (schedulingType == null) {
-                throw new NullPointerException();
-            }
-            this.schedulingType = schedulingType;
-        }
-
-        @Override
-        public void setTimeUnit(TimeUnit timeUnit) {
-            this.timeUnit = timeUnit;
-        }
-        
-    }
-
-    private ScheduledExecutorService timerThreadPool;
-
-    @Override
-    public Timer createTimer() {
-        return new ThreadPoolTimer();
-    }
-
-    @Override
-    public void shutdown() {
-        timerThreadPool.shutdown();
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/Timer.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.util.concurrent.TimeUnit;
-
-public interface Timer {
-
-    enum SchedulingType {
-        ONCE, FIXED_RATE, FIXED_DELAY;
-    }
-
-    void start();
-    void stop();
-    void setAction(Runnable action);
-    void setInitialDelay(long initialDelay);
-    void setDelay(long period);
-    void setSchedulingType(SchedulingType schedulingType);
-    void setTimeUnit(TimeUnit timeUnit);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/TimerFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public interface TimerFactory {
-
-    Timer createTimer();
-
-    void shutdown();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/View.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-/**
- * An object that is meant to be used as a View in an MVC setup.
- *
- * All implementations of this interface must have a no-arg public constructor
- */
-public interface View {
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/ViewFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-public interface ViewFactory {
-
-    public <T extends View> T getView(Class<T> viewClass);
-
-    public <T extends View> Class<? extends T> getViewClass(Class<T> viewClass);
-
-    public <T extends View > void setViewClass(Class<T> viewClass, Class<? extends T> implClass);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.appctx;
-
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.ViewFactory;
-import com.redhat.thermostat.common.dao.DAOFactory;
-
-public class ApplicationContext {
-
-    private static ApplicationContext instance = new ApplicationContext();
-
-    private DAOFactory daoFactory;
-
-    private TimerFactory timerFactory;
-
-    private ViewFactory viewFactory;
-
-    public static ApplicationContext getInstance() {
-        return instance;
-    }
-
-    static void reset() {
-        instance = new ApplicationContext();
-    }
-
-    private ApplicationContext() {
-        // Nothing to do here, just prevent instantiation of this class outside
-        // the factory method.
-    }
-
-    public void setDAOFactory(DAOFactory daoFactory) {
-        this.daoFactory = daoFactory;
-    }
-
-    public DAOFactory getDAOFactory() {
-        return daoFactory;
-    }
-
-    public void setTimerFactory(TimerFactory timerFactory) {
-        this.timerFactory = timerFactory;
-    }
-
-    public TimerFactory getTimerFactory() {
-        return timerFactory;
-    }
-
-    public ViewFactory getViewFactory() {
-        return viewFactory;
-    }
-
-    public void setViewFactory(ViewFactory viewFactory) {
-        this.viewFactory = viewFactory;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContextUtil.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.appctx;
-
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-
-public class ApplicationContextUtil {
-
-    /**
-     * This is here to allow tests to reset the ApplicationContext, while
-     * preventing real code the same (ApplicationContext.reset() is package private).
-     *
-     * It is vital that tests call this from their setUp() and tearDown() methods,
-     * to avoid leaking mocks and stuff from test to test.
-     */
-    public static void resetApplicationContext() {
-        ApplicationContext.reset();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/AppContextSetup.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-public interface AppContextSetup {
-
-    void setupAppContext(String dbUrl);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/AppContextSetupImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.MongoDAOFactory;
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.MongoStorageProvider;
-import com.redhat.thermostat.common.storage.StorageProvider;
-
-class AppContextSetupImpl implements AppContextSetup {
-
-    @Override
-    public void setupAppContext(String dbUrl) {
-        StartupConfiguration config = new ConnectionConfiguration(dbUrl);
-        
-        StorageProvider connProv = new MongoStorageProvider(config);
-        DAOFactory daoFactory = new MongoDAOFactory(connProv);
-        Connection connection = daoFactory.getConnection();
-        connection.connect();
-        ApplicationContext.getInstance().setDAOFactory(daoFactory);
-
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/ArgumentSpec.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-public interface ArgumentSpec {
-
-    /**
-     * Return the name of the argument. This is used as the long option,
-     * e.g. a name of 'dbUrl' results in an option --dbUrl.
-     */
-    String getName();
-
-    /**
-     * Returns the short option version of the argument, e.g. 'd' results
-     * in an option -d.
-     */
-    String getShortOption();
-
-    boolean isRequired();
-
-    boolean isUsingAdditionalArgument();
-
-    String getDescription();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/Arguments.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.List;
-
-public interface Arguments {
-    List<String> getNonOptionArguments();
-    boolean hasArgument(String name);
-    String getArgument(String name);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/BaseCommandRegistry.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.osgi.framework.ServiceRegistration;
-
-
-public abstract class BaseCommandRegistry implements CommandRegistry {
-
-    @Override
-    public Collection<ServiceRegistration> registerCommands(Iterable<? extends Command> cmds) {
-        Collection<ServiceRegistration> regs = new ArrayList<>();
-        for (Command cmd : cmds) {
-            regs.add(registerCommand(cmd));
-        }
-        return regs;
-    }
-
-    protected abstract ServiceRegistration registerCommand(Command cmd);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/Command.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Collection;
-
-/**
- * Represents a command on the command line.
- * <p>
- * To register a custom command, have a class implement this interface and
- * register it as an OSGi service with the {@link #NAME} set to the value of
- * {@link #getName()}.
- */
-public interface Command {
-
-    static final String NAME = "COMMAND_NAME";
-
-    /**
-     * Execute the command
-     */
-    void run(CommandContext ctx) throws CommandException;
-
-    /**
-     * Called when the command is being removed from the system. The command
-     * should cancel any long-term action it has taken, such as any background
-     * tasks or threads it has spawned.
-     */
-    void disable();
-
-    /**
-     * Returns a name for this command. This will be used by the user to select
-     * this command.
-     */
-    String getName();
-
-    /**
-     * A short description for the command indicating what it does.
-     */
-    String getDescription();
-
-    /**
-     * How the user should invoke this command
-     */
-    String getUsage();
-
-    /**
-     * Returns a collection of arguments that the command is prepared to handle.
-     * If the user provides unknown or malformed arguments, this command will
-     * not be invoked.
-     */
-    Collection<ArgumentSpec> getAcceptedArguments();
-
-    boolean isStorageRequired();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandContext.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-
-public interface CommandContext {
-
-    Console getConsole();
-
-    Arguments getArguments();
-
-    CommandRegistry getCommandRegistry();
-
-    AppContextSetup getAppContextSetup();
-
-    CommandContextFactory getCommandContextFactory();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandContextFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import org.osgi.framework.BundleContext;
-
-public class CommandContextFactory {
-
-    private CommandRegistry commandRegistry;
-    private Console console = new SystemConsole();
-
-    private BundleContext bundleContext;
-
-    public CommandContextFactory(BundleContext ctx) {
-        commandRegistry = new CommandRegistryImpl(ctx);
-        bundleContext = ctx;
-    }
-
-    public CommandContext createContext(Arguments args) {
-        return new CommandContextImpl(args, this);
-    }
-
-    protected AppContextSetup getAppContextSetup() {
-        return new AppContextSetupImpl();
-    }
-
-    public CommandRegistry getCommandRegistry() {
-        return commandRegistry;
-    }
-
-    public Console getConsole() {
-        return console ;
-    }
-
-    public BundleContext getBundleContext() {
-        return bundleContext;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandContextImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-public class CommandContextImpl implements CommandContext {
-
-    private Arguments arguments;
-    private CommandContextFactory commandContextFactory;
-
-    public CommandContextImpl(Arguments args, CommandContextFactory ctxFactory) {
-        arguments = args;
-        commandContextFactory = ctxFactory;
-    }
-
-    @Override
-    public Console getConsole() {
-        return commandContextFactory.getConsole();
-    }
-
-    @Override
-    public Arguments getArguments() {
-        return arguments;
-    }
-
-    @Override
-    public CommandRegistry getCommandRegistry() {
-        return commandContextFactory.getCommandRegistry();
-    }
-
-    @Override
-    public AppContextSetup getAppContextSetup() {
-        return commandContextFactory.getAppContextSetup();
-    }
-
-    @Override
-    public CommandContextFactory getCommandContextFactory() {
-        return commandContextFactory;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-public class CommandException extends Exception {
-
-    private static final long serialVersionUID = 3730368617641245016L;
-
-    public CommandException() {
-        super();
-    }
-
-    public CommandException(String message) {
-        super(message);
-    }
-
-    public CommandException(Throwable cause) {
-        super(cause);
-    }
-
-    public CommandException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-public class CommandLineArgumentParseException extends CommandException {
-
-    public CommandLineArgumentParseException() {
-        super();
-    }
-
-    public CommandLineArgumentParseException(String message) {
-        super(message);
-    }
-
-    public CommandLineArgumentParseException(Throwable cause) {
-        super(cause);
-    }
-
-    public CommandLineArgumentParseException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArguments.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-
-class CommandLineArguments implements Arguments {
-
-    private CommandLine cmdLine;
-
-    public CommandLineArguments(CommandLine commandLine) {
-        cmdLine = commandLine;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<String> getNonOptionArguments() {
-        return cmdLine.getArgList();
-    }
-
-    @Override
-    public boolean hasArgument(String name) {
-        return cmdLine.hasOption(name);
-    }
-
-    @Override
-    public String getArgument(String name) {
-        return cmdLine.getOptionValue(name);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParser.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.io.PrintWriter;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.MissingOptionException;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-
-public class CommandLineArgumentsParser {
-
-    private List<ArgumentSpec> arguments = new LinkedList<>();
-
-    void addArguments(Collection<ArgumentSpec> args) {
-        arguments.addAll(args);
-    }
-
-    Arguments parse(String[] args) throws CommandLineArgumentParseException {
-        try {
-            Options options = convertToCommonsCLIOptions(arguments);
-            CommandLineParser parser = new GnuParser();
-            CommandLine commandLine;
-            commandLine = parser.parse(options, args);
-            return new CommandLineArguments(commandLine);
-        } catch (MissingOptionException mae) {
-            String msg = createMissingOptionsMessage(mae);
-            throw new CommandLineArgumentParseException(msg.toString(), mae);
-        } catch (ParseException e) {
-            throw new CommandLineArgumentParseException(e.getMessage(), e);
-        }
-    }
-
-    private String createMissingOptionsMessage(MissingOptionException mae) {
-        @SuppressWarnings("unchecked")
-        List<String> missingOptions = mae.getMissingOptions();
-        StringBuilder msg = new StringBuilder();
-        if (missingOptions.size() == 1) {
-            msg.append("Missing required option: ");
-        } else {
-            msg.append("Missing required options: ");
-        }
-        for (Iterator<String> i = missingOptions.iterator(); i.hasNext();) {
-            String missingOption = i.next();
-            if (missingOption.length() > 1) {
-                msg.append("--");
-            } else {
-                msg.append("-");
-            }
-            msg.append(missingOption);
-            if (i.hasNext()) {
-                msg.append(", ");
-            }
-        }
-        return msg.toString();
-    }
-
-    private Options convertToCommonsCLIOptions(Collection<ArgumentSpec> args) {
-        Options options = new Options();
-        for (ArgumentSpec spec : args) {
-            options.addOption(convertSpecToOption(spec));
-        }
-        return options;
-    }
-
-    private Option convertSpecToOption(ArgumentSpec spec) {
-        String shortOpt = spec.getShortOption();
-        String longOpt = spec.getName();
-        Option option = new Option(shortOpt, longOpt, spec.isUsingAdditionalArgument(), spec.getDescription());
-        option.setRequired(spec.isRequired());
-        return option;
-    }
-
-    void printHelp(CommandContext ctx, Command cmd) {
-        HelpFormatter helpFormatter = new HelpFormatter();
-        PrintWriter pw = new PrintWriter(ctx.getConsole().getOutput());
-        CommonCommandOptions commonOpts = new CommonCommandOptions();
-        Collection<ArgumentSpec> acceptedOptions = commonOpts.getAcceptedOptionsFor(cmd);
-        Options options = convertToCommonsCLIOptions(acceptedOptions);
-        helpFormatter.printHelp(pw, 80, cmd.getName(), cmd.getUsage(), options, 2, 4, null, true);
-        pw.flush();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandRegistry.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Collection;
-
-import org.osgi.framework.ServiceRegistration;
-
-public interface CommandRegistry {
-
-    public abstract Collection<ServiceRegistration> registerCommands(Iterable<? extends Command> cmds);
-
-    public abstract void unregisterCommands();
-
-    public abstract Command getCommand(String name);
-
-    public abstract Collection<Command> getRegisteredCommands();
-
-}
\ No newline at end of file
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.logging.Logger;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-public class CommandRegistryImpl extends BaseCommandRegistry {
-
-    private static final Logger log = Logger.getLogger(CommandRegistryImpl.class.getName());
-
-    private BundleContext context;
-
-    private List<ServiceRegistration> ourRegistrations = new ArrayList<ServiceRegistration>();
-
-    public CommandRegistryImpl(BundleContext ctx) {
-        context = ctx;
-    }
-
-    protected ServiceRegistration registerCommand(Command cmd) {
-        Hashtable<String, String> props = new Hashtable<>();
-        props.put(Command.NAME, cmd.getName());
-        ServiceRegistration registration = context.registerService(Command.class.getName(), cmd, props);
-        ourRegistrations.add(registration);
-        return registration;
-    }
-
-    @Override
-    public void unregisterCommands() {
-        Iterator<ServiceRegistration> iter = ourRegistrations.iterator();
-        while (iter.hasNext()) {
-            ServiceRegistration registration = iter.next();
-            Object serviceObject =  context.getService(registration.getReference());
-            Command cmd = (Command) serviceObject;
-            cmd.disable();
-            registration.unregister();
-            iter.remove();
-        }
-    }
-
-    @Override
-    public Command getCommand(String name) {
-        ServiceReference[] refs = getCommandServiceRefs("(&(objectclass=*)(" + Command.NAME + "=" + name + "))");
-        if (refs == null || refs.length == 0) {
-            return null;
-        } else if (refs.length > 1) {
-            log.warning("More than one command implementation found for: " + name);
-        }
-        ServiceReference ref = refs[0];
-        return (Command) context.getService(ref);
-    }
-
-    @Override
-    public Collection<Command> getRegisteredCommands() {
-        ServiceReference[] refs = getCommandServiceRefs(null);
-        List<Command> cmds = new ArrayList<>();
-        for (ServiceReference ref : refs) {
-            Command cmd = (Command) context.getService(ref);
-            cmds.add(cmd);
-        }
-        return cmds;
-    }
-
-    private ServiceReference[] getCommandServiceRefs(String filter) {
-        ServiceReference[] refs;
-        try {
-            refs = context.getServiceReferences(Command.class.getName(), filter);
-        } catch (InvalidSyntaxException e) {
-            throw (InternalError) new InternalError().initCause(e);
-        }
-        return refs;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/CommonCommandOptions.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-class CommonCommandOptions {
-
-    static final String DB_URL_ARG = "dbUrl";
-    private static final String DB_URL_DESC = "the URL of the storage to connect to";
-
-    static final String LOG_LEVEL_ARG = "logLevel";
-    private static final String LOG_LEVEL_DESC = "log level";
-
-    Collection<ArgumentSpec> getAcceptedOptionsFor(Command cmd) {
-
-        Collection<ArgumentSpec> acceptedArguments = cmd.getAcceptedArguments();
-        acceptedArguments = new ArrayList<>(acceptedArguments);
-        addDbUrlOptionForStorageCommand(cmd, acceptedArguments);
-        addLogLevelOption(acceptedArguments);
-        return acceptedArguments;
-    }
-
-    private void addDbUrlOptionForStorageCommand(Command cmd, Collection<ArgumentSpec> acceptedArguments) {
-        if (cmd.isStorageRequired()) {
-            acceptedArguments.add(new SimpleArgumentSpec(DB_URL_ARG, "d", DB_URL_DESC, false, true));
-        }
-    }
-
-    private void addLogLevelOption(Collection<ArgumentSpec> acceptedArguments) {
-        acceptedArguments.add(new SimpleArgumentSpec(LOG_LEVEL_ARG, LOG_LEVEL_DESC, false, true));
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/ConnectionConfiguration.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-class ConnectionConfiguration implements StartupConfiguration {
-
-    private String dbUrl;
-
-    ConnectionConfiguration(String dbUrl) {
-        this.dbUrl = dbUrl;
-    }
-
-    @Override
-    public String getDBConnectionString() {
-        return dbUrl;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/Console.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-
-public interface Console {
-
-    PrintStream getOutput();
-
-    PrintStream getError();
-
-    InputStream getInput();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-public class HelpCommand implements Command {
-
-    private static final int COMMANDS_COLUMNS_WIDTH = 15;
-    private static final String NAME = "help";
-    private static final String DESCRIPTION = "show help for a given command or help overview";
-    private static final String USAGE = DESCRIPTION;
-
-    @Override
-    public void run(CommandContext ctx) {
-        Arguments args = ctx.getArguments();
-        List<String> nonParsed = args.getNonOptionArguments();
-        if (nonParsed.isEmpty()) {
-            printCommandSummaries(ctx);
-        } else {
-            printCommandUsage(ctx, nonParsed.get(0));
-        }
-    }
-
-    private void printCommandSummaries(CommandContext ctx) {
-        CommandRegistry cmdRegistry = ctx.getCommandRegistry();
-
-        StringBuilder out = new StringBuilder();
-        out.append("list of commands:\n\n");
-
-        Collection<Command> commands = cmdRegistry.getRegisteredCommands();
-        for (Command cmd : commands) {
-            printCommandSummary(out, cmd);
-        }
-        ctx.getConsole().getOutput().print(out);
-    }
-
-    private void printCommandSummary(StringBuilder out, Command cmd) {
-        out.append(" ");
-        out.append(cmd.getName());
-        for (int i = 0; i < COMMANDS_COLUMNS_WIDTH - cmd.getName().length() - 1; i++) {
-            out.append(" ");
-        }
-        out.append(cmd.getDescription());
-        out.append("\n");
-    }
-
-    private void printCommandUsage(CommandContext ctx, String cmdName) {
-        Command cmd = ctx.getCommandRegistry().getCommand(cmdName);
-        if (cmd != null) {
-            CommandLineArgumentsParser cliParser = new CommandLineArgumentsParser();
-            cliParser.printHelp(ctx, cmd);
-        } else {
-            printCommandSummaries(ctx);
-        }
-    }
-
-    @Override
-    public void disable() { /* NO-OP */ }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public String getDescription() {
-        return DESCRIPTION;
-    }
-
-    @Override
-    public String getUsage() {
-        return USAGE;
-    }
-
-    @Override
-    public Collection<ArgumentSpec> getAcceptedArguments() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean isStorageRequired() {
-        return false;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/Launcher.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-/**
- * Launcher is the main entry point for the command line "thermostat" program.
- */
-public interface Launcher {
-
-    /**
-     * Invoked when thermostat starts
-     * @param command line arguments to the program
-     */
-    void run(String[] args);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/LauncherImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.logging.Level;
-
-import org.osgi.framework.BundleException;
-
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.config.ClientPreferences;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-import com.redhat.thermostat.common.storage.ConnectionException;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class LauncherImpl implements Launcher {
-
-    private static final String UNKNOWN_COMMAND_MESSAGE = "unknown command '%s'\n";
-
-    private ClientPreferences prefs = new ClientPreferences();
-
-    private String[] args;
-
-    private CommandContextFactory cmdCtxFactory;
-
-    private int usageCount = 0;
-
-    public LauncherImpl(CommandContextFactory cmdCtxFactory) {
-        this.cmdCtxFactory = cmdCtxFactory;
-    }
-
-    public void run(String[] args) {
-        usageCount++;
-        try {
-            initLogging();
-            this.args = args;
-            if (hasNoArguments()) {
-                runHelpCommand();
-            } else if (unknownCommand()) {
-                cmdCtxFactory.getConsole().getOutput().print(String.format(UNKNOWN_COMMAND_MESSAGE, args[0]));
-                runHelpCommand();
-            } else {
-                runCommandFromArguments();
-            }
-        } finally {
-            usageCount--;
-            shutdownIfLastLaunch();
-        }
-    }
-
-    private void shutdownIfLastLaunch() throws InternalError {
-        if (usageCount == 0) {
-            try {
-                ApplicationContext.getInstance().getTimerFactory().shutdown();
-                cmdCtxFactory.getBundleContext().getBundle(0).stop();
-            } catch (BundleException e) {
-                throw (InternalError) new InternalError().initCause(e);
-            }
-        }
-    }
-
-    void setPreferences(ClientPreferences prefs) {
-        this.prefs = prefs;
-    }
-
-    private void initLogging() {
-        try {
-            LoggingUtils.loadGlobalLoggingConfig();
-        } catch (InvalidConfigurationException e) {
-            System.err.println("WARNING: Could not read global Thermostat logging configuration.");
-        }
-        try {
-            LoggingUtils.loadUserLoggingConfig();
-        } catch (InvalidConfigurationException e) {
-            // We intentionally ignore this.
-        }
-    }
-
-    private boolean hasNoArguments() {
-        return args.length == 0;
-    }
-
-    private boolean unknownCommand() {
-        CommandRegistry registry = cmdCtxFactory.getCommandRegistry();
-        Command cmd = registry.getCommand(args[0]);
-        return cmd == null;
-    }
-
-    private void runHelpCommand() {
-        runCommand("help", new String[0]);
-    }
-
-    private void runCommandFromArguments() {
-        runCommand(args[0], Arrays.copyOfRange(args, 1, args.length));
-    }
-
-    private void runCommand(String cmdName, String[] cmdArgs) {
-        try {
-            parseArgsAndRunCommand(cmdName, cmdArgs);
-        } catch (CommandException e) {
-            cmdCtxFactory.getConsole().getError().println(e.getMessage());
-        }
-    }
-
-    private void parseArgsAndRunCommand(String cmdName, String[] cmdArgs) throws CommandException {
-
-        Command cmd = getCommand(cmdName);
-        if (cmd == null) {
-            throw new CommandException("Unknown command: " + cmdName);
-        }
-        CommonCommandOptions commonOpts = new CommonCommandOptions();
-        Collection<ArgumentSpec> acceptedOptions = commonOpts.getAcceptedOptionsFor(cmd);
-        Arguments args = parseCommandArguments(cmdArgs, acceptedOptions);
-        setupLogLevel(args);
-        CommandContext ctx = setupCommandContext(cmd, args);
-        cmd.run(ctx);
-    }
-
-    private void setupLogLevel(Arguments args) {
-        if (args.hasArgument(CommonCommandOptions.LOG_LEVEL_ARG)) {
-            String levelOption = args.getArgument(CommonCommandOptions.LOG_LEVEL_ARG);
-            setLogLevel(levelOption);
-        }
-    }
-
-    private void setLogLevel(String levelOption) {
-        try {
-            Level level = Level.parse(levelOption);
-            LoggingUtils.setGlobalLogLevel(level);
-        } catch (IllegalArgumentException ex) {
-            // Ignore this, use default loglevel.
-        }
-    }
-
-    private Command getCommand(String cmdName) {
-
-        CommandRegistry registry = cmdCtxFactory.getCommandRegistry();
-        Command cmd = registry.getCommand(cmdName);
-        return cmd;
-    }
-
-    private Arguments parseCommandArguments(String[] cmdArgs, Collection<ArgumentSpec> acceptedArguments)
-            throws CommandLineArgumentParseException {
-
-        CommandLineArgumentsParser cliArgsParser = new CommandLineArgumentsParser();
-        cliArgsParser.addArguments(acceptedArguments);
-        Arguments args = cliArgsParser.parse(cmdArgs);
-        return args;
-    }
-
-    private CommandContext setupCommandContext(Command cmd, Arguments args) throws CommandException {
-
-        CommandContext ctx = cmdCtxFactory.createContext(args);
-        if (cmd.isStorageRequired()) {
-            String dbUrl = ctx.getArguments().getArgument(CommonCommandOptions.DB_URL_ARG);
-            if (dbUrl == null) {
-                dbUrl = prefs.getConnectionUrl();
-            }
-            try {
-                ctx.getAppContextSetup().setupAppContext(dbUrl);
-            } catch (ConnectionException ex) {
-                throw new CommandException("Could not connect to: " + dbUrl, ex);
-            }
-        }
-        return ctx;
-    }
-
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/SimpleArgumentSpec.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Objects;
-
-public class SimpleArgumentSpec implements ArgumentSpec {
-
-    private String name;
-    private String description;
-    private boolean required;
-    private boolean usingAddionalArgument;
-    private String shortOption;
-
-    public SimpleArgumentSpec() {
-        this(null, null);
-    }
-
-    public SimpleArgumentSpec(String name, String description) {
-        this(name, description, false, false);
-    }
-
-    public SimpleArgumentSpec(String name, String description, boolean required, boolean usingAdditionalArgument) {
-        this(name, null, description, required, usingAdditionalArgument);
-    }
-
-    public SimpleArgumentSpec(String name, String shortOption, String description, boolean required, boolean usingAdditionalArgument) {
-        this.name = name;
-        this.shortOption = shortOption;
-        this.description = description;
-        this.required = required;
-        this.usingAddionalArgument = usingAdditionalArgument;
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    void setName(String name) {
-        this.name = name;
-    }
-
-    @Override
-    public String getShortOption() {
-        return shortOption;
-    }
-
-    void setShortOption(String shortOption) {
-        this.shortOption = shortOption;
-    }
-
-    @Override
-    public boolean isRequired() {
-        return required;
-    }
-
-    public void setRequired(boolean required) {
-        this.required = required;
-    }
-
-    @Override
-    public boolean isUsingAdditionalArgument() {
-        return usingAddionalArgument;
-    }
-
-    public void setUsingAdditionalArgument(boolean usingAddionalArgument) {
-        this.usingAddionalArgument = usingAddionalArgument;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public boolean equals(Object o) {
-        if (! (o instanceof SimpleArgumentSpec)) {
-            return false;
-        }
-        SimpleArgumentSpec other = (SimpleArgumentSpec) o;
-        return Objects.equals(name, other.name)
-                && Objects.equals(description, other.description)
-                && usingAddionalArgument == other.usingAddionalArgument
-                && required == other.required
-                && Objects.equals(shortOption, other.shortOption);
-    }
-
-    public int hashCode() {
-        return Objects.hash(name, description, shortOption, usingAddionalArgument, required);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/SimpleArguments.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class SimpleArguments implements Arguments {
-
-    private Map<String,String> arguments = new HashMap<>();
-
-    @Override
-    public boolean hasArgument(String name) {
-        return arguments.containsKey(name);
-    }
-
-    @Override
-    public String getArgument(String name) {
-        return arguments.get(name);
-    }
-
-    public void addArgument(String name, String value) {
-        arguments.put(name, value);
-        
-    }
-
-    @Override
-    public List<String> getNonOptionArguments() {
-        return null;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/cli/SystemConsole.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-
-class SystemConsole implements Console {
-
-    @Override
-    public PrintStream getOutput() {
-        return System.out;
-    }
-
-    @Override
-    public PrintStream getError() {
-        return System.err;
-    }
-
-    @Override
-    public InputStream getInput() {
-        return System.in;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/ClientPreferences.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-
-public class ClientPreferences {
-
-    private static final String CONNECTION_URL = "connection-url";
-
-    private final Preferences prefs;
-
-    public ClientPreferences() {
-        this(Preferences.userRoot().node("thermostat"));
-    }
-
-    ClientPreferences(Preferences prefs) {
-        this.prefs = prefs;
-    }
-
-    public String getConnectionUrl() {
-        return prefs.get(CONNECTION_URL, "mongodb://127.0.0.1:27518");
-    }
-
-    public void setConnectionUrl(String url) {
-        prefs.put(CONNECTION_URL, url);
-    }
-
-    public void flush() throws BackingStoreException {
-        prefs.flush();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/ConfigUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-import java.io.File;
-
-public class ConfigUtils {
-
-    private static final String THERMOSTAT_USER_DIR = ".thermostat";
-
-    public static String getThermostatHome() throws InvalidConfigurationException {
-        // allow this to be specified also as a property, especially for
-        // tests, this overrides the env setting
-        String home = System.getProperty("THERMOSTAT_HOME");
-        if (home == null) {
-            home = System.getenv("THERMOSTAT_HOME");
-        }
-        
-        if (home == null) {
-            throw new InvalidConfigurationException("THERMOSTAT_HOME not defined...");
-        }
-        return home;
-    }
-
-    public static String getThermostatUserHome() {
-        String home = System.getProperty("user.home");
-        return home + File.separator + THERMOSTAT_USER_DIR;
-    }
-
-    public static File getBackendsBaseDirectory() throws InvalidConfigurationException {
-        String loc = getThermostatHome() + File.separatorChar + "backends";
-        File file = new File(loc);
-        return file;
-    }
-    
-    public static File getStorageBaseDirectory() throws InvalidConfigurationException {
-        String loc = getThermostatHome() + File.separatorChar + "storage";
-        File file = new File(loc);
-        return file;
-    }
-    
-    public static File getStorageDirectory() throws InvalidConfigurationException {
-        return new File(getStorageBaseDirectory(), "db");
-    }
-    
-    public static File getStorageConfigurationFile() throws InvalidConfigurationException {
-        return new File(getStorageBaseDirectory(), "db.properties");
-    }
-
-    public static File getStorageLogFile() throws InvalidConfigurationException {
-        File logDir = new File(getStorageBaseDirectory(), "logs");
-        File logFile = new File(logDir, "db.log");
-        
-        return logFile;
-    }
-
-    public static File getStoragePidFile() throws InvalidConfigurationException {
-        File logDir = new File(getStorageBaseDirectory(), "run");
-        File logFile = new File(logDir, "db.pid");
-        
-        return logFile;
-    }
-
-    public static File getBackendPropertyFile(String backendName)
-            throws InvalidConfigurationException
-    {
-        File backendsConfigDir = ConfigUtils.getBackendsBaseDirectory();
-        File backendConfig = new File(backendsConfigDir, backendName);
-        backendConfig = new File(backendConfig, "backend.properties");
-        return backendConfig;
-    }
-
-    public static File getAgentConfigurationFile() throws InvalidConfigurationException {
-
-        File agent = new File(getThermostatHome(), "agent");
-        return new File(agent, "agent.properties");
-    }
-
-    public static File getClientConfigurationDirectory() throws InvalidConfigurationException {
-        File client = new File(getThermostatHome(), "client");
-        return client;
-    }
-
-    public static File getHistoryFile() throws InvalidConfigurationException {
-        File history = new File(getClientConfigurationDirectory(), "cli-history");
-        return history;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/Defaults.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-import java.util.logging.Level;
-
-final class Defaults {
-
-	private Defaults() {
-	    /* Should not be instantiated */
-	}
-
-    public static final Level LOGGING_LEVEL = Level.WARNING;
-    public static final String DATABASE_URI = "mongodb://127.0.0.1";
-    public static final int MONGOS_PORT = 27517;
-    public static final int MONGOD_PORT = 27518;
-    public static final boolean LOCAL_MODE = false; // Default behaviour is to connect to cluster.
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-
-public class InvalidConfigurationException extends Exception {
-
-    private static final long serialVersionUID = -6555406006758264587L;
-
-    public InvalidConfigurationException() {
-        super();
-    }
-    
-    public InvalidConfigurationException(String message) {
-        super(message);
-    }
-    
-    public InvalidConfigurationException(String message, Throwable cause) {
-        super(message, cause);
-    }
-    
-    public InvalidConfigurationException(Throwable cause) {
-        super(cause);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/StartupConfiguration.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-public interface StartupConfiguration {
-
-    String getDBConnectionString();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/config/ThermostatOptionParser.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-public interface ThermostatOptionParser {
-    void parse() throws InvalidConfigurationException;
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/Converter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.Pojo;
-import com.redhat.thermostat.common.storage.Chunk;
-
-interface Converter<T extends Pojo> {
-
-    Chunk toChunk(T pojo);
-
-    T fromChunk(Chunk chunk);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/Countable.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-interface Countable {
-
-    public long getCount();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class CpuStatConverter implements Converter<CpuStat> {
-
-    @Override
-    public Chunk toChunk(CpuStat cpuStat) {
-        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, cpuStat.getTimeStamp());
-        chunk.put(CpuStatDAO.cpu5LoadKey, cpuStat.getLoad5());
-        chunk.put(CpuStatDAO.cpu10LoadKey, cpuStat.getLoad10());
-        chunk.put(CpuStatDAO.cpu15LoadKey, cpuStat.getLoad15());
-        return chunk;
-    }
-
-    @Override
-    public CpuStat fromChunk(Chunk chunk) {
-        long timestamp = chunk.get(Key.TIMESTAMP);
-        double load5 = chunk.get(CpuStatDAO.cpu5LoadKey);
-        double load10 = chunk.get(CpuStatDAO.cpu10LoadKey);
-        double load15 = chunk.get(CpuStatDAO.cpu15LoadKey);
-        return new CpuStat(timestamp, load5, load10, load15);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface CpuStatDAO extends Countable {
-
-    static Key<Double> cpu5LoadKey = new Key<>("5load", false);
-    static Key<Double> cpu10LoadKey = new Key<>("10load", false);
-    static Key<Double> cpu15LoadKey = new Key<>("15load", false);
-
-    static final Category cpuStatCategory = new Category("cpu-stats",
-            Key.AGENT_ID, Key.TIMESTAMP, cpu5LoadKey, cpu10LoadKey, cpu15LoadKey);
-
-    List<CpuStat> getLatestCpuStats(HostRef ref);
-
-    void putCpuStat(CpuStat stat);
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Storage;
-
-class CpuStatDAOImpl implements CpuStatDAO {
-
-    private Storage storage;
-
-    private Converter<CpuStat> converter = new CpuStatConverter();;
-
-    private Map<HostRef, HostLatestPojoListGetter<CpuStat>> getters = new HashMap<>();
-
-    CpuStatDAOImpl(Storage storage) {
-        this.storage = storage;
-    }
-
-    @Override
-    public List<CpuStat> getLatestCpuStats(HostRef ref) {
-        HostLatestPojoListGetter<CpuStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new HostLatestPojoListGetter<CpuStat>(storage, cpuStatCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-
-    @Override
-    public void putCpuStat(CpuStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-
-    @Override
-    public long getCount() {
-        return storage.getCount(cpuStatCategory);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-public class DAOException extends RuntimeException {
-
-    public DAOException() {
-        super();
-    }
-
-    public DAOException(String message) {
-        super(message);
-    }
-
-    public DAOException(Throwable cause) {
-        super(cause);
-    }
-
-    public DAOException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.Storage;
-
-public interface DAOFactory {
-
-    // TODO this is temporary until DAO is made for those that are still using Storage directly.
-    public Storage getStorage();
-
-    public Connection getConnection();
-
-    public HostInfoDAO getHostInfoDAO();
-
-    public CpuStatDAO getCpuStatDAO();
-
-    public MemoryStatDAO getMemoryStatDAO();
-
-    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO();
-
-    public VmInfoDAO getVmInfoDAO();
-
-    public VmCpuStatDAO getVmCpuStatDAO();
-
-    public VmMemoryStatDAO getVmMemoryStatDAO();
-
-    public VmClassStatDAO getVmClassStatsDAO();
-
-    public VmGcStatDAO getVmGcStatDAO();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-
-public class HostInfoConverter implements Converter<HostInfo> {
-
-    @Override
-    public Chunk toChunk(HostInfo hostInfo) {
-        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        chunk.put(HostInfoDAO.hostNameKey, hostInfo.getHostname());
-        chunk.put(HostInfoDAO.osNameKey, hostInfo.getOsName());
-        chunk.put(HostInfoDAO.osKernelKey, hostInfo.getOsKernel());
-        chunk.put(HostInfoDAO.cpuModelKey, hostInfo.getCpuModel());
-        chunk.put(HostInfoDAO.cpuCountKey, hostInfo.getCpuCount());
-        chunk.put(HostInfoDAO.hostMemoryTotalKey, hostInfo.getTotalMemory());
-        return chunk;
-    }
-
-    @Override
-    public HostInfo fromChunk(Chunk chunk) {
-        String hostName = chunk.get(HostInfoDAO.hostNameKey);
-        String osName = chunk.get(HostInfoDAO.osNameKey);
-        String osKernel = chunk.get(HostInfoDAO.osKernelKey);
-        String cpuModel = chunk.get(HostInfoDAO.cpuModelKey);
-        int cpuCount = chunk.get(HostInfoDAO.cpuCountKey);
-        long totalMemory = chunk.get(HostInfoDAO.hostMemoryTotalKey);
-        return new HostInfo(hostName, osName, osKernel, cpuModel, cpuCount, totalMemory);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.Collection;
-
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface HostInfoDAO extends Countable {
-
-    static Key<String> hostNameKey = new Key<>("hostname", true);
-    static Key<String> osNameKey = new Key<>("os_name", false);
-    static Key<String> osKernelKey = new Key<>("os_kernel", false);
-    static Key<Integer> cpuCountKey = new Key<>("cpu_num", false);
-    static Key<String> cpuModelKey = new Key<>("cpu_model", false);
-    static Key<Long> hostMemoryTotalKey = new Key<>("memory_total", false);
-
-    static final Category hostInfoCategory = new Category("host-info",
-            Key.AGENT_ID, hostNameKey, osNameKey, osKernelKey,
-            cpuCountKey, cpuModelKey, hostMemoryTotalKey);
-
-    HostInfo getHostInfo(HostRef ref);
-
-    void putHostInfo(HostInfo info);
-
-    Collection<HostRef> getHosts();
-    Collection<HostRef> getAliveHosts();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.storage.AgentInformation;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class HostInfoDAOImpl implements HostInfoDAO {
-    private Storage storage;
-    private HostInfoConverter converter;
-
-    public HostInfoDAOImpl(Storage storage) {
-        this.storage = storage;
-        converter = new HostInfoConverter();
-    }
-
-    @Override
-    public HostInfo getHostInfo(HostRef ref) {
-        Chunk query = new Chunk(hostInfoCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgentId());
-        Chunk result = storage.find(query);
-        return result == null ? null : converter.fromChunk(result);
-    }
-
-    @Override
-    public void putHostInfo(HostInfo info) {
-        storage.putChunk(converter.toChunk(info));
-    }
-    
-    @Override
-    public Collection<HostRef> getHosts() {
-        return getHosts(new Chunk(hostInfoCategory, false));
-    }
-    
-    private Collection<HostRef> getHosts(Chunk filter) {
-        Collection<HostRef> hosts = new ArrayList<HostRef>();
-        
-        Cursor hostsCursor = storage.findAll(filter);
-        while(hostsCursor.hasNext()) {
-            Chunk hostChunk = hostsCursor.next();
-            String agentId = hostChunk.get(Key.AGENT_ID);
-            String hostName = hostChunk.get(hostNameKey);
-            hosts.add(new HostRef(agentId, hostName));
-        }
-        return hosts;
-    }
-    
-    @Override
-    public Collection<HostRef> getAliveHosts() {
-        
-        Collection<HostRef> hosts = new ArrayList<HostRef>();
-        
-        Chunk agents = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
-        agents.put(AgentInformation.AGENT_ALIVE_KEY, true);
-        Cursor agentCursor = storage.findAll(agents);
-        while(agentCursor.hasNext()) {
-            Chunk chunk = agentCursor.next();
-            
-            Chunk filter = new Chunk(hostInfoCategory, false);
-            filter.put(Key.AGENT_ID, chunk.get(Key.AGENT_ID));
-            
-            hosts.addAll(getHosts(filter));
-        }
-        
-        return hosts;
-    }
-    @Override
-    public long getCount() {
-        return storage.getCount(hostInfoCategory);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.TimeStampedPojo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class HostLatestPojoListGetter<T extends TimeStampedPojo> implements LatestPojoListGetter<T> {
-
-    private Storage storage;
-    private Category cat;
-    private Converter<T> converter;
-    private HostRef ref;
-
-    private Map<HostRef, Long> lastUpdateTimes = new HashMap<>();
-
-    HostLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, HostRef ref) {
-        this.storage = storage;
-        this.cat = cat;
-        this.converter = converter;
-        this.ref = ref;
-    }
-
-    @Override
-    public List<T> getLatest() {
-        Chunk query = buildQuery();
-        return getLatest(query);
-    }
-
-    private List<T> getLatest(Chunk query) {
-        // TODO if multiple threads will be using this utility class, there may be some issues
-        // with the updateTimes
-        Long lastUpdate = lastUpdateTimes.get(ref);
-        Cursor cursor = storage.findAll(query);
-        List<T> result = new ArrayList<>();
-        while (cursor.hasNext()) {
-            Chunk chunk = cursor.next();
-            T pojo = converter.fromChunk(chunk);
-            result.add(pojo);
-            lastUpdateTimes.put(ref, Math.max(pojo.getTimeStamp(), lastUpdate));
-        }
-        return result;
-    }
-
-    protected Chunk buildQuery() {
-        Chunk query = new Chunk(cat, false);
-        query.put(Key.AGENT_ID, ref.getAgentId());
-        Long lastUpdate = lastUpdateTimes.get(ref);
-        if (lastUpdate != null) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
-        } else {
-            lastUpdateTimes.put(ref, Long.MIN_VALUE);
-        }
-        return query;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostRef.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-public class HostRef implements Ref {
-
-    private final String uid;
-    private final String name;
-
-    public HostRef(String id, String name) {
-        this.uid = id;
-        this.name = name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    public String getAgentId() {
-        return uid;
-    }
-
-    public String getHostName() {
-        return name;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (obj == this) {
-            return true;
-        }
-        if (obj.getClass() != this.getClass()) {
-            return false;
-        }
-        HostRef other = (HostRef) obj;
-        if (equals(this.uid, other.uid) && equals(this.name, other.name)) {
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean equals(Object obj1, Object obj2) {
-        return (obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2));
-    }
-
-    @Override
-    public int hashCode() {
-        return uid.hashCode();
-    }
-
-    @Override
-    public String getStringID() {
-        return getAgentId();
-    }
-    
-    @Override
-    public String getName() {
-        return getHostName();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.Pojo;
-
-interface LatestPojoListGetter<T extends Pojo> {
-    List<T> getLatest();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class MemoryStatConverter implements Converter<MemoryStat> {
-
-    @Override
-    public Chunk toChunk(MemoryStat mem) {
-        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
-        chunk.put(Key.TIMESTAMP, mem.getTimeStamp());
-        chunk.put(MemoryStatDAO.memoryTotalKey, mem.getTotal());
-        chunk.put(MemoryStatDAO.memoryFreeKey, mem.getFree());
-        chunk.put(MemoryStatDAO.memoryBuffersKey, mem.getBuffers());
-        chunk.put(MemoryStatDAO.memoryCachedKey, mem.getCached());
-        chunk.put(MemoryStatDAO.memorySwapTotalKey, mem.getSwapTotal());
-        chunk.put(MemoryStatDAO.memorySwapFreeKey, mem.getSwapFree());
-        chunk.put(MemoryStatDAO.memoryCommitLimitKey, mem.getCommitLimit());
-        return chunk;
-    }
-
-    @Override
-    public MemoryStat fromChunk(Chunk chunk) {
-        long timestamp = chunk.get(Key.TIMESTAMP);
-        long total = chunk.get(MemoryStatDAO.memoryTotalKey);
-        long free = chunk.get(MemoryStatDAO.memoryFreeKey);
-        long buffers = chunk.get(MemoryStatDAO.memoryBuffersKey);
-        long cached = chunk.get(MemoryStatDAO.memoryCachedKey);
-        long swapTotal = chunk.get(MemoryStatDAO.memorySwapTotalKey);
-        long swapFree = chunk.get(MemoryStatDAO.memorySwapFreeKey);
-        long commitLimit = chunk.get(MemoryStatDAO.memoryCommitLimitKey);
-
-        return new MemoryStat(timestamp, total, free, buffers, cached, swapTotal, swapFree, commitLimit);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface MemoryStatDAO extends Countable {
-
-    static Key<Long> memoryTotalKey = new Key<>("total", false);
-    static Key<Long> memoryFreeKey = new Key<>("free", false);
-    static Key<Long> memoryBuffersKey = new Key<>("buffers", false);
-    static Key<Long> memoryCachedKey = new Key<>("cached", false);
-    static Key<Long> memorySwapTotalKey = new Key<>("swap-total", false);
-    static Key<Long> memorySwapFreeKey = new Key<>("swap-free", false);
-    static Key<Long> memoryCommitLimitKey = new Key<>("commit-limit", false);
-
-    static final Category memoryStatCategory = new Category("memory-stats",
-            Key.AGENT_ID, Key.TIMESTAMP, memoryTotalKey, memoryFreeKey, memoryBuffersKey,
-            memoryCachedKey, memorySwapTotalKey, memorySwapFreeKey, memoryCommitLimitKey);
-
-    public List<MemoryStat> getLatestMemoryStats(HostRef ref);
-
-    void putMemoryStat(MemoryStat stat);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Storage;
-
-class MemoryStatDAOImpl implements MemoryStatDAO {
-
-    private Storage storage;
-
-    private Converter<MemoryStat> converter = new MemoryStatConverter();
-
-    private Map<HostRef, HostLatestPojoListGetter<MemoryStat>> getters = new HashMap<>();
-
-    MemoryStatDAOImpl(Storage storage) {
-        this.storage = storage;
-    }
-
-    @Override
-    public List<MemoryStat> getLatestMemoryStats(HostRef ref) {
-        HostLatestPojoListGetter<MemoryStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new HostLatestPojoListGetter<MemoryStat>(storage, memoryStatCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-
-    @Override
-    public void putMemoryStat(MemoryStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-
-    @Override
-    public long getCount() {
-        return storage.getCount(memoryStatCategory);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.StorageProvider;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class MongoDAOFactory implements DAOFactory {
-
-    private final Storage storage;
-
-    public MongoDAOFactory(StorageProvider prov) {
-        storage = prov.createStorage();
-    }
-
-    @Override
-    public Connection getConnection() {
-        return storage.getConnection();
-    }
-
-    @Override
-    public HostInfoDAO getHostInfoDAO() {
-        ensureStorageConnected();
-        return new HostInfoDAOImpl(storage);
-    }
-
-    @Override
-    public CpuStatDAO getCpuStatDAO() {
-        ensureStorageConnected();
-        return new CpuStatDAOImpl(storage);
-    }
-
-    @Override
-    public MemoryStatDAO getMemoryStatDAO() {
-        ensureStorageConnected();
-        return new MemoryStatDAOImpl(storage);
-    }
-
-    @Override
-    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO() {
-        ensureStorageConnected();
-        return new NetworkInterfaceInfoDAOImpl(storage);
-    }
-
-    @Override
-    public VmInfoDAO getVmInfoDAO() {
-        ensureStorageConnected();
-        return new VmInfoDAOImpl(storage);
-    }
-
-    @Override
-    public VmCpuStatDAO getVmCpuStatDAO() {
-        ensureStorageConnected();
-        return new VmCpuStatDAOImpl(storage);
-    }
-
-    public VmMemoryStatDAO getVmMemoryStatDAO() {
-        ensureStorageConnected();
-        return new VmMemoryStatDAOImpl(storage);
-    }
-
-    @Override
-    public VmClassStatDAO getVmClassStatsDAO() {
-        ensureStorageConnected();
-        return new VmClassStatDAOImpl(storage);
-    }
-
-    @Override
-    public VmGcStatDAO getVmGcStatDAO() {
-        ensureStorageConnected();
-        return new VmGcStatDAOImpl(storage);
-    }
-
-    @Override
-    public Storage getStorage() {
-        return storage;
-    }
-
-    private void ensureStorageConnected() {
-        if (!storage.getConnection().isConnected()) {
-            throw new IllegalStateException("Set up connection before accessing DAO");
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-
-public class NetworkInterfaceInfoConverter implements Converter<NetworkInterfaceInfo> {
-
-    @Override
-    public Chunk toChunk(NetworkInterfaceInfo info) {
-        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, true);
-        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, info.getInterfaceName());
-        String ip4 = info.getIp4Addr();
-        if (ip4 != null) {
-            chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, ip4);
-        }
-        String ip6 = info.getIp6Addr();
-        if (ip6 != null) {
-            chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, ip6);
-        }
-        return chunk;
-    }
-
-    @Override
-    public NetworkInterfaceInfo fromChunk(Chunk chunk) {
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo(chunk.get(NetworkInterfaceInfoDAO.ifaceKey));
-        info.setIp4Addr(chunk.get(NetworkInterfaceInfoDAO.ip4AddrKey));
-        info.setIp6Addr(chunk.get(NetworkInterfaceInfoDAO.ip6AddrKey));
-        return info;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface NetworkInterfaceInfoDAO {
-
-    static Key<String> ifaceKey = new Key<>("iface", true);
-    static Key<String> ip4AddrKey = new Key<>("ipv4addr", false);
-    static Key<String> ip6AddrKey = new Key<>("ipv6addr", false);
-
-    static final Category networkInfoCategory = new Category("network-info",
-            Key.AGENT_ID, Key.TIMESTAMP, ifaceKey, ip4AddrKey, ip6AddrKey);
-
-    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref);
-
-    public void putNetworkInterfaceInfo(NetworkInterfaceInfo info);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO {
-
-    private Storage storage;
-    private NetworkInterfaceInfoConverter converter;
-
-    NetworkInterfaceInfoDAOImpl(Storage storage) {
-        this.storage = storage;
-        converter = new NetworkInterfaceInfoConverter();
-    }
-
-    @Override
-    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref) {
-        Chunk query = new Chunk(networkInfoCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgentId());
-
-        Cursor cursor = storage.findAll(query);
-        List<NetworkInterfaceInfo> result = new ArrayList<>();
-        while (cursor.hasNext()) {
-            Chunk chunk = cursor.next();
-            NetworkInterfaceInfo stat = converter.fromChunk(chunk);
-            result.add(stat);
-        }
-        return result;
-    }
-
-    @Override
-    public void putNetworkInterfaceInfo(NetworkInterfaceInfo info) {
-        storage.putChunk(converter.toChunk(info));
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/Ref.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-public interface Ref {
-
-    String getStringID();
-    String getName();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmClassStatConverter implements Converter<VmClassStat> {
-
-    @Override
-    public Chunk toChunk(VmClassStat vmClassStat) {
-        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        chunk.put(Key.VM_ID, vmClassStat.getVmId());
-        chunk.put(Key.TIMESTAMP, vmClassStat.getTimeStamp());
-        chunk.put(VmClassStatDAO.loadedClassesKey, vmClassStat.getLoadedClasses());
-        return chunk;
-    }
-
-    @Override
-    public VmClassStat fromChunk(Chunk chunk) {
-        long timestamp = chunk.get(Key.TIMESTAMP);
-        long loadedClasses = chunk.get(VmClassStatDAO.loadedClassesKey);
-        int vmId = chunk.get(Key.VM_ID);
-        return new VmClassStat(vmId, timestamp, loadedClasses);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface VmClassStatDAO {
-
-    static final Key<Long> loadedClassesKey = new Key<>("loadedClasses", false);
-
-    static final Category vmClassStatsCategory = new Category(
-            "vm-class-stats", Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, loadedClassesKey);
-
-    public List<VmClassStat> getLatestClassStats(VmRef ref);
-
-    public void putVmClassStat(VmClassStat stat);
-
-}
\ No newline at end of file
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmClassStatDAOImpl implements VmClassStatDAO {
-
-    private Storage storage;
-
-    private Converter<VmClassStat> converter = new VmClassStatConverter();
-
-    private Map<VmRef, VmLatestPojoListGetter<VmClassStat>> getters = new HashMap<>();
-
-    VmClassStatDAOImpl(Storage storage) {
-        this.storage = storage;
-    }
-
-    @Override
-    public List<VmClassStat> getLatestClassStats(VmRef ref) {
-        VmLatestPojoListGetter<VmClassStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new VmLatestPojoListGetter<VmClassStat>(storage, vmClassStatsCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-
-    @Override
-    public void putVmClassStat(VmClassStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmCpuStatConverter implements Converter<VmCpuStat> {
-
-    @Override
-    public Chunk toChunk(VmCpuStat vmCpuStat) {
-        Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, vmCpuStat.getTimeStamp());
-        chunk.put(Key.VM_ID, vmCpuStat.getVmId());
-        chunk.put(VmCpuStatDAO.vmCpuLoadKey, vmCpuStat.getCpuLoad());
-        return chunk;
-    }
-
-    @Override
-    public VmCpuStat fromChunk(Chunk chunk) {
-        long timestamp = chunk.get(Key.TIMESTAMP);
-        int vmId = chunk.get(Key.VM_ID);
-        double processorUsage = chunk.get(VmCpuStatDAO.vmCpuLoadKey);
-        return new VmCpuStat(timestamp, vmId, processorUsage);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface VmCpuStatDAO {
-
-    static final Key<Double> vmCpuLoadKey = new Key<>("processor-usage", false);
-
-    static final Category vmCpuStatCategory = new Category("vm-cpu-stats",
-            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, vmCpuLoadKey);
-
-    public abstract List<VmCpuStat> getLatestVmCpuStats(VmRef ref);
-
-    public abstract void putVmCpuStat(VmCpuStat stat);
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmCpuStatDAOImpl implements VmCpuStatDAO {
-
-    private final Storage storage;
-
-    private Converter<VmCpuStat> converter = new VmCpuStatConverter();
-
-    private Map<VmRef, VmLatestPojoListGetter<VmCpuStat>> getters = new HashMap<>();
-
-    VmCpuStatDAOImpl(Storage storage) {
-        this.storage = storage;
-    }
-
-    @Override
-    public List<VmCpuStat> getLatestVmCpuStats(VmRef ref) {
-        VmLatestPojoListGetter<VmCpuStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new VmLatestPojoListGetter<VmCpuStat>(storage, vmCpuStatCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-
-    @Override
-    public void putVmCpuStat(VmCpuStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmGcStatConverter implements Converter<VmGcStat> {
-
-    @Override
-    public Chunk toChunk(VmGcStat vmGcStat) {
-        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
-
-        chunk.put(Key.VM_ID, vmGcStat.getVmId());
-        chunk.put(Key.TIMESTAMP, vmGcStat.getTimeStamp());
-        chunk.put(VmGcStatDAO.collectorKey, vmGcStat.getCollectorName());
-        chunk.put(VmGcStatDAO.runCountKey, vmGcStat.getRunCount());
-        chunk.put(VmGcStatDAO.wallTimeKey, vmGcStat.getWallTime());
-
-        return chunk;
-    }
-
-    @Override
-    public VmGcStat fromChunk(Chunk chunk) {
-        int vmId = chunk.get(Key.VM_ID);
-        long timestamp = chunk.get(Key.TIMESTAMP);
-        String collectorName = chunk.get(VmGcStatDAO.collectorKey);
-        long runCount = chunk.get(VmGcStatDAO.runCountKey);
-        long wallTime = chunk.get(VmGcStatDAO.wallTimeKey);
-
-        return new VmGcStat(vmId, timestamp, collectorName, runCount, wallTime);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface VmGcStatDAO {
-
-    static final Key<String> collectorKey = new Key<>("collector", false);
-    static final Key<Long> runCountKey = new Key<>("runtime-count", false);
-    /** time in microseconds */
-    static final Key<Long> wallTimeKey = new Key<>("wall-time", false);
-
-    static final Category vmGcStatCategory = new Category("vm-gc-stats",
-            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, collectorKey,
-            runCountKey, wallTimeKey);
-
-    public List<VmGcStat> getLatestVmGcStats(VmRef ref);
-
-    public void putVmGcStat(VmGcStat stat);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmGcStatDAOImpl implements VmGcStatDAO {
-
-    private Storage storage;
-
-    private Converter<VmGcStat> converter = new VmGcStatConverter();
-
-    private Map<VmRef, VmLatestPojoListGetter<VmGcStat>> getters = new HashMap<>();
-
-    VmGcStatDAOImpl(Storage storage) {
-        this.storage = storage;
-    }
-
-    @Override
-    public List<VmGcStat> getLatestVmGcStats(VmRef ref) {
-        VmLatestPojoListGetter<VmGcStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new VmLatestPojoListGetter<VmGcStat>(storage, vmGcStatCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-
-    @Override
-    public void putVmGcStat(VmGcStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-
-public class VmInfoConverter implements Converter<VmInfo> {
-
-    @Override
-    public Chunk toChunk(VmInfo info) {
-        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
-
-        chunk.put(VmInfoDAO.vmIdKey, info.getVmId());
-        chunk.put(VmInfoDAO.vmPidKey, info.getVmPid());
-        chunk.put(VmInfoDAO.startTimeKey, info.getStartTimeStamp());
-        chunk.put(VmInfoDAO.stopTimeKey, info.getStopTimeStamp());
-        chunk.put(VmInfoDAO.runtimeVersionKey, info.getJavaVersion());
-        chunk.put(VmInfoDAO.javaHomeKey, info.getJavaHome());
-        chunk.put(VmInfoDAO.mainClassKey, info.getMainClass());
-        chunk.put(VmInfoDAO.commandLineKey, info.getJavaCommandLine());
-        chunk.put(VmInfoDAO.vmNameKey, info.getVmName());
-        chunk.put(VmInfoDAO.vmInfoKey, info.getVmInfo());
-        chunk.put(VmInfoDAO.vmVersionKey, info.getVmVersion());
-        chunk.put(VmInfoDAO.vmArgumentsKey, info.getVmArguments());
-        chunk.put(VmInfoDAO.propertiesKey, info.getProperties());
-        chunk.put(VmInfoDAO.environmentKey, info.getEnvironment());
-        chunk.put(VmInfoDAO.librariesKey, info.getLoadedNativeLibraries());
-        return chunk;
-    }
-
-    @Override
-    public VmInfo fromChunk(Chunk chunk) {
-        int vmId = chunk.get(VmInfoDAO.vmIdKey);
-        long startTime = chunk.get(VmInfoDAO.startTimeKey);
-        long stopTime = chunk.get(VmInfoDAO.stopTimeKey);
-        String jVersion = chunk.get(VmInfoDAO.runtimeVersionKey);
-        String jHome = chunk.get(VmInfoDAO.javaHomeKey);
-        String mainClass = chunk.get(VmInfoDAO.mainClassKey);
-        String commandLine = chunk.get(VmInfoDAO.commandLineKey);
-        String vmName = chunk.get(VmInfoDAO.vmNameKey);
-        String vmInfo = chunk.get(VmInfoDAO.vmInfoKey);
-        String vmVersion = chunk.get(VmInfoDAO.vmVersionKey);
-        String vmArgs = chunk.get(VmInfoDAO.vmArgumentsKey);
-        Map<String, String> props = chunk.get(VmInfoDAO.propertiesKey);
-        Map<String, String> env = chunk.get(VmInfoDAO.propertiesKey);
-        List<String> libs = chunk.get(VmInfoDAO.librariesKey);
-        return new VmInfo(vmId, startTime, stopTime, jVersion, jHome, mainClass, commandLine, vmName,
-                vmInfo, vmVersion, vmArgs, props, env, libs);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface VmInfoDAO extends Countable {
-
-    static final Key<Integer> vmIdKey = new Key<>("vm-id", true);
-    static final Key<Integer> vmPidKey = new Key<>("vm-pid", false);
-    static final Key<String> runtimeVersionKey = new Key<>("runtime-version", false);
-    static final Key<String> javaHomeKey = new Key<>("java-home", false);
-    static final Key<String> mainClassKey = new Key<>("main-class", false);
-    static final Key<String> commandLineKey = new Key<>("command-line", false);
-    static final Key<String> vmArgumentsKey = new Key<>("vm-arguments", false);
-    static final Key<String> vmNameKey = new Key<>("vm-name", false);
-    static final Key<String> vmInfoKey = new Key<>("vm-info", false);
-    static final Key<String> vmVersionKey = new Key<>("vm-version", false);
-    static final Key<Map<String, String>> propertiesKey = new Key<>("properties", false);
-    static final Key<Map<String, String>> environmentKey = new Key<>("environment", false);
-    static final Key<List<String>> librariesKey = new Key<>("libraries", false);
-    static final Key<Long> startTimeKey = new Key<>("start-time", false);
-    static final Key<Long> stopTimeKey = new Key<>("stop-time", false);
-
-    static final Category vmInfoCategory = new Category("vm-info",
-            Key.AGENT_ID, vmIdKey, vmPidKey, runtimeVersionKey, javaHomeKey,
-            mainClassKey, commandLineKey,
-            vmArgumentsKey, vmNameKey, vmInfoKey, vmVersionKey,
-            propertiesKey, environmentKey, librariesKey,
-            startTimeKey, stopTimeKey);
-
-    public VmInfo getVmInfo(VmRef ref);
-
-    Collection<VmRef> getVMs(HostRef host);
-
-    public void putVmInfo(VmInfo info);
-
-    public void putVmStoppedTime(int vmId, long timestamp);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmInfoDAOImpl implements VmInfoDAO {
-
-    private Storage storage;
-    private VmInfoConverter converter;
-
-    VmInfoDAOImpl(Storage storage) {
-        this.storage = storage;
-        this.converter = new VmInfoConverter();
-    }
-
-    @Override
-    public VmInfo getVmInfo(VmRef ref) {
-        Chunk query = new Chunk(vmInfoCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(vmIdKey, ref.getId());
-        Chunk result = storage.find(query);
-        if (result == null) {
-            throw new DAOException("Unknown VM: host:" + ref.getAgent().getAgentId() + ";vm:" + ref.getId());
-        }
-        return converter.fromChunk(result);
-    }
-
-    @Override
-    public Collection<VmRef> getVMs(HostRef host) {
-
-        Chunk query = buildQuery(host);
-        Cursor cursor = storage.findAll(query);
-        return buildVMsFromQuery(cursor, host);
-    }
-
-    private Chunk buildQuery(HostRef host) {
-        Chunk query = new Chunk(vmInfoCategory, false);
-        query.put(Key.AGENT_ID, host.getAgentId());
-        return query;
-    }
-
-    private Collection<VmRef> buildVMsFromQuery(Cursor cursor, HostRef host) {
-        List<VmRef> vmRefs = new ArrayList<VmRef>();
-        while (cursor.hasNext()) {
-            Chunk vmChunk = cursor.next();
-            VmRef vm = buildVmRefFromChunk(vmChunk, host);
-            vmRefs.add(vm);
-        }
-
-        return vmRefs;
-    }
-
-    private VmRef buildVmRefFromChunk(Chunk vmChunk, HostRef host) {
-        Integer id = vmChunk.get(vmIdKey);
-        // TODO can we do better than the main class?
-        String mainClass = vmChunk.get(mainClassKey);
-        VmRef ref = new VmRef(host, id, mainClass);
-        return ref;
-    }
-
-    @Override
-    public long getCount() {
-        return storage.getCount(vmInfoCategory);
-    }
-
-    @Override
-    public void putVmInfo(VmInfo info) {
-        storage.putChunk(converter.toChunk(info));
-    }
-
-    @Override
-    public void putVmStoppedTime(int vmId, long timestamp) {
-        storage.updateChunk(makeStoppedChunk(vmId, timestamp));
-    }
-
-    private Chunk makeStoppedChunk(int vmId, long stopTimeStamp) {
-        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, false);
-        chunk.put(VmInfoDAO.vmIdKey, vmId);
-        chunk.put(VmInfoDAO.stopTimeKey, stopTimeStamp);
-        return chunk;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import com.redhat.thermostat.common.model.TimeStampedPojo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmLatestPojoListGetter<T extends TimeStampedPojo> extends HostLatestPojoListGetter<T> {
-
-    private VmRef vmRef;
-
-    VmLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, VmRef ref) {
-        super(storage, cat, converter, ref.getAgent());
-        vmRef = ref;
-    }
-
-    @Override
-    protected Chunk buildQuery() {
-        Chunk query = super.buildQuery();
-        query.put(Key.VM_ID, vmRef.getId());
-        return query;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmMemoryStatConverter implements Converter<VmMemoryStat> {
-
-    @Override
-    public Chunk toChunk(VmMemoryStat vmMemStat) {
-        Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
-
-        chunk.put(Key.VM_ID, vmMemStat.getVmId());
-        chunk.put(Key.TIMESTAMP, vmMemStat.getTimeStamp());
-
-        Generation newGen = vmMemStat.getGeneration("new");
-
-        Space eden = newGen.getSpace("eden");
-        chunk.put(VmMemoryStatDAO.edenGenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.edenCollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.edenCapacityKey, eden.capacity);
-        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, eden.maxCapacity);
-        chunk.put(VmMemoryStatDAO.edenUsedKey, eden.used);
-
-        Space s0 = newGen.getSpace("s0");
-        chunk.put(VmMemoryStatDAO.s0GenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.s0CollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.s0CapacityKey, s0.capacity);
-        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, s0.maxCapacity);
-        chunk.put(VmMemoryStatDAO.s0UsedKey, s0.used);
-
-        Space s1 = newGen.getSpace("s1");
-        chunk.put(VmMemoryStatDAO.s1GenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.s1CollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.s1CapacityKey, s1.capacity);
-        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, s1.maxCapacity);
-        chunk.put(VmMemoryStatDAO.s1UsedKey, s1.used);
-
-        Generation oldGen = vmMemStat.getGeneration("old");
-
-        Space old = oldGen.getSpace("old");
-        chunk.put(VmMemoryStatDAO.oldGenKey, oldGen.name);
-        chunk.put(VmMemoryStatDAO.oldCollectorKey, oldGen.collector);
-        chunk.put(VmMemoryStatDAO.oldCapacityKey, old.capacity);
-        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, old.maxCapacity);
-        chunk.put(VmMemoryStatDAO.oldUsedKey, old.used);
-
-        Generation permGen = vmMemStat.getGeneration("perm");
-
-        Space perm = permGen.getSpace("perm");
-        chunk.put(VmMemoryStatDAO.permGenKey, permGen.name);
-        chunk.put(VmMemoryStatDAO.permCollectorKey, permGen.collector);
-        chunk.put(VmMemoryStatDAO.permCapacityKey, perm.capacity);
-        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, perm.maxCapacity);
-        chunk.put(VmMemoryStatDAO.permUsedKey, perm.used);
-
-        return chunk;
-    }
-
-    @Override
-    public VmMemoryStat fromChunk(Chunk chunk) {
-        Space space = null;
-        List<Space> spaces = null;
-
-        List<Generation> gens = new ArrayList<>();
-        Generation newGen = new Generation();
-        spaces = new ArrayList<>();
-        newGen.spaces = spaces;
-        newGen.name = "new";
-        newGen.capacity = 0;
-        newGen.maxCapacity = 0;
-        // FIXME Something is wrong here when we have the collector stored
-        // as part of 3 spaces in Chunk but is only one thing in Stat
-        newGen.collector = chunk.get(VmMemoryStatDAO.edenCollectorKey);
-
-        space = new Space();
-        space.name = VmMemoryStatDAO.edenKey.getName();
-        space.capacity = chunk.get(VmMemoryStatDAO.edenCapacityKey);
-        space.maxCapacity = chunk.get(VmMemoryStatDAO.edenMaxCapacityKey);
-        space.used = chunk.get(VmMemoryStatDAO.edenUsedKey);
-        spaces.add(space);
-        newGen.capacity += space.capacity;
-        newGen.maxCapacity += space.maxCapacity;
-
-        space = new Space();
-        space.name = VmMemoryStatDAO.s0Key.getName();
-        space.capacity = chunk.get(VmMemoryStatDAO.s0CapacityKey);
-        space.maxCapacity = chunk.get(VmMemoryStatDAO.s0MaxCapacityKey);
-        space.used = chunk.get(VmMemoryStatDAO.s0UsedKey);
-        spaces.add(space);
-        newGen.capacity += space.capacity;
-        newGen.maxCapacity += space.maxCapacity;
-
-        space = new Space();
-        space.name = VmMemoryStatDAO.s1Key.getName();
-        space.capacity = chunk.get(VmMemoryStatDAO.s1CapacityKey);
-        space.maxCapacity = chunk.get(VmMemoryStatDAO.s1MaxCapacityKey);
-        space.used = chunk.get(VmMemoryStatDAO.s1UsedKey);
-        spaces.add(space);
-        newGen.capacity += space.capacity;
-        newGen.maxCapacity += space.maxCapacity;
-
-        gens.add(newGen);
-
-        Generation oldGen = new Generation();
-        spaces = new ArrayList<>();
-        oldGen.spaces = spaces;
-        oldGen.name = "old";
-        oldGen.collector = chunk.get(VmMemoryStatDAO.oldCollectorKey);
-
-        space = new Space();
-        space.name = VmMemoryStatDAO.oldKey.getName();
-        space.capacity = chunk.get(VmMemoryStatDAO.oldCapacityKey);
-        space.maxCapacity = chunk.get(VmMemoryStatDAO.oldMaxCapacityKey);
-        space.used = chunk.get(VmMemoryStatDAO.oldUsedKey);
-        spaces.add(space);
-        oldGen.capacity = space.capacity;
-        oldGen.maxCapacity = space.capacity;
-
-        gens.add(oldGen);
-
-        Generation permGen = new Generation();
-        spaces = new ArrayList<>();
-        permGen.spaces = spaces;
-        permGen.name = "perm";
-        permGen.collector = chunk.get(VmMemoryStatDAO.permCollectorKey);
-
-        space = new Space();
-        space.name = VmMemoryStatDAO.permKey.getName();
-        space.capacity = chunk.get(VmMemoryStatDAO.permCapacityKey);
-        space.maxCapacity = chunk.get(VmMemoryStatDAO.permMaxCapacityKey);
-        space.used = chunk.get(VmMemoryStatDAO.permUsedKey);
-        spaces.add(space);
-        permGen.capacity = space.capacity;
-        permGen.maxCapacity = space.capacity;
-
-        gens.add(permGen);
-
-        return new VmMemoryStat(chunk.get(Key.TIMESTAMP), chunk.get(Key.VM_ID), gens);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Key;
-
-public interface VmMemoryStatDAO {
-
-    static final Key<String> edenKey = new Key<>("eden", false);
-    static final Key<String> edenGenKey = new Key<>("eden.gen", false);
-    static final Key<String> edenCollectorKey = new Key<>("eden.collector", false);
-    static final Key<Long> edenCapacityKey = new Key<>("eden.capacity", false);
-    static final Key<Long> edenMaxCapacityKey = new Key<>("eden.max-capacity", false);
-    static final Key<Long> edenUsedKey = new Key<>("eden.used", false);
-
-    static final Key<String> s0Key = new Key<>("s0", false);
-    static final Key<String> s0GenKey = new Key<>("s0.gen", false);
-    static final Key<String> s0CollectorKey = new Key<>("s0.collector", false);
-    static final Key<Long> s0CapacityKey = new Key<>("s0.capacity", false);
-    static final Key<Long> s0MaxCapacityKey = new Key<>("s0.max-capacity", false);
-    static final Key<Long> s0UsedKey = new Key<>("s0.used", false);
-
-    static final Key<String> s1Key = new Key<>("s1", false);
-    static final Key<String> s1GenKey = new Key<>("s1.gen", false);
-    static final Key<String> s1CollectorKey = new Key<>("s1.collector", false);
-    static final Key<Long> s1CapacityKey = new Key<>("s1.capacity", false);
-    static final Key<Long> s1MaxCapacityKey = new Key<>("s1.max-capacity", false);
-    static final Key<Long> s1UsedKey = new Key<>("s1.used", false);
-
-    static final Key<String> oldKey = new Key<>("old", false);
-    static final Key<String> oldGenKey = new Key<>("old.gen", false);
-    static final Key<String> oldCollectorKey = new Key<>("old.collector", false);
-    static final Key<Long> oldCapacityKey = new Key<>("old.capacity", false);
-    static final Key<Long> oldMaxCapacityKey = new Key<>("old.max-capacity", false);
-    static final Key<Long> oldUsedKey = new Key<>("old.used", false);
-
-    static final Key<String> permKey = new Key<>("perm", false);
-    static final Key<String> permGenKey = new Key<>("perm.gen", false);
-    static final Key<String> permCollectorKey = new Key<>("perm.collector", false);
-    static final Key<Long> permCapacityKey = new Key<>("perm.capacity", false);
-    static final Key<Long> permMaxCapacityKey = new Key<>("perm.max-capacity", false);
-    static final Key<Long> permUsedKey = new Key<>("perm.used", false);
-
-    static final Category vmMemoryStatsCategory = new Category("vm-memory-stats",
-            Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP,
-            edenGenKey, edenCollectorKey,
-            edenCapacityKey, edenMaxCapacityKey,edenUsedKey,
-            s0GenKey, s0CollectorKey, s0CapacityKey,
-            s0MaxCapacityKey, s0UsedKey,
-            s1GenKey, s1CollectorKey, s1CapacityKey,
-            s1MaxCapacityKey, s1UsedKey,
-            oldGenKey, oldCollectorKey, oldCapacityKey,
-            oldMaxCapacityKey, oldUsedKey,
-            permGenKey, permCollectorKey, permCapacityKey,
-            permMaxCapacityKey, permUsedKey);
-
-    public VmMemoryStat getLatestMemoryStat(VmRef ref);
-
-    public List<VmMemoryStat> getLatestVmMemoryStats(VmRef vm);
-
-    public void putVmMemoryStat(VmMemoryStat stat);
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-class VmMemoryStatDAOImpl implements VmMemoryStatDAO {
-
-    private final Storage storage;
-    private final VmMemoryStatConverter converter;
-
-    private Map<VmRef, VmLatestPojoListGetter<VmMemoryStat>> getters = new HashMap<>();
-
-    VmMemoryStatDAOImpl(Storage storage) {
-        this.storage = storage;
-        converter = new VmMemoryStatConverter();
-    }
-
-    @Override
-    public VmMemoryStat getLatestMemoryStat(VmRef ref) {
-        Chunk query = new Chunk(vmMemoryStatsCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(Key.VM_ID, ref.getId());
-        Cursor cursor = storage.findAll(query).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1);
-        if (cursor.hasNext()) {
-            return converter.fromChunk(cursor.next());
-        }
-        return null;
-    }
-
-    @Override
-    public void putVmMemoryStat(VmMemoryStat stat) {
-        storage.putChunk(converter.toChunk(stat));
-    }
-
-    @Override
-    public List<VmMemoryStat> getLatestVmMemoryStats(VmRef ref) {
-        VmLatestPojoListGetter<VmMemoryStat> getter = getters.get(ref);
-        if (getter == null) {
-            getter = new VmLatestPojoListGetter<VmMemoryStat>(storage, vmMemoryStatsCategory, converter, ref);
-            getters.put(ref, getter);
-        }
-        return getter.getLatest();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmRef.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-public class VmRef implements Ref {
-
-    private final HostRef hostRef;
-    private final Integer uid;
-    private final String uidString;
-    private final String name;
-
-    public VmRef(HostRef hostRef, Integer id, String name) {
-        this.hostRef = hostRef;
-        this.uid = id;
-        this.uidString = id.toString();
-        this.name = name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    public HostRef getAgent() {
-        return hostRef;
-    }
-
-    public Integer getId() {
-        return uid;
-    }
-
-    public String getIdString() {
-        return uidString;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (obj == this) {
-            return true;
-        }
-        if (obj.getClass() != this.getClass()) {
-            return false;
-        }
-        VmRef other = (VmRef) obj;
-        if (equals(this.hostRef, other.hostRef) && equals(this.uid, other.uid) && equals(this.name, other.name)) {
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean equals(Object obj1, Object obj2) {
-        return (obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2));
-    }
-
-    @Override
-    public int hashCode() {
-        return uid.hashCode();
-    }
-
-    @Override
-    public String getStringID() {
-        return getIdString();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/CpuStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class CpuStat implements TimeStampedPojo {
-
-    public static final double INVALID_LOAD = Double.MIN_VALUE;
-
-    private final double load5;
-    private final double load10;
-    private final double load15;
-    private final long timeStamp;
-
-    public CpuStat(long timestamp, double load5, double load10, double load15) {
-        this.timeStamp = timestamp;
-        this.load5 = load5;
-        this.load10 = load10;
-        this.load15 = load15;
-    }
-
-    public double getLoad5() {
-        return load5;
-    }
-
-    public double getLoad10() {
-        return load10;
-    }
-
-    public double getLoad15() {
-        return load15;
-    }
-
-    public double[] getLoad() {
-        return new double[] { load5, load10, load15 };
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timeStamp;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/DiscreteTimeData.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-/**
- * Represents a data associated with a discrete point in time
- *
- * @param <T> the type data associated with this point in time
- */
-public class DiscreteTimeData<T> {
-
-    private long millis;
-    private T data;
-
-    public DiscreteTimeData(long millis, T data) {
-        this.millis = millis;
-        this.data = data;
-    }
-
-    public long getTimeInMillis() {
-        return millis;
-    }
-
-    public T getData() {
-        return data;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/HostInfo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class HostInfo implements Pojo {
-
-    private final String hostname;
-    private final String osName;
-    private final String osKernel;
-    private final String cpuModel;
-    private final int cpuCount;
-    private final long totalMemory;
-
-    public HostInfo(String hostname, String osName, String osKernel, String cpuModel, int cpuCount, long totalMemory) {
-        this.hostname = hostname;
-        this.osName = osName;
-        this.osKernel = osKernel;
-        this.cpuModel = cpuModel;
-        this.cpuCount = cpuCount;
-        this.totalMemory = totalMemory;
-    }
-
-    public String getHostname() {
-        return hostname;
-    }
-
-    public String getOsName() {
-        return osName;
-    }
-
-    public String getOsKernel() {
-        return osKernel;
-    }
-
-    public String getCpuModel() {
-        return cpuModel;
-    }
-
-    public int getCpuCount() {
-        return cpuCount;
-    }
-
-    /**
-     * Total memory in bytes
-     */
-    public long getTotalMemory() {
-        return totalMemory;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/IntervalTimeData.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class IntervalTimeData<T> {
-
-    private long start;
-    private long end;
-    private T data;
-
-    public IntervalTimeData(long start, long end, T data) {
-        this.start = start;
-        this.end = end;
-        this.data = data;
-    }
-
-    public long getStartTimeInMillis() {
-        return start;
-    }
-
-    public long getEndTimeInMillis() {
-        return end;
-    }
-
-    public T getData() {
-        return data;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class MemoryStat implements TimeStampedPojo {
-    private final long timestamp;
-    private final long total;
-    private final long free;
-    private final long buffers;
-    private final long cached;
-    private final long swapTotal;
-    private final long swapFree;
-    private final long commitLimit;
-
-    public MemoryStat(long timestamp, long total, long free, long buffers, long cached, long swapTotal, long swapFree, long commitLimit) {
-        this.timestamp = timestamp;
-        this.total = total;
-        this.free = free;
-        this.buffers = buffers;
-        this.cached = cached;
-        this.swapTotal = swapTotal;
-        this.swapFree = swapFree;
-        this.commitLimit = commitLimit;
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timestamp;
-    }
-
-    public long getTotal() {
-        return total;
-    }
-
-    public long getFree() {
-        return free;
-    }
-
-    public long getBuffers() {
-        return buffers;
-    }
-
-    public long getCached() {
-        return cached;
-    }
-
-    public long getSwapTotal() {
-        return swapTotal;
-    }
-
-    public long getSwapFree() {
-        return swapFree;
-    }
-
-    public long getCommitLimit() {
-        return commitLimit;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/MemoryType.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public enum MemoryType {
-    MEMORY_TOTAL,
-    MEMORY_FREE,
-    MEMORY_USED,
-    SWAP_TOTAL,
-    SWAP_FREE,
-    BUFFERS;
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class NetworkInterfaceInfo implements Pojo {
-
-    private String iFace;
-    private String ip4Addr;
-    private String ip6Addr;
-
-    public NetworkInterfaceInfo(String iFace) {
-        this.iFace = iFace;
-        this.ip4Addr = null;
-        this.ip6Addr = null;
-    }
-
-    public String getInterfaceName() {
-        return iFace;
-    }
-
-    public String getIp4Addr() {
-        return ip4Addr;
-    }
-
-    public void setIp4Addr(String newAddr) {
-        ip4Addr = newAddr;
-    }
-
-    public void clearIp4Addr() {
-        ip4Addr = null;
-    }
-
-    public String getIp6Addr() {
-        return ip6Addr;
-    }
-
-    public void setIp6Addr(String newAddr) {
-        ip6Addr = newAddr;
-    }
-
-    public void clearIp6Addr() {
-        ip6Addr = null;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/Pojo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-/**
- * All data types should implement this empty interface, to support the
- * generalization of DAO code where possible.
- */
-public interface Pojo {
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-/**
- * Any Pojo which is taken as a timestamped piece of data should
- * implement this interface.
- */
-public interface TimeStampedPojo extends Pojo {
-
-    public long getTimeStamp();
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelator.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
-public class TimeStampedPojoCorrelator implements Iterable<TimeStampedPojoCorrelator.Correlation> {
-
-    public static class Correlation {
-
-        private long timestamp;
-        private TimeStampedPojo[] correlation;
-
-        private Correlation(long timestamp, TimeStampedPojo[] correlation) {
-            this.timestamp = timestamp;
-            this.correlation = correlation;
-        }
-
-        public TimeStampedPojo get(int i) {
-            return correlation[i];
-        }
-
-        public long getTimeStamp() {
-            return timestamp;
-        }
-        
-    }
-
-    private static class TimeStampedPojoComparator implements Comparator<TimeStampedPojo> {
-
-        @Override
-        public int compare(TimeStampedPojo o1, TimeStampedPojo o2) {
-            return Long.compare(o1.getTimeStamp(), o2.getTimeStamp());
-        }
-
-        
-    }
-
-    private class Correlator implements Iterator<Correlation> {
-
-        private List<Iterator<TimeStampedPojo>> seriesIterators;
-
-        private Correlator() {
-            seriesIterators = new ArrayList<>();
-            int index = 0;
-            for (List<TimeStampedPojo> series : seriesList) {
-                Iterator<TimeStampedPojo> seriesIterator = series.iterator();
-                seriesIterators.add(seriesIterator);
-                if (seriesIterator.hasNext()) {
-                    current[index] = seriesIterator.next();
-                }
-                index++;
-            }
-            
-        }
-
-        @Override
-        public boolean hasNext() {
-            boolean hasNext = false;
-            for (TimeStampedPojo pojo : current) {
-                hasNext |= pojo != null;
-            }
-            return hasNext;
-        }
-
-        @Override
-        public Correlation next() {
-            long minTimestamp = Long.MAX_VALUE;
-            for (TimeStampedPojo pojo : current) {
-                if (pojo != null) {
-                    minTimestamp = Math.min(minTimestamp, pojo.getTimeStamp());
-                }
-            }
-            TimeStampedPojo[] next = new TimeStampedPojo[numSeries];
-            for (int i = 0; i < numSeries; i++) {
-                if (current[i] != null && current[i].getTimeStamp() == minTimestamp) {
-                    next[i] = current[i];
-                    Iterator<TimeStampedPojo> iterator = seriesIterators.get(i);
-                    current[i] = iterator.hasNext() ? iterator.next() : null;
-                } else {
-                    next[i] = last != null ? last.get(i) : null;
-                }
-            }
-            last = new Correlation(minTimestamp, next);
-            return last;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-        
-    }
-
-    private int numSeries;
-
-    private List<List<TimeStampedPojo>> seriesList;
-
-    private TimeStampedPojo[] current;
-    private Correlation last;
-
-    public TimeStampedPojoCorrelator(int numSeries) {
-        this.numSeries = numSeries;
-        seriesList = new ArrayList<>();
-        for (int i = 0; i < numSeries; i++) {
-            seriesList.add(new ArrayList<TimeStampedPojo>());
-        }
-        current = new TimeStampedPojo[numSeries];
-    }
-
-    public void add(int seriesIndex, TimeStampedPojo timeStampedPojo) {
-        List<? extends TimeStampedPojo> series = seriesList.get(seriesIndex);
-        int insertIdx = Collections.binarySearch(series, timeStampedPojo, new TimeStampedPojoComparator());
-        if (insertIdx < 0) {
-            insertIdx = -(insertIdx + 1);
-        }
-        seriesList.get(seriesIndex).add(insertIdx, timeStampedPojo);
-    }
-
-    public Iterator<Correlation> iterator() {
-        return new Correlator();
-    }
-
-    public void clear() {
-        for (List<TimeStampedPojo> series : seriesList) {
-            series.clear();
-        }
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class VmClassStat implements TimeStampedPojo {
-
-    private int vmId;
-    private long timestamp;
-    private long loadedClasses;
-
-    public VmClassStat(int vmId, long timestamp, long loadedClasses) {
-        this.vmId = vmId;
-        this.timestamp = timestamp;
-        this.loadedClasses = loadedClasses;
-    }
-
-    public int getVmId() {
-        return vmId;
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timestamp;
-    }
-
-    public long getLoadedClasses() {
-        return loadedClasses;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class VmCpuStat implements TimeStampedPojo {
-
-    private final long timestamp;
-    private final int vmId;
-    private final double cpuLoad;
-
-    public VmCpuStat(long timestamp, int vmId, double cpuLoad) {
-        this.timestamp = timestamp;
-        this.vmId = vmId;
-        this.cpuLoad = cpuLoad;
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timestamp;
-    }
-
-    public int getVmId() {
-        return vmId;
-    }
-
-    /**
-     * The cpu load in percent (as in 100.0 for 100%). This value should be
-     * normalized to be in the range [0, 100]
-     */
-    public double getCpuLoad() {
-        return cpuLoad;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-public class VmGcStat implements TimeStampedPojo {
-
-    private final long timestamp;
-    private final int vmId;
-    private final String collectorName;
-    private final long runCount;
-    private final long wallTime;
-
-    public VmGcStat(int vmId, long timestamp, String collectorName, long runCount, long wallTime) {
-        this.timestamp = timestamp;
-        this.vmId = vmId;
-        this.collectorName = collectorName;
-        this.runCount = runCount;
-        this.wallTime = wallTime;
-    }
-    public int getVmId() {
-        return vmId;
-    }
-    public String getCollectorName() {
-        return collectorName;
-    }
-    public long getRunCount() {
-        return runCount;
-    }
-    public long getWallTime() {
-        return wallTime;
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timestamp;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmInfo.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class VmInfo implements Pojo {
-
-    private int vmPid = 0;
-    private long startTime = System.currentTimeMillis();
-    private long stopTime = Long.MIN_VALUE;
-    private String javaVersion = "unknown";
-    private String javaHome = "unknown";
-    private String javaCommandLine = "unknown";
-    private String mainClass = "unknown";
-    private String vmName = "unknown";
-    private String vmInfo = "unknown";
-    private String vmVersion = "unknown";
-    private String vmArguments = "unknown";
-    private Map<String, String> properties = new HashMap<String, String>();
-    private Map<String, String> environment = new HashMap<String, String>();
-    private List<String> loadedNativeLibraries;
-
-    public VmInfo() {
-        /* use defaults */
-    }
-
-    public VmInfo(int vmPid, long startTime, long stopTime,
-            String javaVersion, String javaHome,
-            String mainClass, String commandLine,
-            String vmName, String vmInfo, String vmVersion, String vmArguments,
-            Map<String, String> properties, Map<String, String> environment, List<String> loadedNativeLibraries) {
-        this.vmPid = vmPid;
-        this.startTime = startTime;
-        this.stopTime = stopTime;
-        this.javaVersion = javaVersion;
-        this.javaHome = javaHome;
-        this.mainClass = mainClass;
-        this.javaCommandLine = commandLine;
-        this.vmName = vmName;
-        this.vmInfo = vmInfo;
-        this.vmVersion = vmVersion;
-        this.vmArguments = vmArguments;
-        this.properties = properties;
-        this.environment = environment;
-        this.loadedNativeLibraries = loadedNativeLibraries;
-    }
-
-    public int getVmId() {
-        return vmPid;
-    }
-
-    public int getVmPid() {
-        return vmPid;
-    }
-
-    public long getStartTimeStamp() {
-        return startTime;
-    }
-
-    public long getStopTimeStamp() {
-        return stopTime;
-    }
-
-    public String getJavaVersion() {
-        return javaVersion;
-    }
-
-    public String getJavaHome() {
-        return javaHome;
-    }
-
-    public String getMainClass() {
-        return mainClass;
-    }
-
-    public String getJavaCommandLine() {
-        return javaCommandLine;
-    }
-
-    public String getVmName() {
-        return vmName;
-    }
-
-    public String getVmArguments() {
-        return vmArguments;
-    }
-
-    public String getVmInfo() {
-        return vmInfo;
-    }
-
-    public String getVmVersion() {
-        return vmVersion;
-    }
-
-    public boolean isAlive() {
-        return getStartTimeStamp() > getStopTimeStamp();
-    }
-    
-    public Map<String, String> getProperties() {
-        return properties;
-    }
-
-    public Map<String, String> getEnvironment() {
-        return environment;
-    }
-
-    public List<String> getLoadedNativeLibraries() {
-        return loadedNativeLibraries;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-import java.util.List;
-
-public class VmMemoryStat implements TimeStampedPojo {
-
-    public static class Generation {
-        public static final String COLLECTOR_NONE = "none";
-        public String name;
-        public long capacity;
-        public long maxCapacity;
-        public List<Space> spaces;
-        public String collector;
-
-        public Space getSpace(String string) {
-            for (Space s : spaces) {
-                if (s.name.equals(string)) {
-                    return s;
-                }
-            }
-            return null;
-        }
-    }
-
-    public static class Space {
-        public int index;
-        public String name;
-        public long capacity;
-        public long maxCapacity;
-        public long used;
-    }
-
-    private final List<Generation> generations;
-    private final long timestamp;
-    private final int vmId;
-
-    public VmMemoryStat(long timestamp, int vmId, List<Generation> generations) {
-        this.timestamp = timestamp;
-        this.vmId = vmId;
-        this.generations = generations;
-    }
-
-    public int getVmId() {
-        return vmId;
-    }
-
-    @Override
-    public long getTimeStamp() {
-        return timestamp;
-    }
-
-    public List<Generation> getGenerations() {
-        return generations;
-    }
-
-    public Generation getGeneration(String name) {
-        for (Generation g : generations) {
-            if (g.name.equals(name)) {
-                return g;
-            }
-        }
-        return null;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class AgentInformation {
-
-    public static final Category AGENT_INFO_CATEGORY =
-            new Category(StorageConstants.CATEGORY_AGENT_CONFIG, Key.AGENT_ID);
-
-    public static final Key<Boolean> AGENT_ALIVE_KEY = new Key<>("alive", false);
-    
-    private long startTime;
-    private long stopTime;
-
-    private boolean alive;
-    
-    private List<BackendInformation> backends = new ArrayList<BackendInformation>();
-    
-    public long getStartTime() {
-        return startTime;
-    }
-
-    public void setStartTime(long startTime) {
-        this.startTime = startTime;
-    }
-
-    public void setStopTime(long stopTime) {
-        this.stopTime = stopTime;
-    }
-    
-    public long getStopTime() {
-        return stopTime;
-    }
-    
-    public List<BackendInformation> getBackends() {
-        return Collections.unmodifiableList(backends);
-    }
-
-    public boolean isAlive() {
-        return alive;
-    }
-    
-    public void setAlive(boolean alive) {
-        this.alive = alive;
-    }
-    
-    public void addBackend(BackendInformation backend) {
-        backends.add(backend);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/BackendInformation.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class BackendInformation {
-
-    private String name;
-    private String description;
-    private boolean observeNewJvm;
-    private List<Integer> pids;
-    private Map<String, String> configuration = new HashMap<String,String>();
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    public boolean isObserveNewJvm() {
-        return observeNewJvm;
-    }
-
-    public void setObserveNewJvm(boolean observeNewJvm) {
-        this.observeNewJvm = observeNewJvm;
-    }
-
-    public List<Integer> getPids() {
-        return pids;
-    }
-
-    public Map<String, String> getConfiguration() {
-        return configuration;
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Category.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class Category {
-    private final String name;
-    private final Map<String, Key<?>> keys;
-
-    private ConnectionKey connectionKey;
-
-    private static Set<String> categoryNames = new HashSet<String>();
-
-    /**
-     * Creates a new Category instance with the specified name.
-     *
-     * @param name the name of the category
-     *
-     * @throws IllegalArgumentException if a Category is created with a name that has been used before
-     */
-    public Category(String name, Key<?>... keys) {
-        if (categoryNames.contains(name)) {
-            throw new IllegalStateException();
-        }
-        categoryNames.add(name);
-        this.name = name;
-        Map<String, Key<?>> keysMap = new HashMap<String, Key<?>>();
-        for (Key<?> key : keys) {
-            keysMap.put(key.getName(), key);
-        }
-        this.keys = Collections.unmodifiableMap(keysMap);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public synchronized Collection<Key<?>> getKeys() {
-        return keys.values();
-    }
-
-    public void setConnectionKey(ConnectionKey connKey) {
-        connectionKey = connKey;
-    }
-
-    public ConnectionKey getConnectionKey() {
-        return connectionKey;
-    }
-
-    public boolean hasBeenRegistered() {
-        return getConnectionKey() != null;
-    }
-
-    public Key<?> getKey(String name) {
-        return keys.get(name);
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Chunk.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * A Chunk is a unit containing a set of data that can be added as a whole to the dataset
- * that exists behind the storage layer.
- */
-public class Chunk {
-    private final Category category;
-    private final boolean replace;
-
-    private Map<Key<?>, Object> values = new LinkedHashMap<Key<?>, Object>();
-
-    /**
-     *
-     * @param category The {@link Category} of this data.  This should be a Category that the {@link Backend}
-     * who is producing this Chunk has registered via {@link Storage#registerCategory()}
-     * @param replace whether this chunk should replace the values based on the keys for this category,
-     * or be added to a set of values in this category
-     */
-    public Chunk(Category category, boolean replace) {
-        this.category = category;
-        this.replace = replace;
-    }
-
-    public Category getCategory() {
-        return category;
-    }
-
-    public boolean getReplace() {
-        return replace;
-    }
-
-    public <T> void put(Key<T> entry, T value) {
-        values.put(entry, value);
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T> T get(Key<T> entry) {
-        // We only allow matching types in put(), so this cast should be fine.
-        return (T) values.get(entry);
-    }
-
-    public Set<Key<?>> getKeys() {
-        return values.keySet();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (! (o instanceof Chunk)) {
-            return false;
-        }
-        Chunk other = (Chunk) o;
-        return equalCategory(other) && equalValues(other);
-
-    }
-
-    private boolean equalCategory(Chunk other) {
-        return category == other.category;
-    }
-
-    private boolean equalValues(Chunk other) {
-        if (values.size() != other.values.size()) {
-            return false;
-        }
-        for (Entry<Key<?>, Object> entry : values.entrySet()) {
-            if (! equalEntry(other, entry)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean equalEntry(Chunk other, Entry<Key<?>, Object> entry) {
-        Key<?> key = entry.getKey();
-        return other.values.containsKey(key) && Objects.equals(other.values.get(key), values.get(key));
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/ChunkConverter.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-class ChunkConverter {
-
-    private static final Logger logger = LoggingUtils.getLogger(ChunkConverter.class);
-
-    DBObject chunkToDBObject(Chunk chunk) {
-        BasicDBObject dbObject = new BasicDBObject();
-        Map<String, DBObject> dbObjectMap = null;
-        for (Key<?> key : chunk.getKeys()) {
-            dbObjectMap = convertChunkKey(chunk, key, dbObject, dbObjectMap);
-        }
-        return dbObject;
-    }
-
-    private Map<String, DBObject> convertChunkKey(Chunk chunk, Key<?> key, DBObject dbObject, Map<String,DBObject> dbObjectMap) {
-        String[] keyParts = key.getName().split("\\.");
-        String initialName = keyParts[0];
-        return convertChunkKeyRecursively(chunk, key, dbObject, keyParts, 0, initialName, dbObjectMap);
-    }
-
-    private Map<String, DBObject> convertChunkKeyRecursively(Chunk chunk, Key<?> key, DBObject dbObject, String[] keyParts, int partIndex,
-                                            String partialKeyName, Map<String, DBObject> dbObjectMap) {
-        if (partIndex == keyParts.length - 1) {
-            dbObject.put(keyParts[partIndex], chunk.get(key));
-        } else {
-            dbObjectMap = lazyCreateDBObjectMap(dbObjectMap);
-            DBObject nestedDbObject = getOrCreateSubObject(partialKeyName, dbObjectMap);
-            dbObject.put(keyParts[partIndex], nestedDbObject);
-            partIndex++;
-            String nextSubKey = keyParts[partIndex];
-            partialKeyName = partialKeyName + "." + nextSubKey;
-            convertChunkKeyRecursively(chunk, key, nestedDbObject, keyParts, partIndex, partialKeyName, dbObjectMap);
-        }
-        return dbObjectMap;
-    }
-
-    
-    private Map<String, DBObject> lazyCreateDBObjectMap(Map<String, DBObject> dbObjectMap) {
-        if (dbObjectMap == null) {
-            dbObjectMap = new HashMap<String, DBObject>();
-        }
-        return dbObjectMap;
-    }
-
-    private DBObject getOrCreateSubObject(String partialKeyName,
-            Map<String, DBObject> dbObjectMap) {
-        DBObject dbObject = dbObjectMap.get(partialKeyName);
-        if (dbObject == null) {
-            dbObject = new BasicDBObject();
-            dbObjectMap.put(partialKeyName, dbObject);
-        }
-        return dbObject;
-    }
-
-    public Chunk dbObjectToChunk(DBObject dbObject, Category category) {
-        Chunk chunk = new Chunk(category, false);
-        dbObjectToChunkRecurse(chunk, dbObject, category, null);
-        return chunk;
-    }
-
-    private void dbObjectToChunkRecurse(Chunk chunk, DBObject dbObject, Category category, String fullKey) {
-        for (String dbKey : dbObject.keySet()) {
-            if (!dbKey.equals("_id")) { // Mongo adds this to any stored document.
-                String newFullKey;
-                if (fullKey == null) {
-                    newFullKey = dbKey;
-                } else {
-                    newFullKey = fullKey + "." + dbKey;
-                }
-                dbObjectToChunkRecursively(chunk, dbObject, category, dbKey, newFullKey);
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private void dbObjectToChunkRecursively(Chunk chunk, DBObject dbObject, Category category, String dbKey, String fullKey) {
-        Object value = dbObject.get(dbKey);
-        if (value instanceof DBObject) {
-            DBObject dbObj = (DBObject) value;
-            dbObjectToChunkRecurse(chunk, dbObj, category, fullKey);
-        } else {
-            @SuppressWarnings("rawtypes")
-            Key key = category.getKey(fullKey);
-            if (key != null) {
-                chunk.put(key, value);
-            } else {
-                logger.warning("No key matching \"" + fullKey + "\" in category \"" + category + "\"");
-            }
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Connection.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public abstract class Connection {
-
-    public enum ConnectionType {
-        LOCAL(false),
-        REMOTE(true),
-        CLUSTER(true),
-        ;
-
-        boolean isDisplayable = false;
-        boolean needsUrl = false;
-
-        private ConnectionType(boolean needsUrl) {
-            this.needsUrl = needsUrl;
-        }
-
-        private ConnectionType(boolean isDisplayable, boolean needsUrl) {
-            this.isDisplayable = isDisplayable;
-        }
-
-        public boolean isDisplayable() {
-            return isDisplayable;
-        }
-
-        public boolean needsUrl() {
-            return needsUrl;
-        }
-    }
-
-    public enum ConnectionStatus {
-        CONNECTED,
-        CONNECTING,
-        FAILED_TO_CONNECT,
-        DISCONNECTED,
-    }
-
-    public interface ConnectionListener {
-        public void changed(ConnectionStatus newStatus);
-    }
-
-    protected boolean connected = false;
-
-    private ConnectionType type;
-    private String url;
-
-    private List<Connection.ConnectionListener> listeners = new CopyOnWriteArrayList<>();
-
-    public void setType(ConnectionType type) {
-        this.type = type;
-    }
-
-    public ConnectionType getType() {
-        return type;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    @Override
-    public String toString() {
-        if (url == null) {
-            return type.toString();
-        }
-        return type.toString() + " to " + url;
-    }
-
-    public abstract void connect();
-
-    public abstract void disconnect();
-
-    public boolean isConnected() {
-        return connected;
-    }
-
-    public void addListener(ConnectionListener listener) {
-        this.listeners.add(listener);
-    }
-
-    public void removeListener(ConnectionListener listener) {
-        this.listeners.remove(listener);
-    }
-
-    protected void fireChanged(ConnectionStatus status) {
-        for (ConnectionListener listener: listeners) {
-            listener.changed(status);
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/ConnectionException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-public class ConnectionException extends RuntimeException {
-
-    public ConnectionException() {
-        super();
-    }
-
-    public ConnectionException(String message) {
-        super(message);
-    }
-
-    public ConnectionException(Throwable cause) {
-        super(cause);
-    }
-
-    public ConnectionException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/ConnectionKey.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-public interface ConnectionKey {
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Cursor.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-public interface Cursor {
-
-    public enum SortDirection {
-        ASCENDING(1),
-        DESCENDING(-1);
-
-        private int value;
-
-        private SortDirection(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-    }
-
-    boolean hasNext();
-
-    Chunk next();
-
-    Cursor sort(Key<?> orderBy, SortDirection direction);
-
-    Cursor limit(int i);
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Key.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-/**
- * A Key is used to refer to data in a {@link Chunk}.  It may also be a partial key to the
- * set of data represented by a {@link Chunk} in a category.
- */
-public class Key<T> {
-
-    // Keys used by most Categories.
-    public static final Key<Long> TIMESTAMP = new Key<>("timestamp", false);
-    public static final Key<String> AGENT_ID = new Key<>("agent-id", false);
-    public static final Key<Integer> VM_ID = new Key<>("vm-id", false);
-    public static final Key<String> WHERE = new Key<>("$where", false);
-
-    private String name;
-    private boolean isPartialCategoryKey;
-
-    public Key(String name, boolean isPartialCategoryKey) {
-        if (name == null || name.length() == 0) {
-            throw new IllegalArgumentException("A Key must have a non-null name of length >= 1.");
-        }
-        this.name = name;
-        this.isPartialCategoryKey = isPartialCategoryKey;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public boolean isPartialCategoryKey() {
-        return isPartialCategoryKey;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if ((o == null) || (o.getClass() != this.getClass())) {
-            return false;
-        }
-        Key<?> e = (Key<?>) o;
-        return (isPartialCategoryKey == e.isPartialCategoryKey()) &&
-            name.equals(e.getName());
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 1867;
-        hash = hash * 37 + (isPartialCategoryKey ? 0 : 1);
-        hash = hash * 37 + (name == null ? 0 : name.hashCode());
-        return hash;
-    }
-
-    @Override
-    public String toString() {
-        return "Key: " + name;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/MongoConnection.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-
-import com.mongodb.DB;
-import com.mongodb.Mongo;
-import com.mongodb.MongoException;
-import com.mongodb.MongoURI;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-class MongoConnection extends Connection {
-
-    private Mongo m = null;
-    private DB db = null;
-    private StartupConfiguration conf;
-
-    MongoConnection(StartupConfiguration conf) {
-        this.conf = conf;
-    }
-
-    @Override
-    public void connect() {
-        try {
-            createConnection();
-            /* the mongo java driver does not ensure this connection is actually working */
-            testConnection();
-        } catch (IOException | MongoException |
-                 NotImplementedException | IllegalArgumentException e)
-        {
-            fireChanged(ConnectionStatus.FAILED_TO_CONNECT);
-            throw new ConnectionException(e.getMessage(), e);
-        }
-        fireChanged(ConnectionStatus.CONNECTED);
-        connected = true;
-    }
-
-    @Override
-    public void disconnect() {
-        connected = false;
-        db = null;
-        if (m != null) {
-            m.close();
-        }
-    }
-
-    public DB getDB() {
-        return db;
-    }
-
-    private void createConnection() throws MongoException, UnknownHostException {
-        this.m = new Mongo(getMongoURI());
-        this.db = m.getDB(StorageConstants.THERMOSTAT_DB_NAME);
-    }
-
-    private MongoURI getMongoURI() {
-        MongoURI uri = new MongoURI(conf.getDBConnectionString());
-        return uri;
-    }
-
-    private void testConnection() {
-        db.getCollection("agent-config").getCount();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-
-class MongoCursor implements Cursor {
-
-    private DBCursor cursor;
-    private Category category;
-
-    MongoCursor(DBCursor cursor, Category category) {
-        this.cursor = cursor;
-        this.category = category;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return cursor.hasNext();
-    }
-
-    @Override
-    public Chunk next() {
-        DBObject next = cursor.next();
-        if (next == null) {
-            return null;
-        }
-        ChunkConverter converter = new ChunkConverter();
-        return converter.dbObjectToChunk(next, category);
-    }
-
-    @Override
-    public Cursor sort(Key<?> orderBy, SortDirection direction) {
-        if (!category.getKeys().contains(orderBy)) {
-            throw new IllegalArgumentException("Key not present in this Cursor's category.");
-        }   /* TODO: There are other possible error conditions.  Once there is API to configure
-             * indexing/optimization, we may want to prevent or log predictably bad performance
-             * sorting requests.
-             */
-        DBObject dbOrderBy = new BasicDBObject(orderBy.getName(), direction.getValue());
-        DBCursor sorted = cursor.sort(dbOrderBy);
-        return new MongoCursor(sorted, category);
-    }
-
-    @Override
-    public Cursor limit(int i) {
-        DBCursor limited = cursor.limit(i);
-        return new MongoCursor(limited, category);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.bson.BSONObject;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.WriteConcern;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
-import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
-
-/**
- * Implementation of the Storage interface that uses MongoDB to store the instrumentation data.
- *
- * In this implementation, each CATEGORY is given a distinct collection.
- */
-public class MongoStorage extends Storage {
-
-    public static final String KEY_AGENT_ID = "agent-id";
-    public static final String SET_MODIFIER = "$set";
-
-    private MongoConnection conn;
-    private DB db = null;
-    private Map<String, DBCollection> collectionCache = new HashMap<String, DBCollection>();
-
-    private UUID agentId = null;
-
-    public MongoStorage(StartupConfiguration conf) {
-        conn = new MongoConnection(conf);
-        conn.addListener(new ConnectionListener() {
-            @Override
-            public void changed(ConnectionStatus newStatus) {
-                switch (newStatus) {
-                case DISCONNECTED:
-                    db = null;
-                case CONNECTED:
-                    db = conn.getDB();
-                default:
-                    // ignore other status events
-                }
-            }
-        });
-    }
-
-    @Override
-    public Connection getConnection() {
-        return conn;
-    }
-
-    @Override
-    public void setAgentId(UUID agentId) {
-        this.agentId = agentId;
-    }
-
-    private BasicDBObject getAgentDBObject() {
-        return new BasicDBObject(KEY_AGENT_ID, agentId.toString());
-    }
-
-    @Override
-    public void putChunk(Chunk chunk) {
-        Category cat = chunk.getCategory();
-        DBCollection coll = getCachedCollection(cat.getName());
-        BasicDBObject toInsert = getAgentDBObject();
-        BasicDBObject replaceKey = null;
-        boolean replace = chunk.getReplace();
-        Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>();
-        Map<String, BasicDBObject> replaceKeyNestedParts = null;
-        if (replace) {
-            replaceKey = getAgentDBObject();
-            replaceKeyNestedParts = new HashMap<String, BasicDBObject>();
-        }
-        for (Key<?> key : cat.getKeys()) {
-            boolean isKey = key.isPartialCategoryKey();
-            String[] entryParts = key.getName().split("\\.");
-            if (entryParts.length == 2) {
-                BasicDBObject nested = nestedParts.get(entryParts[0]);
-                if (nested == null) {
-                    if (isKey) {
-                        throwMissingKey(key.getName());
-                    }
-                    nested = new BasicDBObject();
-                    nestedParts.put(entryParts[0], nested);
-                }
-                nested.append(entryParts[1], chunk.get(key));
-                if (replace && isKey) {
-                    BasicDBObject replaceKeyNested = replaceKeyNestedParts.get(entryParts[0]);
-                    if (replaceKeyNested == null) {
-                        replaceKeyNested = new BasicDBObject();
-                        replaceKeyNestedParts.put(entryParts[0], replaceKeyNested);
-                    }
-                    replaceKeyNested.append(entryParts[1], replaceKeyNested);
-                }
-            } else {
-                if (!key.equals(Key.AGENT_ID)) {
-                    String mongoKey = key.getName();
-                    Object value = chunk.get(key);
-                    if ((value == null) && isKey) {
-                        throwMissingKey(key.getName());
-                    }
-                    toInsert.append(mongoKey, value);
-                    if (replace && isKey) {
-                        replaceKey.append(mongoKey, value);
-                    }
-                }
-            }
-        }
-        for (Entry<String, BasicDBObject> entry: nestedParts.entrySet()) {
-            toInsert.append(entry.getKey(), entry.getValue());
-        }
-        if (replace) {
-            for (Entry<String, BasicDBObject> entry: replaceKeyNestedParts.entrySet()) {
-                replaceKey.append(entry.getKey(), entry.getValue());
-            }
-            coll.update(replaceKey, toInsert, true, false);
-        } else {
-            coll.insert(toInsert);
-        }
-    }
-
-    @Override
-    public void updateChunk(Chunk chunk) {
-        Category cat = chunk.getCategory();
-        DBCollection coll = getCachedCollection(cat.getName());
-        BasicDBObject toUpdate = new BasicDBObject();
-        BasicDBObject updateKey = getAgentDBObject();
-        Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>();
-        Map<String, BasicDBObject> updateKeyNestedParts = new HashMap<String, BasicDBObject>();
-        for (Key<?> key : cat.getKeys()) {
-            boolean isKey = key.isPartialCategoryKey();
-            String[] entryParts = key.getName().split("\\.");
-            if (entryParts.length == 2) {
-                BasicDBObject nested = nestedParts.get(entryParts[0]);
-                if (nested == null) {
-                    if (isKey) {
-                        throwMissingKey(key.getName());
-                    }
-                } else {
-                    if (isKey) {
-                        BasicDBObject updateKeyNested = updateKeyNestedParts.get(entryParts[0]);
-                        if (updateKeyNested == null) {
-                            updateKeyNested = new BasicDBObject();
-                            updateKeyNestedParts.put(entryParts[0], updateKeyNested);
-                        }
-                        updateKeyNested.append(entryParts[1], updateKeyNested);
-                    } else {
-                        nested.append(SET_MODIFIER, new BasicDBObject(entryParts[1], chunk.get(key)));
-                    }
-                }
-            } else {
-                String mongoKey = key.getName();
-                Object value = chunk.get(key);
-                if (value == null) {
-                    if (isKey) {
-                        throwMissingKey(key.getName());
-                    }
-                } else {
-                    if (isKey) {
-                        updateKey.append(mongoKey, value);
-                    } else {
-                        toUpdate.append(SET_MODIFIER, new BasicDBObject(mongoKey, value));
-                    }
-                }
-            }
-        }
-        for (Entry<String, BasicDBObject> entry: nestedParts.entrySet()) {
-            toUpdate.append(entry.getKey(), entry.getValue());
-        }
-        for (Entry<String, BasicDBObject> entry: updateKeyNestedParts.entrySet()) {
-            updateKey.append(entry.getKey(), entry.getValue());
-        }
-        coll.update(updateKey, toUpdate);
-    }
-
-    private void throwMissingKey(String keyName) {
-        throw new IllegalArgumentException("Attempt to insert chunk with incomplete partial key.  Missing: " + keyName);
-    }
-
-    private DBCollection getCachedCollection(String collName) {
-        DBCollection coll = collectionCache.get(collName);
-        if (coll == null && db.collectionExists(collName)) {
-            coll = db.getCollection(collName);
-            if (coll != null) {
-                collectionCache.put(collName, coll);
-            }
-        }
-        return coll;
-    }
-
-    private DBObject createConfigDBObject(AgentInformation agentInfo) {
-        BasicDBObject result = getAgentDBObject();
-        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_START_TIME, agentInfo.getStartTime());
-        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_STOP_TIME, agentInfo.getStopTime());
-        result.put(StorageConstants.KEY_AGENT_CONFIG_AGENT_ALIVE, agentInfo.isAlive());
-        
-        BasicDBObject backends = new BasicDBObject();
-        for (BackendInformation backend : agentInfo.getBackends()) {
-            backends.put(backend.getName(), createBackendConfigDBObject(backend));
-        }
-        result.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS, backends);
-        
-        return result;
-    }
-
-    private DBObject createBackendConfigDBObject(BackendInformation backend) {
-        BasicDBObject result = new BasicDBObject();
-        Map<String, String> configMap = backend.getConfiguration();
-        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NAME, backend.getName());
-        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_DESC, backend.getDescription());
-        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_ACTIVE, createBackendActiveDBObject(backend));
-        for (Entry<String, String> entry: configMap.entrySet()) {
-            result.append(entry.getKey(), entry.getValue());
-        }
-        return result;
-    }
-
-    private DBObject createBackendActiveDBObject(BackendInformation backend) {
-        BasicDBObject result = new BasicDBObject();
-        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_NEW, backend.isObserveNewJvm());
-        result.append(StorageConstants.KEY_AGENT_CONFIG_BACKEND_PIDS, new BasicDBList());
-        // TODO check which processes are already being listened to.
-        return result;
-    }
-
-    @Override
-    public void purge() {
-        BasicDBObject deleteKey = getAgentDBObject();
-        for (DBCollection coll : collectionCache.values()) {
-            coll.remove(deleteKey);
-        }
-    }
-    
-    @Override
-    public ConnectionKey createConnectionKey(Category category) {
-        // TODO: There is probably some better place to do this, perhaps related to the inner class
-        // idea mentioned below.
-        if (!db.collectionExists(category.getName())) {
-            db.createCollection(category.getName(), new BasicDBObject("capped", false));
-        }
-        // TODO: We want to return an instance of an inner class here that carries the actual connection
-        // and replace the collectionCache. For now this is good enough though.
-        return new ConnectionKey(){};
-    }
-
-    @Override
-    public Cursor findAll(Chunk query) {
-        Category cat = query.getCategory();
-        DBCollection coll = getCachedCollection(cat.getName());
-        ChunkConverter converter = new ChunkConverter();
-        DBObject obj = converter.chunkToDBObject(query);
-        DBCursor dbCursor = coll.find(obj);
-        return new MongoCursor(dbCursor, query.getCategory());
-    }
-
-    // TODO: This method is only temporary to enable tests, until we come up with a better design,
-    // in particular, the collection should be stored in the category itself. It must not be called
-    // from production code.
-    void mapCategoryToDBCollection(Category category, DBCollection coll) {
-        collectionCache.put(category.getName(), coll);
-    }
-
-    @Override
-    public Chunk find(Chunk query) {
-        Category cat = query.getCategory();
-        DBCollection coll = getCachedCollection(cat.getName());
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbResult = coll.findOne(converter.chunkToDBObject(query));
-        return dbResult == null ? null : converter.dbObjectToChunk(dbResult, cat);
-    }
-    
-    @Override
-    public Cursor findAllFromCategory(Category category) {
-        DBCollection coll = getCachedCollection(category.getName());
-        DBCursor dbCursor = coll.find();
-        return new MongoCursor(dbCursor, category);
-    }
-
-    @Override
-    public long getCount(Category category) {
-        DBCollection coll = getCachedCollection(category.getName());
-        if (coll != null) {
-            return coll.getCount();
-        }
-        return 0L;
-    }
-
-    // TODO these methods below belong in some DAO.
-    @Override
-    public void addAgentInformation(AgentInformation agentInfo) {
-        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
-        DBObject toInsert = createConfigDBObject(agentInfo);
-        /* cast required to disambiguate between putAll(BSONObject) and putAll(Map) */
-        toInsert.putAll((BSONObject) getAgentDBObject());
-        configCollection.insert(toInsert, WriteConcern.SAFE);
-    }
-    
-    @Override
-    public void updateAgentInformation(AgentInformation agentInfo) {
-        BasicDBObject queryObject = getAgentDBObject();
-
-        DBObject updated = createConfigDBObject(agentInfo);
-        updated.putAll((BSONObject) queryObject);
-
-        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
-        configCollection.update(queryObject, updated);
-    }
-
-    @Override
-    public void removeAgentInformation() {
-        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
-        BasicDBObject toRemove = getAgentDBObject();
-        configCollection.remove(toRemove, WriteConcern.NORMAL);
-    }
-
-    @Override
-    public String getBackendConfig(String backendName, String configurationKey) {
-        DBCollection configCollection = db.getCollection(StorageConstants.CATEGORY_AGENT_CONFIG);
-        BasicDBObject query = getAgentDBObject();
-        query.put(StorageConstants.KEY_AGENT_CONFIG_BACKENDS + "." + backendName, new BasicDBObject("$exists", true));
-        DBObject config = configCollection.findOne(query);
-        Object value = config.get(configurationKey);
-        if (value instanceof String) {
-            return (String) value;
-        }
-        return null;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/MongoStorageProvider.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-public class MongoStorageProvider implements StorageProvider {
-
-    private StartupConfiguration configuration;
-
-    public MongoStorageProvider(StartupConfiguration configuration) {
-        this.configuration = configuration;
-    }
-
-    @Override
-    public Storage createStorage() {
-        return new MongoStorage(configuration);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Storage.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import java.util.UUID;
-
-
-public abstract class Storage {
-
-    public abstract void setAgentId(UUID id);
-
-    public final void registerCategory(Category category) {
-        if (category.hasBeenRegistered()) {
-            throw new IllegalStateException("Category may only be associated with one backend.");
-        }
-        ConnectionKey connKey = createConnectionKey(category);
-        category.setConnectionKey(connKey);
-    }
-
-    public abstract Connection getConnection();
-
-    public abstract ConnectionKey createConnectionKey(Category category);
-
-    public abstract void putChunk(Chunk chunk);
-
-    public abstract void updateChunk(Chunk chunk);
-
-    /**
-     * Drop all data related to the currently running agent.
-     */
-    public abstract void purge();
-    
-    public abstract Cursor findAll(Chunk query);
-
-    public abstract Chunk find(Chunk query);
-
-    public abstract Cursor findAllFromCategory(Category category);
-    
-    public abstract long getCount(Category category);
-
-    // TODO these will move to appropriate DAO
-    public abstract void addAgentInformation(AgentInformation agentInfo);
-
-    public abstract void removeAgentInformation();
-
-    public abstract void updateAgentInformation(AgentInformation agentInfo);
-
-    /**
-     * @return {@code null} if the value is invalid or missing
-     */
-    public abstract String getBackendConfig(String backendName, String configurationKey);
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/StorageConstants.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-public class StorageConstants {
-    public static final String THERMOSTAT_DB_NAME = "thermostat";
-
-    public static final String CATEGORY_AGENT_CONFIG = "agent-config";
-
-    public static final String KEY_AGENT_CONFIG_BACKENDS = "backends";
-    public static final String KEY_AGENT_CONFIG_AGENT_START_TIME = "start-time";
-    public static final String KEY_AGENT_CONFIG_BACKEND_NAME = "name";
-    public static final String KEY_AGENT_CONFIG_BACKEND_DESC = "description";
-    public static final String KEY_AGENT_CONFIG_BACKEND_ACTIVE = "active";
-    public static final String KEY_AGENT_CONFIG_BACKEND_NEW = "new";
-    public static final String KEY_AGENT_CONFIG_BACKEND_PIDS = "pids";
-
-    public static final String KEY_AGENT_CONFIG_AGENT_ALIVE = "alive";
-    public static final String KEY_AGENT_CONFIG_AGENT_STOP_TIME = "stop-time";
-}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-public interface StorageProvider {
-
-    Storage createStorage();
-}
--- a/common/src/main/java/com/redhat/thermostat/common/tools/ApplicationException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.tools;
-
-public class ApplicationException extends Exception {
-
-    private static final long serialVersionUID = 5910852125476383826L;
-
-    public ApplicationException(String message) {
-        super(message);
-    }
-
-    public ApplicationException(Throwable cause) {
-        super(cause);
-    }
-
-    public ApplicationException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public ApplicationException(String message, Throwable cause,
-            boolean enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/tools/ApplicationState.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.tools;
-
-/**
- * Denotes the condition this application is in.
- */
-public enum ApplicationState {
-
-    NONE,
-    SUCCESS,
-    FAIL,
-    HELP,
-    START,
-    STOP;
-}
--- a/common/src/main/java/com/redhat/thermostat/common/tools/BasicCommand.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.tools;
-
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-/**
- * Common base class for all daemon and application
- */
-public abstract class BasicCommand implements Command {
-
-    private ActionNotifier<ApplicationState> notifier;
-    private boolean storageRequired;
-    
-    public BasicCommand() {
-        this.notifier = new ActionNotifier<>(this);
-    }
-
-    public ActionNotifier<ApplicationState> getNotifier() {
-        return notifier;
-    }
-
-    public abstract StartupConfiguration getConfiguration();
-
-    @Override
-    public boolean isStorageRequired() {
-        return storageRequired;
-    }
-
-    protected void setStorageRequired(boolean storageRequired) {
-        this.storageRequired = storageRequired;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/tools/ProcessStartException.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.tools;
-
-public class ProcessStartException extends ApplicationException {
-
-    private String commandName;
-
-    /**
-     * @param commandName the name of the program that failed to execute
-     * @param cause the original exception
-     */
-    public ProcessStartException(String commandName, Throwable cause) {
-        super("unable to execute " + commandName, cause);
-        this.commandName = commandName;
-    }
-
-    public String getCommandName() {
-        return commandName;
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/utils/DisplayableValues.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.utils;
-
-public class DisplayableValues {
-
-    private static final long BYTES_IN_KB = 1024;
-    private static final long BYTES_IN_MB = 1024*BYTES_IN_KB;
-    private static final long BYTES_IN_GB = 1024*BYTES_IN_MB;
-    private static final long BYTES_IN_TB = 1024*BYTES_IN_GB;
-    
-    public enum Scale {
-        B(1),
-        KiB(BYTES_IN_KB),
-        MiB(BYTES_IN_MB),
-        GiB(BYTES_IN_GB),
-        TiB(BYTES_IN_TB);
-
-        private long numBytes;
-
-        private Scale(long numBytes) {
-            this.numBytes = numBytes;
-        }
-
-        public long getNumBytes() {
-            return numBytes;
-        }
-
-        public static double convertTo(Scale scale, final long bytes) {
-            
-            return ((double) bytes) / ((double) scale.numBytes);
-        }
-        
-        public static double convertTo(Scale scale, final long bytes, long roundTo) {
-            
-            double result = ((double) bytes) / ((double) scale.numBytes);
-            result = ((double) Math.round(result * roundTo)) / roundTo;
-            
-            return result;
-        }
-
-        public static Scale getScale(final long bytes) {
-            if (bytes < BYTES_IN_KB) {
-                return Scale.B;
-            } else if (bytes < BYTES_IN_MB) {
-                return Scale.KiB;
-            } else if (bytes < BYTES_IN_GB) {
-                return Scale.MiB;
-            } else if (bytes < BYTES_IN_TB) {
-                return Scale.GiB;
-            } else {
-                return Scale.TiB;
-            }
-        }
-    }
-    
-    private static final String DOUBLE_FORMAT_STRING = "%.1f";
-
-    private DisplayableValues() {} // Not to be instantiated.
-
-    public static String[] bytes(final long bytes) {
-        if (bytes < BYTES_IN_KB) {
-            return new String[] { String.valueOf(bytes), Scale.B.name() };
-        } else if (bytes < BYTES_IN_MB) {
-            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_KB), Scale.KiB.name() };
-        } else if (bytes < BYTES_IN_GB) {
-            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_MB), Scale.MiB.name() };
-        } else if (bytes < BYTES_IN_TB) {
-            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_GB), Scale.GiB.name() };
-        } else {
-            return new String[] { String.format(DOUBLE_FORMAT_STRING, (double) bytes/BYTES_IN_TB), Scale.TiB.name() };
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/utils/LoggedExternalProcess.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.utils;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.tools.ApplicationException;
-import com.redhat.thermostat.common.tools.ProcessStartException;
-
-/**
- * Runs a process and logs it's output. The process's output and error streams
- * will be unreadable.
- */
-public class LoggedExternalProcess extends Thread {
-
-    private static final Logger logger = LoggingUtils.getLogger(LoggedExternalProcess.class);
-    private BufferedReader reader;
-    private String[] commands;
-
-    public LoggedExternalProcess(List<String> commands) {
-        this(commands.toArray(new String[0]));
-    }
-    
-    public LoggedExternalProcess(String[] commands) {
-        this.commands = Arrays.copyOf(commands, commands.length);
-        setDaemon(true);
-    }
-
-    public int runAndReturnResult() throws IOException, InterruptedException, ApplicationException{
-        Process p = runAndReturnProcess();
-        return p.waitFor();
-    }
-
-    public Process runAndReturnProcess() throws IOException, ApplicationException {
-        ProcessBuilder b = new ProcessBuilder(commands);
-        b.redirectErrorStream(true);
-        Process p = null;
-        try {
-            p = b.start();
-        } catch (IOException ioe) {
-            throw new ProcessStartException(commands[0], ioe);
-        }
-        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
-        this.start();
-        return p;
-    }
-
-    @Override
-    public void run() {
-        try {
-            String output = null;
-            while ((output = reader.readLine()) != null) {
-                logger.info(output);
-            }
-        } catch (IOException ex) {
-            logger.warning("Error reading external program output.");
-        } finally {
-            try {
-                reader.close();
-            } catch (IOException ex) {
-                logger.warning("Error closing stream from external program.");
-            }
-        }
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.utils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogManager;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.LogFormatter;
-import com.redhat.thermostat.common.config.ConfigUtils;
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-/**
- * A few helper functions to facilitate using loggers
- * <p>
- * It would be good idea to call {@link LogManager#readConfiguration()} with a
- * properties file that sets an appropriate value for ".level"
- */
-public final class LoggingUtils {
-
-    private static Logger root = null;
-    private static final String ROOTNAME = "com.redhat.thermostat";
-
-    private LoggingUtils() {
-        /* should not be instantiated */
-    }
-
-    /**
-     * Pretty much every one of the utility methods in this static class should call this method before doing anything else.
-     */
-    private static void ensureRootLogger() {
-        if (root == null) {
-            root = Logger.getLogger(ROOTNAME);
-            root.setUseParentHandlers(false);
-            for (Handler handler : root.getHandlers()) {
-                handler.setFormatter(new LogFormatter());
-                // This is workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4462908
-                handler.setLevel(Level.ALL);
-            }
-        }
-    }
-
-    /**
-     * Set the log level for the logger at the root of the "com.redhat.thermostat" namespace
-     * 
-     * @param level the minimum level at which logging statements should appear in the logs
-     */
-    public static void setGlobalLogLevel(Level level) {
-        ensureRootLogger();
-        root.setLevel(level);
-    }
-
-    /**
-     * Returns an appropriate logger to be used by class klass.
-     */
-    public static Logger getLogger(Class<?> klass) {
-        ensureRootLogger();
-        Logger logger = Logger.getLogger(klass.getPackage().getName());
-        logger.setLevel(null); // Will inherit from root logger
-        return logger;
-    }
-
-    /**
-     * Ensures log messages are written to the console as well
-     */
-    public static void useDevelConsole() {
-        ensureRootLogger();
-        ConsoleHandler handler = new ConsoleHandler();
-        handler.setFormatter(new LogFormatter());
-        // This is workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4462908
-        handler.setLevel(Level.ALL);
-        root.addHandler(handler);
-    }
-
-    public static void loadGlobalLoggingConfig() throws InvalidConfigurationException {
-        File thermostatEtcDir = new File(ConfigUtils.getThermostatHome(), "etc");
-        File loggingPropertiesFile = new File(thermostatEtcDir, "logging.properties");
-        if (loggingPropertiesFile.isFile()) {
-            readLoggingProperties(loggingPropertiesFile);
-        }
-    }
-
-    public static void loadUserLoggingConfig() throws InvalidConfigurationException {
-        File thermostatUserDir = new File(ConfigUtils.getThermostatUserHome());
-        File loggingPropertiesFile = new File(thermostatUserDir, "logging.properties");
-        if (loggingPropertiesFile.isFile()) {
-            readLoggingProperties(loggingPropertiesFile);
-        }
-    }
-
-    private static void readLoggingProperties(File loggingPropertiesFile)
-            throws InvalidConfigurationException {
-        try (FileInputStream fis = new FileInputStream(loggingPropertiesFile)){
-            LogManager.getLogManager().readConfiguration(fis);
-        } catch (SecurityException | IOException e) {
-            throw new InvalidConfigurationException("Could not read logging.properties", e);
-        }
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/common/utils/StringUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.utils;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-
-public class StringUtils {
-
-    private StringUtils() {
-        /* should not be instantiated */
-    }
-
-    public static InputStream toInputStream(String toConvert) {
-        try {
-            return new ByteArrayInputStream(toConvert.getBytes("UTF-8"));
-        } catch (UnsupportedEncodingException e) {
-            throw new IllegalStateException("UTF-8 not supported");
-        }
-    }
-
-    public static String quote(String toQuote) {
-        return "\"" + toQuote + "\"";
-    }
-
-    public static String repeat(String text, int times) {
-        StringBuilder builder = new StringBuilder(text.length() * times);
-        for (int i = 0; i < times; i++) {
-            builder.append(text);
-        }
-        return builder.toString();
-    }
-
-}
--- a/common/src/main/java/com/redhat/thermostat/test/Bug.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.AppContextSetup;
-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 CommandRegistry commandRegistry = new TestCommandRegistry();
-
-    private AppContextSetup appContextSetup = new AppContextSetup() {
-
-        @Override
-        public void setupAppContext(String dbUrl) {
-            // We do nothing for now.
-        }
-    };
-
-    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 commandRegistry;
-            }
-
-            @Override
-            public AppContextSetup getAppContextSetup() {
-                return TestCommandContextFactory.this.getAppContextSetup();
-            }
-
-            @Override
-            public CommandContextFactory getCommandContextFactory() {
-                return TestCommandContextFactory.this;
-            }
-            
-        };
-    }
-
-    @Override
-    public CommandRegistry getCommandRegistry() {
-        return commandRegistry;
-    }
-
-    @Override
-    protected AppContextSetup getAppContextSetup() {
-        return appContextSetup;
-    }
-
-    public String getOutput() {
-        return new String(out.toByteArray());
-    }
-
-    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/src/main/java/com/redhat/thermostat/test/TestCommandRegistry.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.Dictionary;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.common.cli.BaseCommandRegistry;
-import com.redhat.thermostat.common.cli.Command;
-
-class TestCommandRegistry extends BaseCommandRegistry {
-
-    private static class TestServiceRegistration implements ServiceRegistration {
-
-        @Override
-        public ServiceReference getReference() {
-            // Nothing to do for now.
-            return null;
-        }
-
-        @Override
-        public void setProperties(Dictionary properties) {
-            // Nothing to do for now.
-        }
-
-        @Override
-        public void unregister() {
-            // Nothing to do for now.
-        }
-
-    }
-
-    private Map<String, Command> commands = new HashMap<>();
-
-    public Command getCommand(String name) {
-        return commands.get(name);
-    }
-
-    public Collection<Command> getRegisteredCommands() {
-        return commands.values();
-    }
-
-    protected ServiceRegistration registerCommand(Command cmd) {
-        commands.put(cmd.getName(), cmd);
-        return new TestServiceRegistration();
-    }
-
-    @Override
-    public void unregisterCommands() {
-        commands.clear();
-    }
-}
--- a/common/src/main/java/com/redhat/thermostat/test/TestTimerFactory.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.redhat.thermostat.common.cli.HelpCommand
--- a/common/src/test/java/com/redhat/thermostat/common/ActionEventTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-public class ActionEventTest {
-
-    private enum TestId {
-        TEST_ID1, TEST_ID2
-    }
-
-    @Test
-    public void testGetActionId() {
-        ActionEvent<TestId> viewActionEvent = new ActionEvent<>(new Object(), TestId.TEST_ID1);
-        assertEquals(TestId.TEST_ID1, viewActionEvent.getActionId());
-    }
-
-    @Test(expected=NullPointerException.class)
-    public void verifyThatNullActionIdThrowsNPE() {
-        new ActionEvent<>(new Object(), null);
-    }
-
-    @Test
-    public void testEqualsEquals() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID1);
-        assertTrue(action1.equals(action2));
-    }
-
-    @Test
-    public void testEqualsDifferentSource() {
-        Object source1 = new Object();
-        Object source2 = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source1, TestId.TEST_ID1);
-        ActionEvent<TestId> action2 = new ActionEvent<>(source2, TestId.TEST_ID1);
-        assertFalse(action1.equals(action2));
-    }
-
-    @Test
-    public void testEqualsDifferentId() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID2);
-        assertFalse(action1.equals(action2));
-    }
-
-    @Test
-    public void testEqualsNull() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        assertFalse(action1.equals(null));
-    }
-
-    @Test
-    public void testEqualsSame() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        assertTrue(action1.equals(action1));
-    }
-
-    @Test
-    public void testEqualsOtherType() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        assertFalse(action1.equals("test"));
-    }
-
-    @Test
-    public void testHashCodeEquals() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        ActionEvent<TestId> action2 = new ActionEvent<>(source, TestId.TEST_ID1);
-        assertTrue(action1.hashCode() == action2.hashCode());
-    }
-
-    @Test
-    public void testHashCodeStaysSame() {
-        Object source = new Object();
-        ActionEvent<TestId> action1 = new ActionEvent<>(source, TestId.TEST_ID1);
-        int hashCode1 = action1.hashCode();
-        int hashCode2 = action1.hashCode();
-        assertTrue(hashCode1 == hashCode2);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/ActionNotifierTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
-import org.junit.Test;
-
-public class ActionNotifierTest {
-
-    private enum TestId {
-        TEST_ID1
-    }
-
-
-    @Test
-    public void verifySingleListenerNotification() {
-
-        Object source = new Object();
-        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
-        @SuppressWarnings("unchecked")
-        ActionListener<TestId> listener = mock(ActionListener.class);
-        viewActionSupport.addActionListener(listener);
-
-        viewActionSupport.fireAction(TestId.TEST_ID1);
-
-        verify(listener).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
-    }
-
-    @Test
-    public void verifyMultiListenerNotification() {
-
-        Object source = new Object();
-        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
-        @SuppressWarnings("unchecked")
-        ActionListener<TestId> listener1 = mock(ActionListener.class);
-        @SuppressWarnings("unchecked")
-        ActionListener<TestId> listener2 = mock(ActionListener.class);
-        @SuppressWarnings("unchecked")
-        ActionListener<TestId> listener3 = mock(ActionListener.class);
-        viewActionSupport.addActionListener(listener1);
-        viewActionSupport.addActionListener(listener2);
-        viewActionSupport.addActionListener(listener3);
-
-        viewActionSupport.fireAction(TestId.TEST_ID1);
-
-        verify(listener1).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
-        verify(listener2).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
-        verify(listener3).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
-    }
-
-    @Test
-    public void verifyRemoveListener() {
-        Object source = new Object();
-        ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
-        @SuppressWarnings("unchecked")
-        ActionListener<TestId> listener = mock(ActionListener.class);
-        viewActionSupport.addActionListener(listener);
-        viewActionSupport.removeActionListener(listener);
-
-        viewActionSupport.fireAction(TestId.TEST_ID1);
-
-        verify(listener, never()).actionPerformed(new ActionEvent<TestId>(source, TestId.TEST_ID1));
-    }
-
-    @Test
-    public void testRemoveWhileNotifying() {
-        Object source = new Object();
-        final ActionNotifier<TestId> viewActionSupport = new ActionNotifier<TestId>(source);
-        final boolean[] listenerCalled = new boolean[] { false };
-
-        final ActionListener<TestId> listener = new ActionListener<TestId>() {
-
-            @Override
-            public void actionPerformed(ActionEvent<TestId> viewActionEvent) {
-                viewActionSupport.removeActionListener(this);
-                listenerCalled[0] = true;
-            }
-            
-        };
-        viewActionSupport.addActionListener(listener);
-
-        viewActionSupport.fireAction(TestId.TEST_ID1);
-
-        assertTrue(listenerCalled[0]);
-
-        listenerCalled[0] = false;
-        viewActionSupport.fireAction(TestId.TEST_ID1);
-        assertFalse(listenerCalled[0]);
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/ActivatorTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-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.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.HelpCommand;
-import com.redhat.thermostat.common.cli.Launcher;
-
-public class ActivatorTest {
-
-    @Test
-    public void testRegisterServices() throws Exception {
-        final Map<ServiceRegistration, Object> regs = new HashMap<>();
-        BundleContext bCtx = mock(BundleContext.class);
-        when(bCtx.registerService(anyString(), any(), any(Dictionary.class))).then(new Answer<ServiceRegistration>() {
-
-            @Override
-            public ServiceRegistration answer(InvocationOnMock invocation) throws Throwable {
-                ServiceRegistration reg = mock(ServiceRegistration.class);
-                when(reg.getReference()).thenReturn(mock(ServiceReference.class));
-                regs.put(reg, invocation.getArguments()[1]);
-                return reg;
-            }
-        });
-        when(bCtx.getService(isA(ServiceReference.class))).then(new Answer<Object>() {
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                ServiceReference ref = (ServiceReference) invocation.getArguments()[0];
-                for (Entry<ServiceRegistration,Object> registration: regs.entrySet()) {
-                    if (registration.getKey().getReference().equals(ref)) {
-                        return registration.getValue();
-                    }
-                }
-                return null;
-            }
-        });
-
-        Activator activator = new Activator();
-
-        activator.start(bCtx);
-
-        Hashtable<String, Object> props = new Hashtable<>();
-        props.put(Command.NAME, "help");
-        verify(bCtx).registerService(eq(Command.class.getName()), isA(HelpCommand.class), eq(props));
-
-        verify(bCtx).registerService(eq(Launcher.class.getName()), isA(Launcher.class), any(Dictionary.class));
-
-        activator.stop(bCtx);
-
-        for (ServiceRegistration reg : regs.keySet()) {
-            verify(reg).unregister();
-        }
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/TestUtils.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.util.Properties;
-import java.util.Random;
-
-public class TestUtils {
-
-    public static int getProcessId() {
-        String name = ManagementFactory.getRuntimeMXBean().getName();
-        String pidPart = name.split("@")[0];
-        return Integer.parseInt(pidPart);
-    }
-
-    public static boolean isLinux() {
-        return (System.getProperty("os.name").toLowerCase().contains("linux"));
-    }
-        
-    public static String setupAgentConfigs() throws IOException {
-        // need to create dummy config files for the tests
-        Random random = new Random();
-
-        String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar +
-                Math.abs(random.nextInt()) + File.separatorChar;
-
-        System.setProperty("THERMOSTAT_HOME", tmpDir);
-        File agent = new File(tmpDir, "agent");
-        agent.mkdirs();
-
-        File tmpConfigs = new File(agent, "agent.properties");
-
-        new File(agent, "run").mkdirs();
-        new File(agent, "logs").mkdirs();
-
-        File backends = new File(tmpDir, "backends");
-        File system = new File(backends, "system");
-        system.mkdirs();
-        
-        Properties props = new Properties();            
-
-        props.setProperty("BACKENDS", "system");
-        props.setProperty("LOG_LEVEL", "WARNING");
-
-        props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties");
-
-        // now write the configs for the backends
-        tmpConfigs = new File(system, "backend.properties");
-        props = new Properties();
-        props.setProperty("BACKEND_CLASS",
-                          "com.redhat.thermostat.backend.system.SystemBackend");
-        props.setProperty("DESCRIPTION",
-                          "fluff backend for tests");
-        props.setProperty("VENDOR",
-                          "Red Hat, Inc.");
-        props.setProperty("VERSION",
-                          "1.0");
-        props.store(new FileOutputStream(tmpConfigs), "thermostat system backend properties");
-        
-        return tmpDir;
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/ThreadPoolTimerFactoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import java.util.concurrent.TimeUnit;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.test.Bug;
-
-public class ThreadPoolTimerFactoryTest {
-
-    private static final long DELAY = 200;
-
-    private Timer timer;
-
-    private ThreadGroup threadGroup;
-
-    private TimerFactory timerFactory;
-
-    @Before
-    public void setUp() {
-        threadGroup = new ThreadGroup("test");
-        timerFactory = new ThreadPoolTimerFactory(1, threadGroup);
-        timer = timerFactory.createTimer();
-    }
-
-    @After
-    public void tearDown() {
-        
-        timer = null;
-        timerFactory.shutdown();
-        timerFactory = null;
-        threadGroup = null;
-    }
-
-    @Test
-    public void testDefault() throws InterruptedException {
-        Runnable action = mock(Runnable.class);
-        timer.setAction(action);
-        timer.start();
-        Thread.sleep(DELAY / 2);
-        verify(action).run();
-    }
-
-    @Test
-    public void testNullAction() {
-        timer.setAction(null);
-        timer.start();
-        // Good when no NPE is thrown.
-    }
-
-    @Test
-    public void testDefaultWithDelay() throws InterruptedException {
-        Runnable action = mock(Runnable.class);
-        timer.setAction(action);
-        timer.setInitialDelay(DELAY);
-        timer.start();
-        Thread.sleep(DELAY / 2);
-        verify(action, never()).run();
-        Thread.sleep(DELAY);
-        verify(action).run();
-        Thread.sleep(DELAY);
-        verify(action).run();
-    }
-
-    @Test
-    public void testTimeUnitSecond() throws InterruptedException {
-        Runnable action = mock(Runnable.class);
-        timer.setAction(action);
-        timer.setInitialDelay(1);
-        timer.setTimeUnit(TimeUnit.SECONDS);
-        timer.start();
-        Thread.sleep(500);
-        verify(action, never()).run();
-        Thread.sleep(1000);
-        verify(action).run();
-        Thread.sleep(1000);
-        verify(action).run();
-    }
-
-    @Test(expected=NullPointerException.class)
-    public void testNullType() throws InterruptedException {
-        timer.setSchedulingType(null);
-    }
-
-    @Test
-    public void testWithFixedRate() throws InterruptedException {
-        Runnable action = mock(Runnable.class);
-        doAnswer(new Answer<Void>() {
-
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                // Wait a little less than delay to
-                // 1. Verify more easily that the duration of the task does not push back the activation of next task.
-                // 2. Not congest the timer thread (which would happen if we take >= DELAY).
-                Thread.sleep(DELAY * 9 / 10 );
-                return null;
-            }
-            
-        }).when(action).run();
-        timer.setAction(action);
-        timer.setInitialDelay(DELAY);
-        timer.setDelay(DELAY);
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-        timer.start();
-        Thread.sleep(DELAY / 2);
-        verify(action, never()).run();
-        Thread.sleep(DELAY);
-        verify(action).run();
-        Thread.sleep(DELAY);
-        verify(action, times(2)).run();
-        timer.stop();
-        Thread.sleep(DELAY);
-        verify(action, times(2)).run();
-    }
-
-    @Test
-    public void testStopWithoutStart() {
-        timer.stop();
-        // Good when no exception is thrown.
-    }
-
-    @Test
-    public void testWithFixedDelay() throws InterruptedException {
-        Runnable action = mock(Runnable.class);
-        doAnswer(new Answer<Void>() {
-
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Thread.sleep(DELAY / 2);
-                return null;
-            }
-            
-        }).when(action).run();
-        timer.setAction(action);
-        timer.setInitialDelay(DELAY);
-        timer.setDelay(DELAY);
-        timer.setSchedulingType(SchedulingType.FIXED_DELAY);
-        timer.start();
-        Thread.sleep(DELAY / 2);
-        verify(action, never()).run();
-        Thread.sleep(DELAY);
-        verify(action).run();
-        Thread.sleep(DELAY / 2);
-        verify(action).run();
-        Thread.sleep(DELAY);
-        verify(action, times(2)).run();
-        Thread.sleep(DELAY / 2);
-        verify(action, times(2)).run();
-        timer.stop();
-        Thread.sleep(DELAY);
-        verify(action, times(2)).run();
-    }
-
-    @Bug(id="957",
-         summary="Thermostat GUI doesn't exit when closed, needs killing",
-         url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=957")
-    @Test
-    public void verifyShutdownKillsThreads() throws InterruptedException {
-
-        Runnable action = mock(Runnable.class);
-        timer.setAction(action);
-        timer.setInitialDelay(DELAY / 2);
-        timer.start();
-
-        assertTrue(threadGroup.activeCount() > 0);
-
-        timerFactory.shutdown();
-
-        Thread.sleep(DELAY);
-
-        assertEquals(0, threadGroup.activeCount());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/appctx/ApplicationContextTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.appctx;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.DAOFactory;
-
-public class ApplicationContextTest {
-
-    @Before
-    public void setUp() {
-        ApplicationContext.reset();
-    }
-
-    @After
-    public void tearDown() {
-        ApplicationContext.reset();
-    }
-
-    @Test
-    public void verifyGetInstanceNotNull() {
-        ApplicationContext ctx = ApplicationContext.getInstance();
-        assertNotNull(ctx);
-    }
-
-    @Test
-    public void  testDAOFactorySetGet() {
-        DAOFactory daoFactory = mock(DAOFactory.class);
-        ApplicationContext ctx = ApplicationContext.getInstance();
-        ctx.setDAOFactory(daoFactory);
-
-        DAOFactory actual1 = ctx.getDAOFactory();
-        assertSame(daoFactory, actual1);
-    }
-
-    @Test
-    public void  verifyDAOFactoryIsNullWhenNotInitialized() {
-        ApplicationContext ctx = ApplicationContext.getInstance();
-
-        DAOFactory actual = ctx.getDAOFactory();
-        assertNull(actual);
-    }
-
-    @Test
-    public void  verifyDAOFactoryStaysSame() {
-        DAOFactory daoFactory = mock(DAOFactory.class);
-        ApplicationContext ctx = ApplicationContext.getInstance();
-        ctx.setDAOFactory(daoFactory);
-
-        ApplicationContext ctx2 = ApplicationContext.getInstance();
-        DAOFactory actual2 = ctx2.getDAOFactory();
-        assertSame(daoFactory, actual2);
-    }
-
-    @Test
-    public void  testTimerFactorySetGet() {
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        ApplicationContext ctx = ApplicationContext.getInstance();
-        ctx.setTimerFactory(timerFactory);
-
-        TimerFactory actual1 = ctx.getTimerFactory();
-        assertSame(timerFactory, actual1);
-    }
-
-    @Test
-    public void  verifyTimerFactoryIsNullWhenNotInitialized() {
-        ApplicationContext ctx = ApplicationContext.getInstance();
-
-        TimerFactory actual = ctx.getTimerFactory();
-        assertNull(actual);
-    }
-
-    @Test
-    public void  verifyTimerFactoryStaysSame() {
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        ApplicationContext ctx = ApplicationContext.getInstance();
-        ctx.setTimerFactory(timerFactory);
-
-        ApplicationContext ctx2 = ApplicationContext.getInstance();
-        TimerFactory actual2 = ctx2.getTimerFactory();
-        assertSame(timerFactory, actual2);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/CommandContextFactoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.mockito.Mockito.mock;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-
-public class CommandContextFactoryTest {
-
-    private BundleContext bundleContext;
-    private CommandContextFactory cmdCtxFactory;
-
-    @Before
-    public void setUp() {
-        bundleContext = mock(BundleContext.class);
-        cmdCtxFactory = new CommandContextFactory(bundleContext);
-    }
-
-    @After
-    public void tearDown() {
-        cmdCtxFactory = null;
-        bundleContext = null;
-    }
-
-    @Test
-    public void testCreateContext() {
-        Arguments args = mock(Arguments.class);
-        CommandContext ctx = cmdCtxFactory.createContext(args);
-        assertSame(args, ctx.getArguments());
-        assertNotNull(ctx.getAppContextSetup());
-        assertSame(cmdCtxFactory, ctx.getCommandContextFactory());
-        assertSame(cmdCtxFactory.getCommandRegistry(), ctx.getCommandRegistry());
-        assertSame(cmdCtxFactory.getConsole(), ctx.getConsole());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/CommandExceptionTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.CommandException;
-
-public class CommandExceptionTest {
-
-    @Test
-    public void testDefaultConstructor() {
-        CommandException ce = new CommandException();
-        verifyMessageAndCause(ce, null, null);
-    }
-
-    @Test
-    public void testMessageConstructor() {
-        CommandException ce = new CommandException("test");
-        verifyMessageAndCause(ce, "test", null);
-    }
-
-    @Test
-    public void testCauseConstructor() {
-        Exception cause = new Exception("test fluff");
-        CommandException ce = new CommandException(cause);
-        verifyMessageAndCause(ce, "java.lang.Exception: test fluff", cause);
-    }
-
-    @Test
-    public void testCombinedConstructor() {
-        Exception cause = new Exception("test fluff");
-        CommandException ce = new CommandException("test", cause);
-        verifyMessageAndCause(ce, "test", cause);
-    }
-
-    private void verifyMessageAndCause(CommandException ce, String message, Exception cause) {
-        assertEquals(message, ce.getMessage());
-        assertSame(cause, ce.getCause());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/CommandLineArgumentsParserTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class CommandLineArgumentsParserTest {
-
-    private CommandLineArgumentsParser parser;
-
-    private ArgumentSpec arg3;
-
-    @Before
-    public void setUp() {
-        parser = new CommandLineArgumentsParser();
-
-        ArgumentSpec arg1 = mock(ArgumentSpec.class);
-        when(arg1.getName()).thenReturn("test1");
-        when(arg1.getShortOption()).thenReturn("t");
-        when(arg1.isRequired()).thenReturn(true);
-
-        ArgumentSpec arg2 = mock(ArgumentSpec.class);
-        when(arg2.getName()).thenReturn("test2");
-        when(arg2.isRequired()).thenReturn(false);
-
-        arg3 = mock(ArgumentSpec.class);
-        when(arg3.getName()).thenReturn("test3");
-        when(arg3.isRequired()).thenReturn(false);
-        when(arg3.isUsingAdditionalArgument()).thenReturn(true);
-
-        parser.addArguments(Arrays.asList(arg1, arg2, arg3));
-    }
-
-    @After
-    public void tearDown() {
-       parser = null; 
-       arg3 = null;
-    }
-
-    @Test
-    public void testSimpleArgs() throws CommandLineArgumentParseException {
-        Arguments args = parser.parse(new String[] { "--test1", "--test2" });
-
-        assertTrue(args.hasArgument("test1"));
-        assertEquals(null, args.getArgument("test1"));
-        assertTrue(args.hasArgument("test2"));
-        assertEquals(null, args.getArgument("test2"));
-    }
-
-    @Test
-    public void testShortArgs() throws CommandLineArgumentParseException {
-        Arguments args = parser.parse(new String[] { "-t", "--test2" });
-
-        assertTrue(args.hasArgument("test1"));
-        assertTrue(args.hasArgument("t"));
-        assertEquals(null, args.getArgument("test1"));
-        assertTrue(args.hasArgument("test2"));
-        assertEquals(null, args.getArgument("test2"));
-    }
-
-    @Test(expected=CommandLineArgumentParseException.class)
-    public void testNoMatchingArgs() throws CommandLineArgumentParseException {
-        parser.parse(new String[] { "--test1", "--no-match" });
-    }
-
-    @Test
-    public void testMissingRequiredArgument() throws CommandLineArgumentParseException {
-        try {
-          parser.parse(new String[] { "--test2" });
-          fail();
-        } catch (CommandLineArgumentParseException ex) {
-            String msg = ex.getMessage();
-            assertEquals("Missing required option: -t", msg);
-        }
-    }
-
-    @Test
-    public void testMissingRequiredArguments() throws CommandLineArgumentParseException {
-        ArgumentSpec arg4 = mock(ArgumentSpec.class);
-        when(arg4.getName()).thenReturn("test4");
-        when(arg4.isRequired()).thenReturn(true);
-        parser.addArguments(Arrays.asList(arg4));
-
-        try {
-          parser.parse(new String[] { "--test2" });
-          fail();
-        } catch (CommandLineArgumentParseException ex) {
-            String msg = ex.getMessage();
-            assertEquals("Missing required options: -t, --test4", msg);
-        }
-    }
-
-    @Test
-    public void testArgumentWithAdditionalArgument() throws CommandLineArgumentParseException {
-        Arguments args = parser.parse(new String[] { "--test3", "parameter", "--test1" } );
-        assertTrue(args.hasArgument("test3"));
-        assertEquals("parameter", args.getArgument("test3"));
-        assertTrue(args.hasArgument("test1"));
-    }
-
-    @Test(expected=CommandLineArgumentParseException.class)
-    public void testMissingAdditionalArgument() throws CommandLineArgumentParseException {
-        parser.parse(new String[] { "--test3" });
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/CommandRegistryImplTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Hashtable;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-public class CommandRegistryImplTest {
-
-    private CommandRegistryImpl commandRegistry;
-
-    private BundleContext bundleContext;
-
-    @Before
-    public void setUp() {
-        bundleContext = mock(BundleContext.class);
-        commandRegistry = new CommandRegistryImpl(bundleContext);
-    }
-
-    @After
-    public void tearDown() {
-        bundleContext = null;
-    }
-
-    @Test
-    public void testRegisterCommands() {
-        Command cmd1 = mock(Command.class);
-        when(cmd1.getName()).thenReturn("test1");
-        Command cmd2 = mock(Command.class);
-        when(cmd2.getName()).thenReturn("test2");
-
-        commandRegistry.registerCommands(Arrays.asList(cmd1, cmd2));
-
-        Hashtable<String,Object> props1 = new Hashtable<>();
-        props1.put(Command.NAME, "test1");
-        Hashtable<String,Object> props2 = new Hashtable<>();
-        props2.put(Command.NAME, "test2");
-        verify(bundleContext).registerService(Command.class.getName(), cmd1, props1);
-        verify(bundleContext).registerService(Command.class.getName(), cmd2, props2);
-
-        verifyNoMoreInteractions(bundleContext);
-
-    }
-
-    @Test
-    public void testUnregisterCommand() {
-        Command cmd1 = mock(Command.class);
-        when(cmd1.getName()).thenReturn("test1");
-        Command cmd2 = mock(Command.class);
-        when(cmd2.getName()).thenReturn("test2");
-
-        ServiceReference cmd1Reference = mock(ServiceReference.class);
-        ServiceReference cmd2Reference = mock(ServiceReference.class);
-
-        ServiceRegistration cmd1Reg = mock(ServiceRegistration.class);
-        when(cmd1Reg.getReference()).thenReturn(cmd1Reference);
-        ServiceRegistration cmd2Reg = mock(ServiceRegistration.class);
-        when(cmd2Reg.getReference()).thenReturn(cmd2Reference);
-
-        Hashtable<String,String> props1 = new Hashtable<>();
-        props1.put(Command.NAME, cmd1.getName());
-        Hashtable<String,String> props2 = new Hashtable<>();
-        props2.put(Command.NAME, cmd2.getName());
-
-        when(bundleContext.registerService(Command.class.getName(), cmd1, props1)).thenReturn(cmd1Reg);
-        when(bundleContext.registerService(Command.class.getName(), cmd2, props2)).thenReturn(cmd2Reg);
-
-        commandRegistry.registerCommands(Arrays.asList(cmd1, cmd2));
-
-        verify(bundleContext).registerService(Command.class.getName(), cmd1, props1);
-        verify(bundleContext).registerService(Command.class.getName(), cmd2, props2);
-
-        when(bundleContext.getService(eq(cmd1Reference))).thenReturn(cmd1);
-        when(bundleContext.getService(eq(cmd2Reference))).thenReturn(cmd2);
-
-        commandRegistry.unregisterCommands();
-
-        verify(bundleContext).getService(cmd1Reference);
-        verify(cmd1).disable();
-        verify(cmd1Reg).unregister();
-        verify(bundleContext).getService(cmd2Reference);
-        verify(cmd2).disable();
-        verify(cmd2Reg).unregister();
-
-        verifyNoMoreInteractions(bundleContext);
-    }
-
-    @Test
-    public void testGetCommand() throws InvalidSyntaxException {
-        ServiceReference ref1 = mock(ServiceReference.class);
-        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[] { ref1 });
-        Command cmd1 = mock(Command.class);
-        when(bundleContext.getService(ref1)).thenReturn(cmd1);
-
-        Command cmd = commandRegistry.getCommand("test1");
-
-        assertSame(cmd1, cmd);
-    }
-
-    @Test
-    public void testNotRegisteredCommand() throws InvalidSyntaxException {
-        ServiceReference ref1 = mock(ServiceReference.class);
-        Command cmd1 = mock(Command.class);
-        when(bundleContext.getService(ref1)).thenReturn(cmd1);
-
-        Command cmd = commandRegistry.getCommand("test1");
-
-        assertNull(cmd);
-    }
-
-    @Test
-    public void testNotRegisteredCommandEmptyList() throws InvalidSyntaxException {
-        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[0]);
-
-        Command cmd = commandRegistry.getCommand("test1");
-
-        assertNull(cmd);
-    }
-
-    @Test
-    public void testDoubleRegisteredCommand() throws InvalidSyntaxException {
-        ServiceReference ref1 = mock(ServiceReference.class);
-        ServiceReference ref2 = mock(ServiceReference.class);
-        Command cmd1 = mock(Command.class);
-        Command cmd2 = mock(Command.class);
-        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenReturn(new ServiceReference[] { ref1, ref2 });
-        when(bundleContext.getService(ref1)).thenReturn(cmd1);
-        when(bundleContext.getService(ref2)).thenReturn(cmd2);
-
-        Command cmd = commandRegistry.getCommand("test1");
-
-        assertSame(cmd1, cmd);
-    }
-
-    @Test(expected=InternalError.class)
-    public void testGetCommandInvalidSyntax() throws InvalidSyntaxException {
-        when(bundleContext.getServiceReferences(Command.class.getName(), "(&(objectclass=*)(COMMAND_NAME=test1))")).thenThrow(new InvalidSyntaxException("test", "test"));
-
-        commandRegistry.getCommand("test1");
-    }
-
-    @Test
-    public void testRegisteredCommands() throws InvalidSyntaxException {
-        ServiceReference ref1 = mock(ServiceReference.class);
-        ServiceReference ref2 = mock(ServiceReference.class);
-        Command cmd1 = mock(Command.class);
-        Command cmd2 = mock(Command.class);
-        when(bundleContext.getServiceReferences(Command.class.getName(), null)).thenReturn(new ServiceReference[] { ref1, ref2 });
-        when(bundleContext.getService(ref1)).thenReturn(cmd1);
-        when(bundleContext.getService(ref2)).thenReturn(cmd2);
-
-        Collection<Command> cmds = commandRegistry.getRegisteredCommands();
-
-        assertEquals(2, cmds.size());
-        assertTrue(cmds.contains(cmd1));
-        assertTrue(cmds.contains(cmd2));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/CommonCommandOptionsTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collection;
-
-import org.junit.Test;
-
-public class CommonCommandOptionsTest {
-
-    @Test
-    public void verifyStorageCommandAddsDbUrlOption() {
-        TestCommand cmd = new TestCommand("test1");
-        cmd.setStorageRequired(true);
-
-        CommonCommandOptions commonOpts = new CommonCommandOptions();
-        Collection<ArgumentSpec> cmdOpts = commonOpts.getAcceptedOptionsFor(cmd);
-
-        assertTrue(cmdOpts.contains(new SimpleArgumentSpec("dbUrl", "d", "the URL of the storage to connect to", false, true)));
-    }
-
-    @Test
-    public void verifyLogLevelOption() {
-        TestCommand cmd = new TestCommand("test1");
-
-        CommonCommandOptions commonOpts = new CommonCommandOptions();
-        Collection<ArgumentSpec> cmdOpts = commonOpts.getAcceptedOptionsFor(cmd);
-
-        assertTrue(cmdOpts.contains(new SimpleArgumentSpec("logLevel", "log level", false, true)));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/HelpCommandTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class HelpCommandTest {
-
-    private TestCommandContextFactory  ctxFactory;
-
-    @Before
-    public void setUp() {
-
-        ctxFactory = new TestCommandContextFactory();
-
-
-    }
-
-    @After
-    public void tearDown() {
-        ctxFactory = null;
-    }
-
-    @Test
-    public void testName() {
-        HelpCommand cmd = new HelpCommand();
-        assertEquals("help", cmd.getName());
-    }
-
-    @Test
-    public void verifyHelpNoArgPrintsListOfCommandsNoCommands() {
-
-        HelpCommand cmd = new HelpCommand();
-        Arguments args = mock(Arguments.class);
-        cmd.run(ctxFactory.createContext(args));
-        String expected = "list of commands:\n\n";
-        String actual = ctxFactory.getOutput();
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void verifyHelpNoArgPrintsListOfCommands2Commands() {
-
-        TestCommand cmd1 = new TestCommand("test1");
-        cmd1.setDescription("test command 1");
-        TestCommand cmd2 = new TestCommand("test2longname");
-        cmd2.setDescription("test command 2");
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1, cmd2));
-
-        HelpCommand cmd = new HelpCommand();
-        Arguments args = mock(Arguments.class);
-        cmd.run(ctxFactory.createContext(args));
-        String expected = "list of commands:\n\n"
-                        + " test1         test command 1\n"
-                        + " test2longname test command 2\n";
-        String actual = ctxFactory.getOutput();
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void verifyHelpKnownCmdPrintsCommandUsage() {
-        TestCommand cmd1 = new TestCommand("test1");
-        String usage = "test usage command 1";
-        cmd1.setUsage(usage);
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
-
-        HelpCommand cmd = new HelpCommand();
-        Arguments args = mock(Arguments.class);
-        when(args.getNonOptionArguments()).thenReturn(Arrays.asList("test1"));
-        cmd.run(ctxFactory.createContext(args));
-
-        String actual = ctxFactory.getOutput();
-        assertEquals("usage: test1 [--logLevel <arg>]\ntest usage command 1\n     --logLevel <arg>    log level\n", actual);
-    }
-
-    @Test
-    public void verifyHelpKnownStorageCmdPrintsCommandUsageWithDbUrl() {
-        TestCommand cmd1 = new TestCommand("test1");
-        String usage = "test usage command 1";
-        cmd1.setUsage(usage);
-        cmd1.setStorageRequired(true);
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
-
-        HelpCommand cmd = new HelpCommand();
-        Arguments args = mock(Arguments.class);
-        when(args.getNonOptionArguments()).thenReturn(Arrays.asList("test1"));
-        cmd.run(ctxFactory.createContext(args));
-
-        String actual = ctxFactory.getOutput();
-        assertEquals("usage: test1 [-d <arg>] [--logLevel <arg>]\ntest usage command 1\n  -d,--dbUrl <arg>       the URL of the storage to connect to\n     --logLevel <arg>    log level\n", actual);
-    }
-
-    @Test
-    public void verifyHelpUnknownCmdPrintsSummaries() {
-        TestCommand cmd1 = new TestCommand("test1");
-        cmd1.setUsage("test usage command 1");
-        cmd1.setDescription("test command 1");
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1));
-
-        HelpCommand cmd = new HelpCommand();
-        Arguments args = mock(Arguments.class);
-        cmd.run(ctxFactory.createContext(args));
-
-        String expected = "list of commands:\n\n"
-                        + " test1         test command 1\n";
-        String actual = ctxFactory.getOutput();
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testDescription() {
-        HelpCommand cmd = new HelpCommand();
-        assertEquals("show help for a given command or help overview", cmd.getDescription());
-    }
-
-    @Test
-    public void testUsage() {
-        HelpCommand cmd = new HelpCommand();
-        String expected = "show help for a given command or help overview";
-
-        assertEquals(expected, cmd.getUsage());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/LauncherTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-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.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.config.ClientPreferences;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.test.TestTimerFactory;
-
-public class LauncherTest {
-
-    private static class TestCmd1 implements TestCommand.Handle {
-
-        @Override
-        public void run(CommandContext ctx) {
-            Arguments args = ctx.getArguments();
-            ctx.getConsole().getOutput().print(args.getArgument("arg1") + ", " + args.getArgument("arg2"));
-        }
-
-        @Override
-        public void stop() { /* N0-OP */ }
-
-    }
-
-    private static class TestCmd2 implements TestCommand.Handle {
-        @Override
-        public void run(CommandContext ctx) {
-            Arguments args = ctx.getArguments();
-            ctx.getConsole().getOutput().print(args.getArgument("arg4") + ": " + args.getArgument("arg3"));
-        }
-
-        @Override
-        public void stop() {
-            /* NO-OP */
-        }
-    }
-
-    private TestCommandContextFactory  ctxFactory;
-    private AppContextSetup appContextSetup;
-    private BundleContext bundleContext;
-    private TestTimerFactory timerFactory;
-
-    @Before
-    public void setUp() {
-
-        ApplicationContextUtil.resetApplicationContext();
-        timerFactory = new TestTimerFactory();
-        ApplicationContext.getInstance().setTimerFactory(timerFactory);
-        setupCommandContextFactory();
-
-        TestCommand cmd1 = new TestCommand("test1", new TestCmd1());
-        SimpleArgumentSpec arg1 = new SimpleArgumentSpec();
-        arg1.setName("arg1");
-        arg1.setUsingAdditionalArgument(true);
-        SimpleArgumentSpec arg2 = new SimpleArgumentSpec();
-        arg2.setName("arg2");
-        arg2.setUsingAdditionalArgument(true);
-        cmd1.addArguments(arg1, arg2);
-        cmd1.setDescription("description 1");
-        TestCommand cmd2 = new TestCommand("test2", new TestCmd2());
-        SimpleArgumentSpec arg3 = new SimpleArgumentSpec();
-        arg3.setName("arg3");
-        arg3.setUsingAdditionalArgument(true);
-        SimpleArgumentSpec arg4 = new SimpleArgumentSpec();
-        arg4.setName("arg4");
-        arg4.setUsingAdditionalArgument(true);
-        cmd2.addArguments(arg3, arg4);
-        cmd2.setDescription("description 2");
-
-        TestCommand cmd3 = new TestCommand("test3");
-        cmd3.setStorageRequired(true);
-        cmd3.setDescription("description 3");
-
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(cmd1, cmd2, cmd3, new HelpCommand()));
-
-    }
-
-    private void setupCommandContextFactory() {
-        appContextSetup = mock(AppContextSetup.class);
-        Bundle sysBundle = mock(Bundle.class);
-        bundleContext = mock(BundleContext.class);
-        when(bundleContext.getBundle(0)).thenReturn(sysBundle);
-        ctxFactory = new TestCommandContextFactory(bundleContext) {
-            @Override
-            protected AppContextSetup getAppContextSetup() {
-                return appContextSetup;
-            }
-        };
-    }
-
-
-    @After
-    public void tearDown() {
-        appContextSetup = null;
-        ctxFactory = null;
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @Test
-    public void testMain() {
-        runAndVerifyCommand(new String[] {"test1", "--arg1", "Hello", "--arg2", "World"}, "Hello, World");
-
-        ctxFactory.reset();
-
-        runAndVerifyCommand(new String[] {"test2", "--arg3", "Hello", "--arg4", "World"}, "World: Hello");
-    }
-
-    @Test
-    public void testMainNoArgs() {
-        String expected = "list of commands:\n\n"
-                        + " help          show help for a given command or help overview\n"
-                        + " test1         description 1\n"
-                        + " test2         description 2\n"
-                        + " test3         description 3\n";
-        runAndVerifyCommand(new String[0], expected);
-    }
-
-    @Test
-    public void verifySetLogLevel() {
-        runAndVerifyCommand(new String[] {"test1", "--logLevel", "WARNING", "--arg1", "Hello", "--arg2", "World"}, "Hello, World");
-        Logger globalLogger = Logger.getLogger("com.redhat.thermostat");
-        assertEquals(Level.WARNING, globalLogger.getLevel());
-    }
-
-    @Test
-    public void testMainBadCommand1() {
-        String expected = "unknown command '--help'\n"
-            + "list of commands:\n\n"
-            + " help          show help for a given command or help overview\n"
-            + " test1         description 1\n"
-            + " test2         description 2\n"
-            + " test3         description 3\n";
-        runAndVerifyCommand(new String[] {"--help"}, expected);
-    }
-
-    @Test
-    public void testMainBadCommand2() {
-        String expected = "unknown command '-help'\n"
-            + "list of commands:\n\n"
-            + " help          show help for a given command or help overview\n"
-            + " test1         description 1\n"
-            + " test2         description 2\n"
-            + " test3         description 3\n";
-        runAndVerifyCommand(new String[] {"-help"}, expected);
-    }
-
-    @Test
-    public void testMainBadCommand3() {
-        String expected = "unknown command 'foobarbaz'\n"
-            + "list of commands:\n\n"
-            + " help          show help for a given command or help overview\n"
-            + " test1         description 1\n"
-            + " test2         description 2\n"
-            + " test3         description 3\n";
-        runAndVerifyCommand(new String[] {"foobarbaz"}, expected);
-    }
-
-    @Test
-    public void testMainBadCommand4() {
-        String expected = "unknown command 'foo'\n"
-            + "list of commands:\n\n"
-            + " help          show help for a given command or help overview\n"
-            + " test1         description 1\n"
-            + " test2         description 2\n"
-            + " test3         description 3\n";
-        runAndVerifyCommand(new String[] {"foo",  "--bar", "baz"}, expected);
-    }
-
-    @Test
-    public void testMainExceptionInCommand() {
-        TestCommand errorCmd = new TestCommand("error", new TestCommand.Handle() {
-
-            @Override
-            public void run(CommandContext ctx) throws CommandException {
-                throw new CommandException("test error");
-            }
-
-            @Override
-            public void stop() { /* NO-OP */ }
-        });
-        ctxFactory.getCommandRegistry().registerCommands(Arrays.asList(errorCmd));
-
-        new LauncherImpl(ctxFactory).run(new String[] { "error" });
-        assertEquals("test error\n", ctxFactory.getError());
-
-    }
-
-    private void runAndVerifyCommand(String[] args, String expected) {
-        new LauncherImpl(ctxFactory).run(args);
-        assertEquals(expected, ctxFactory.getOutput());
-        assertTrue(timerFactory.isShutdown());
-    }
-
-    @Test
-    public void verifyStorageCommandSetsUpDAOFactory() {
-        new LauncherImpl(ctxFactory).run(new String[] { "test3" , "--dbUrl", "mongo://fluff:12345" });
-        verify(appContextSetup).setupAppContext("mongo://fluff:12345");
-    }
-
-    public void verifyPrefsAreUsed() {
-        ClientPreferences prefs = mock(ClientPreferences.class);
-        when(prefs.getConnectionUrl()).thenReturn("mongo://fluff:12345");
-        LauncherImpl l = new LauncherImpl(ctxFactory);
-        l.setPreferences(prefs);
-        l.run(new String[] { "test3" });
-        verify(appContextSetup).setupAppContext("mongo://fluff:12345");
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentSpecTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class SimpleArgumentSpecTest {
-
-    private SimpleArgumentSpec spec;
-    private SimpleArgumentSpec other;
-
-    @Before
-    public void setUp() {
-        spec = new SimpleArgumentSpec();
-        other = new SimpleArgumentSpec();
-    }
-
-    @After
-    public void tearDown() {
-        spec = null;
-        other = null;
-    }
-
-    @Test
-    public void testName() {
-        spec.setName("test1");
-        assertEquals("test1", spec.getName());
-        spec.setName("test2");
-        assertEquals("test2", spec.getName());
-    }
-
-    @Test
-    public void testDescription() {
-        spec.setDescription("test1");
-        assertEquals("test1", spec.getDescription());
-        spec.setDescription("test2");
-        assertEquals("test2", spec.getDescription());
-    }
-
-    @Test
-    public void testRequired() {
-        spec.setRequired(true);
-        assertTrue(spec.isRequired());
-        spec.setRequired(false);
-        assertFalse(spec.isRequired());
-    }
-
-    @Test
-    public void testUsesAdditionalArgument() {
-        spec.setUsingAdditionalArgument(true);
-        assertTrue(spec.isUsingAdditionalArgument());
-        spec.setUsingAdditionalArgument(false);
-        assertFalse(spec.isUsingAdditionalArgument());
-    }
-
-    @Test
-    public void testShortOption() {
-        spec.setShortOption("test1");
-        assertEquals("test1", spec.getShortOption());
-        spec.setShortOption("test2");
-        assertEquals("test2", spec.getShortOption());
-    }
-
-    @Test
-    public void testEquals() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        assertTrue(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsUnequalName() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        other.setName("fluff");
-
-        assertFalse(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsUnequalDescription() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        other.setDescription("fluff");
-
-        assertFalse(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsUnequalUsingAdditionalArgument() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        other.setUsingAdditionalArgument(false);
-
-        assertFalse(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsUnequalRequired() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        other.setRequired(false);
-
-        assertFalse(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsUnequalShortOption() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        other.setShortOption("fluff");
-
-        assertFalse(spec.equals(other));
-    }
-
-    @Test
-    public void testEqualsNull() {
-        prepareSpecForEqualsTest(spec);
-
-        assertFalse(spec.equals(null));
-    }
-
-    @Test
-    public void testHashCode() {
-        prepareSpecForEqualsTest(spec);
-        prepareSpecForEqualsTest(other);
-
-        assertEquals(spec.hashCode(), other.hashCode());
-    }
-
-    private void prepareSpecForEqualsTest(SimpleArgumentSpec spec) {
-        spec.setName("test");
-        spec.setDescription("description");
-        spec.setUsingAdditionalArgument(true);
-        spec.setRequired(true);
-        spec.setShortOption("shortOption");
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/SimpleArgumentsTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.SimpleArguments;
-
-public class SimpleArgumentsTest {
-
-    private SimpleArguments args;
-
-    @Before
-    public void setUp() {
-        args = new SimpleArguments();
-    }
-
-    @After
-    public void tearDown() {
-        args = null;
-    }
-
-    @Test
-    public void testSimpleArgs() {
-        args.addArgument("fluff", "fluffor");
-        assertTrue(args.hasArgument("fluff"));
-        assertEquals("fluffor", args.getArgument("fluff"));
-        assertFalse(args.hasArgument("foo"));
-        assertNull(args.getArgument("bar"));
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/cli/TestCommand.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.cli;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-
-class TestCommand implements Command {
-
-    private String name;
-    private Handle handle;
-    private String description;
-    private String usage;
-    private boolean storageRequired;
-
-    private List<ArgumentSpec> arguments = new LinkedList<ArgumentSpec>();
-
-    static interface Handle {
-        public void run(CommandContext ctx) throws CommandException;
-        public void stop();
-    }
-
-    TestCommand(String name) {
-        this(name, null);
-    }
-
-    TestCommand(String name, Handle r) {
-        this.name = name;
-        this.handle = r;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        if (handle != null) {
-            handle.run(ctx);
-        }
-    }
-
-    @Override
-    public void disable() {
-        if (handle != null) {
-            handle.stop();
-        }
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    void setDescription(String desc) {
-        description = desc;
-    }
-
-    @Override
-    public String getUsage() {
-        return usage;
-    }
-
-    void setUsage(String usage) {
-        this.usage = usage;
-    }
-
-    @Override
-    public Collection<ArgumentSpec> getAcceptedArguments() {
-        return arguments;
-    }
-
-    void addArguments(ArgumentSpec... arguments) {
-        this.arguments.addAll(Arrays.asList(arguments));
-    }
-
-    public boolean isStorageRequired() {
-        return storageRequired;
-    }
-
-    void setStorageRequired(boolean storageRequired) {
-        this.storageRequired = storageRequired;
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/config/ClientPreferencesTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-import static org.junit.Assert.assertEquals;
-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.util.prefs.Preferences;
-
-import org.junit.Test;
-
-public class ClientPreferencesTest {
-
-    @Test
-    public void testGetConnectionUrl() {
-
-        Preferences prefs = mock(Preferences.class);
-        when(prefs.get(eq("connection-url"), any(String.class))).thenReturn("mock-value");
-
-        ClientPreferences clientPrefs = new ClientPreferences(prefs);
-        String value = clientPrefs.getConnectionUrl();
-
-        assertEquals("mock-value", value);
-        verify(prefs).get(eq("connection-url"), any(String.class));
-    }
-
-    @Test
-    public void testSetConnectionUrl() {
-
-        Preferences prefs = mock(Preferences.class);
-
-        ClientPreferences clientPrefs = new ClientPreferences(prefs);
-        clientPrefs.setConnectionUrl("test");
-
-        verify(prefs).put(eq("connection-url"), eq("test"));
-    }
-
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/config/ConfigUtilsTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.config;
-
-import java.io.File;
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class ConfigUtilsTest {
-    
-    @Before
-    public void setUp() throws IOException {
-        System.setProperty("THERMOSTAT_HOME", "/tmp/");
-    }
-    
-    @Test
-    public void testLocations() throws InvalidConfigurationException, IOException {
-        String path = System.getProperty("THERMOSTAT_HOME");
-        char s = File.separatorChar;
-        
-        Assert.assertEquals(path, ConfigUtils.getThermostatHome());
-        
-        Assert.assertEquals(path + "agent" + s + "agent.properties",
-                            ConfigUtils.getAgentConfigurationFile().getCanonicalPath());
-        Assert.assertEquals(path + "backends", ConfigUtils.getBackendsBaseDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "client", ConfigUtils.getClientConfigurationDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "client" + s + "cli-history", ConfigUtils.getHistoryFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage", ConfigUtils.getStorageBaseDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "db.properties",
-                            ConfigUtils.getStorageConfigurationFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "db",
-                ConfigUtils.getStorageDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "logs" + s + "db.log",
-                ConfigUtils.getStorageLogFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "run" + s + "db.pid",
-                ConfigUtils.getStoragePidFile().getCanonicalPath());
-        
-        Assert.assertEquals(path + "backends" + s + "system" + s + "backend.properties",
-                            ConfigUtils.getBackendPropertyFile("system").getCanonicalPath());
-        
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class CpuStatConverterTest {
-
-    @Test
-    public void testToChunk() {
-        CpuStat stat = new CpuStat(10, 5.0, 10.0, 15.0);
-        Chunk chunk = new CpuStatConverter().toChunk(stat);
-        assertNotNull(chunk);
-        assertEquals("cpu-stats", chunk.getCategory().getName());
-        assertEquals((Long) 10L, chunk.get(Key.TIMESTAMP));
-        assertEquals(5.0, chunk.get(CpuStatDAO.cpu5LoadKey), 0.001);
-        assertEquals(10.0, chunk.get(CpuStatDAO.cpu10LoadKey), 0.001);
-        assertEquals(15.0, chunk.get(CpuStatDAO.cpu15LoadKey), 0.001);
-    }
-
-    @Test
-    public void testFromChunk() {
-        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, 10L);
-        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
-        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
-        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
-        CpuStat stat = new CpuStatConverter().fromChunk(chunk);
-        assertNotNull(stat);
-        assertEquals(10L, stat.getTimeStamp());
-        assertEquals(5.0, stat.getLoad5(), 0.001);
-        assertEquals(10.0, stat.getLoad10(), 0.001);
-        assertEquals(15.0, stat.getLoad15(), 0.001);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-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.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class CpuStatDAOTest {
-
-    @Test
-    public void testCategory() {
-        assertEquals("cpu-stats", CpuStatDAO.cpuStatCategory.getName());
-        Collection<Key<?>> keys = CpuStatDAO.cpuStatCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<Double>("5load", false)));
-        assertTrue(keys.contains(new Key<Double>("10load", false)));
-        assertTrue(keys.contains(new Key<Double>("15load", false)));
-        assertEquals(5, keys.size());
-    }
-
-    @Test
-    public void testGetLatestCpuStats() {
-
-        Cursor cursor = mock(Cursor.class);
-        Storage storage = mock(Storage.class);
-        HostRef hostRef = mock(HostRef.class);
-        CpuStatDAO dao = new CpuStatDAOImpl(storage);
-
-        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
-        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
-        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
-
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        List<CpuStat> cpuStats = dao.getLatestCpuStats(hostRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, cpuStats.size());
-        CpuStat stat = cpuStats.get(0);
-        assertEquals(1234L, stat.getTimeStamp());
-        assertEquals(5.0, stat.getLoad5(), 0.001);
-        assertEquals(10.0, stat.getLoad10(), 0.001);
-        assertEquals(15.0, stat.getLoad15(), 0.001);
-    }
-
-    @Test
-    public void testGetLatestCpuStatsTwice() {
-
-        Cursor cursor = mock(Cursor.class);
-        Storage storage = mock(Storage.class);
-        HostRef hostRef = mock(HostRef.class);
-
-        CpuStatDAO dao = new CpuStatDAOImpl(storage);
-
-        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
-        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
-        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
-
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        dao.getLatestCpuStats(hostRef);
-        dao.getLatestCpuStats(hostRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        assertEquals("this.timestamp > 1234", arg.getValue().get(Key.WHERE));
-    }
-
-    @Test
-    public void testPutCpuStat() {
-        Storage storage = mock(Storage.class);
-        CpuStat stat = new CpuStat(1, 5.0, 15.0, 10.0);
-        CpuStatDAO dao = new CpuStatDAOImpl(storage);
-        dao.putCpuStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(CpuStatDAO.cpuStatCategory, chunk.getCategory());
-        assertEquals((Long) 1L, chunk.get(Key.TIMESTAMP));
-        assertEquals((Double) 5.0, chunk.get(CpuStatDAO.cpu5LoadKey));
-        assertEquals((Double) 15.0, chunk.get(CpuStatDAO.cpu10LoadKey));
-        assertEquals((Double) 10.0, chunk.get(CpuStatDAO.cpu15LoadKey));
-    }
-
-    @Test
-    public void testGetCount() {
-        Storage storage = mock(Storage.class);
-        when(storage.getCount(any(Category.class))).thenReturn(5L);
-        CpuStatDAO dao = new CpuStatDAOImpl(storage);
-        Long count = dao.getCount();
-        assertEquals((Long) 5L, count);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class HostInfoConverterTest {
-
-    @Test
-    public void testHostInfoToChunk() {
-        HostInfo info = new HostInfo("a-host", "an-os", "a-kernel", "a-cpu", 9, 99);
-
-        Chunk chunk = new HostInfoConverter().toChunk(info);
-
-        assertEquals("host-info", chunk.getCategory().getName());
-        assertEquals("a-host", chunk.get(new Key<String>("hostname", true)));
-        assertEquals("an-os", chunk.get(new Key<String>("os_name", false)));
-        assertEquals("a-kernel", chunk.get(new Key<String>("os_kernel", false)));
-        assertEquals("a-cpu", chunk.get(new Key<String>("cpu_model", false)));
-        assertEquals((Integer)9, chunk.get(new Key<Integer>("cpu_num", false)));
-        assertEquals((Long) 99L, chunk.get(new Key<Long>("memory_total", false)));
-    }
-
-    @Test
-    public void testChunktoHostInfo() {
-        final String HOST_NAME = "a host name";
-        final String OS_NAME = "some os";
-        final String OS_KERNEL = "some kernel";
-        final String CPU_MODEL = "some cpu that runs fast";
-        final int CPU_NUM = -1;
-        final long MEMORY_TOTAL = 0xCAFEBABEl;
-
-
-        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        chunk.put(HostInfoDAO.hostNameKey, HOST_NAME);
-        chunk.put(HostInfoDAO.osNameKey, OS_NAME);
-        chunk.put(HostInfoDAO.osKernelKey, OS_KERNEL);
-        chunk.put(HostInfoDAO.cpuModelKey, CPU_MODEL);
-        chunk.put(HostInfoDAO.cpuCountKey, CPU_NUM);
-        chunk.put(HostInfoDAO.hostMemoryTotalKey, MEMORY_TOTAL);
-
-        HostInfo info = new HostInfoConverter().fromChunk(chunk);
-        assertNotNull(info);
-        assertEquals(HOST_NAME, info.getHostname());
-        assertEquals(OS_NAME, info.getOsName());
-        assertEquals(OS_KERNEL, info.getOsKernel());
-        assertEquals(CPU_MODEL, info.getCpuModel());
-        assertEquals(CPU_NUM, info.getCpuCount());
-        assertEquals(MEMORY_TOTAL, info.getTotalMemory());
-
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collection;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.times;
-
-import com.redhat.thermostat.common.model.HostInfo;
-import com.redhat.thermostat.common.storage.AgentInformation;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class HostInfoDAOTest {
-
-    private static final String HOST_NAME = "a host name";
-    private static final String OS_NAME = "some os";
-    private static final String OS_KERNEL = "some kernel";
-    private static final String CPU_MODEL = "some cpu that runs fast";
-    private static final int CPU_NUM = -1;
-    private static final long MEMORY_TOTAL = 0xCAFEBABEl;
-
-    @Test
-    public void testCategory() {
-        assertEquals("host-info", HostInfoDAO.hostInfoCategory.getName());
-        Collection<Key<?>> keys = HostInfoDAO.hostInfoCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<String>("hostname", true)));
-        assertTrue(keys.contains(new Key<String>("os_name", false)));
-        assertTrue(keys.contains(new Key<String>("os_kernel", false)));
-        assertTrue(keys.contains(new Key<String>("cpu_model", false)));
-        assertTrue(keys.contains(new Key<Integer>("cpu_num", false)));
-        assertTrue(keys.contains(new Key<Long>("memory_total", false)));
-        assertEquals(7, keys.size());
-    }
-
-    @Test
-    public void testGetHostInfo() {
-
-        Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        chunk.put(HostInfoDAO.hostNameKey, HOST_NAME);
-        chunk.put(HostInfoDAO.osNameKey, OS_NAME);
-        chunk.put(HostInfoDAO.osKernelKey, OS_KERNEL);
-        chunk.put(HostInfoDAO.cpuModelKey, CPU_MODEL);
-        chunk.put(HostInfoDAO.cpuCountKey, CPU_NUM);
-        chunk.put(HostInfoDAO.hostMemoryTotalKey, MEMORY_TOTAL);
-
-        Storage storage = mock(Storage.class);
-        when(storage.find(any(Chunk.class))).thenReturn(chunk);
-
-        HostInfo info = new HostInfoDAOImpl(storage).getHostInfo(new HostRef("some uid", HOST_NAME));
-        assertNotNull(info);
-        assertEquals(HOST_NAME, info.getHostname());
-        assertEquals(OS_NAME, info.getOsName());
-        assertEquals(OS_KERNEL, info.getOsKernel());
-        assertEquals(CPU_MODEL, info.getCpuModel());
-        assertEquals(CPU_NUM, info.getCpuCount());
-        assertEquals(MEMORY_TOTAL, info.getTotalMemory());
-    }
-
-    @Test
-    public void testGetHostsSingleHost() {
-
-        Storage storage = setupStorageForSingleHost();
-
-        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
-        Collection<HostRef> hosts = hostsDAO.getHosts();
-
-        assertEquals(1, hosts.size());
-        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
-    }
-
-    private Storage setupStorageForSingleHost() {
-
-        Chunk hostConfig = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig.put(HostInfoDAO.hostNameKey, "fluffhost1");
-        hostConfig.put(Key.AGENT_ID, "123");
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(hostConfig);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-        
-        return storage;
-    }
-
-    @Test
-    public void testGetHosts3Hosts() {
-
-        Storage storage = setupStorageFor3Hosts();
-
-        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
-        Collection<HostRef> hosts = hostsDAO.getHosts();
-
-        assertEquals(3, hosts.size());
-        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
-        assertTrue(hosts.contains(new HostRef("456", "fluffhost2")));
-        assertTrue(hosts.contains(new HostRef("789", "fluffhost3")));
-    }
-
-    private Storage setupStorageFor3Hosts() {
-
-        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
-        hostConfig1.put(Key.AGENT_ID, "123");
-        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
-        hostConfig2.put(Key.AGENT_ID, "456");
-        Chunk hostConfig3 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig3.put(HostInfoDAO.hostNameKey, "fluffhost3");
-        hostConfig3.put(Key.AGENT_ID, "789");
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(hostConfig1).thenReturn(hostConfig2).thenReturn(hostConfig3);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-        
-        return storage;
-    }
-
-    @Test
-    public void testPutHostInfo() {
-        Storage storage = mock(Storage.class);
-        HostInfo info = new HostInfo(HOST_NAME, OS_NAME, OS_KERNEL, CPU_MODEL, CPU_NUM, MEMORY_TOTAL);
-        HostInfoDAO dao = new HostInfoDAOImpl(storage);
-        dao.putHostInfo(info);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(HostInfoDAO.hostInfoCategory, chunk.getCategory());
-        assertEquals(HOST_NAME, chunk.get(HostInfoDAO.hostNameKey));
-        assertEquals(OS_NAME, chunk.get(HostInfoDAO.osNameKey));
-        assertEquals(OS_KERNEL, chunk.get(HostInfoDAO.osKernelKey));
-        assertEquals(CPU_MODEL, chunk.get(HostInfoDAO.cpuModelKey));
-        assertEquals((Integer) CPU_NUM, chunk.get(HostInfoDAO.cpuCountKey));
-        assertEquals((Long) MEMORY_TOTAL, chunk.get(HostInfoDAO.hostMemoryTotalKey));
-    }
-
-    @Test
-    public void testGetCount() {
-        Storage storage = mock(Storage.class);
-        when(storage.getCount(any(Category.class))).thenReturn(5L);
-        HostInfoDAO dao = new HostInfoDAOImpl(storage);
-        Long count = dao.getCount();
-        assertEquals((Long) 5L, count);
-    }
-    
-    @Test
-    public void getAliveHostSingle() {
-        Storage storage = setupStorageForSingleAliveHost();
-
-        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
-        Collection<HostRef> hosts = hostsDAO.getAliveHosts();
-
-        // cursor 3 from the above storage should not be used
-        assertEquals(1, hosts.size());
-        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
-        verify(storage, times(2)).findAll(any(Chunk.class));
-    }
-    
-    private Storage setupStorageForSingleAliveHost() {
-        
-        // agents
-        
-        Chunk agentConfig1 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
-        agentConfig1.put(Key.AGENT_ID, "123");
-        agentConfig1.put(AgentInformation.AGENT_ALIVE_KEY, true);
-        
-        Cursor cursor1 = mock(Cursor.class);
-        when(cursor1.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor1.next()).thenReturn(agentConfig1);
-        
-        // hosts
-        
-        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
-        hostConfig1.put(Key.AGENT_ID, "123");
-        
-        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
-        hostConfig2.put(Key.AGENT_ID, "456");
-        
-        Cursor cursor2 = mock(Cursor.class);
-        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor2.next()).thenReturn(hostConfig1);
-
-        Cursor cursor3 = mock(Cursor.class);
-        when(cursor3.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor3.next()).thenReturn(hostConfig2);
-        
-        // storage
-        
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1).thenReturn(cursor2).thenReturn(cursor3);
-        
-        return storage;
-    }
-    
-    @Test
-    public void getAliveHost3() {
-        Storage storage = setupStorageForSingleAliveHost3();
-
-        HostInfoDAO hostsDAO = new HostInfoDAOImpl(storage);
-        Collection<HostRef> hosts = hostsDAO.getAliveHosts();
-
-        // cursor 3 from the above storage should not be used
-        assertEquals(3, hosts.size());
-        assertTrue(hosts.contains(new HostRef("123", "fluffhost1")));
-        assertTrue(hosts.contains(new HostRef("456", "fluffhost2")));
-        assertTrue(hosts.contains(new HostRef("678", "fluffhost3")));
-        verify(storage, times(4)).findAll(any(Chunk.class));
-    }
-    
-    private Storage setupStorageForSingleAliveHost3() {
-        
-        // agents
-        
-        Chunk agentConfig1 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
-        agentConfig1.put(Key.AGENT_ID, "123");
-        agentConfig1.put(AgentInformation.AGENT_ALIVE_KEY, true);
-        
-        Chunk agentConfig2 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
-        agentConfig2.put(Key.AGENT_ID, "456");
-        agentConfig2.put(AgentInformation.AGENT_ALIVE_KEY, true);
-        
-        Chunk agentConfig3 = new Chunk(AgentInformation.AGENT_INFO_CATEGORY, false);
-        agentConfig3.put(Key.AGENT_ID, "678");
-        agentConfig3.put(AgentInformation.AGENT_ALIVE_KEY, true);
-        
-        Cursor cursor1 = mock(Cursor.class);
-        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor1.next()).thenReturn(agentConfig1).thenReturn(agentConfig2).thenReturn(agentConfig3);
-        
-        // hosts
-        
-        Chunk hostConfig1 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig1.put(HostInfoDAO.hostNameKey, "fluffhost1");
-        hostConfig1.put(Key.AGENT_ID, "123");
-        
-        Chunk hostConfig2 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig2.put(HostInfoDAO.hostNameKey, "fluffhost2");
-        hostConfig2.put(Key.AGENT_ID, "456");
-        
-        Chunk hostConfig3 = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        hostConfig3.put(HostInfoDAO.hostNameKey, "fluffhost3");
-        hostConfig3.put(Key.AGENT_ID, "678");
-        
-        Cursor cursor2 = mock(Cursor.class);
-        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor2.next()).thenReturn(hostConfig1);
-
-        Cursor cursor3 = mock(Cursor.class);
-        when(cursor3.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor3.next()).thenReturn(hostConfig2);
-        
-        Cursor cursor4 = mock(Cursor.class);
-        when(cursor4.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor4.next()).thenReturn(hostConfig3);
-        
-        // storage
-        
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1).
-                                                thenReturn(cursor2).
-                                                thenReturn(cursor3).
-                                                thenReturn(cursor4);
-        
-        return storage;
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-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 static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
-
-public class HostLatestPojoListGetterTest {
-    private static final String AGENT_ID = "agentid";
-    private static final String HOSTNAME = "host.example.com";
-    private static final String CATEGORY_NAME = "hostcategory";
-    // Make this one static so we don't get IllegalStateException from trying
-    // to make category of same name while running tests in same classloader.
-    private static final Category cat =  new Category(CATEGORY_NAME);
-
-    private static long t1 = 1;
-    private static long t2 = 5;
-    private static long t3 = 10;
-
-    private static double load5_1 = 2.0;
-    private static double load5_2 = 6.0;
-    private static double load5_3 = 11.0;
-
-    private static double load10_1 = 3.0;
-    private static double load10_2 = 7.0;
-    private static double load10_3 = 12.0;
-
-    private static double load15_1 = 4.0;
-    private static double load15_2 = 8.0;
-    private static double load15_3 = 13.0;
-
-    private HostRef ref;
-    private Converter<CpuStat> converter;
-    private Chunk result1, result2, result3;
-
-    @Before
-    public void setUp() {
-        ref = new HostRef(AGENT_ID, HOSTNAME);
-        converter = new CpuStatConverter();
-        result1 = new Chunk(cat, false);
-        result1.put(Key.AGENT_ID, AGENT_ID);
-        result1.put(Key.TIMESTAMP, t1);
-        result1.put(CpuStatDAO.cpu5LoadKey, load5_1);
-        result1.put(CpuStatDAO.cpu10LoadKey, load10_1);
-        result1.put(CpuStatDAO.cpu15LoadKey, load15_1);
-        result2 = new Chunk(cat, false);
-        result2.put(Key.AGENT_ID, AGENT_ID);
-        result2.put(Key.TIMESTAMP, t2);
-        result2.put(CpuStatDAO.cpu5LoadKey, load5_2);
-        result2.put(CpuStatDAO.cpu10LoadKey, load10_2);
-        result2.put(CpuStatDAO.cpu15LoadKey, load15_2);
-        result3 = new Chunk(cat, false);
-        result3.put(Key.AGENT_ID, AGENT_ID);
-        result3.put(Key.TIMESTAMP, t3);
-        result3.put(CpuStatDAO.cpu5LoadKey, load5_3);
-        result3.put(CpuStatDAO.cpu10LoadKey, load10_3);
-        result3.put(CpuStatDAO.cpu15LoadKey, load15_3);
-    }
-
-    @Test
-    public void testBuildQuery() {
-        Storage storage = mock(Storage.class);
-        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
-        Chunk query = getter.buildQuery();
-
-        assertNotNull(query);
-        assertEquals(cat, query.getCategory());
-        assertEquals(1, query.getKeys().size());
-        assertTrue(query.getKeys().contains(Key.AGENT_ID));
-        assertFalse(query.getKeys().contains(Key.WHERE));
-        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-    }
-
-    @Test
-    public void testBuildQueryPopulatesUpdateTimes() {
-        Storage storage = mock(Storage.class);
-        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
-        getter.buildQuery(); // Ignore first return value.
-        Chunk query = getter.buildQuery();
-
-        assertNotNull(query);
-        assertEquals(cat, query.getCategory());
-        assertEquals(2, query.getKeys().size());
-        assertTrue(query.getKeys().contains(Key.AGENT_ID));
-        assertTrue(query.getKeys().contains(Key.WHERE));
-        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
-    }
-
-    @Test
-    public void testGetLatest() {
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
-
-        List<CpuStat> stats = getter.getLatest();
-
-        assertNotNull(stats);
-        assertEquals(2, stats.size());
-        CpuStat stat1 = stats.get(0);
-        assertEquals(t1, stat1.getTimeStamp());
-        assertEquals(load5_1, stat1.getLoad5(), 0.001);
-        assertEquals(load10_1, stat1.getLoad10(), 0.001);
-        assertEquals(load15_1, stat1.getLoad15(), 0.001);
-        CpuStat stat2 = stats.get(1);
-        assertEquals(t2, stat2.getTimeStamp());
-        assertEquals(load5_2, stat2.getLoad5(), 0.001);
-        assertEquals(load10_2, stat2.getLoad10(), 0.001);
-        assertEquals(load15_2, stat2.getLoad15(), 0.001);
-    }
-
-    @Test
-    public void testGetLatestMultipleCalls() {
-        Cursor cursor1 = mock(Cursor.class);
-        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
-
-        Cursor cursor2 = mock(Cursor.class);
-        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor2.next()).thenReturn(result3);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
-
-        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
-        getter.getLatest();
-        getter.getLatest();
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        List<Chunk> queries = arg.getAllValues();
-
-        assertEquals(2, queries.size());
-        Chunk query = queries.get(1);
-        assertNotNull(query);
-        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
-    }
-
-    @After
-    public void tearDown() {
-        ref = null;
-        converter = null;
-        result1 = null;
-        result2 = null;
-        result3 = null;
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class MemoryStatConverterTest {
-
-    @Test
-    public void testMemoryStatToChunk() {
-        MemoryStat stat = new MemoryStat(0, 1, 2, 3, 4, 5, 6, 7);
-
-        Chunk chunk = new MemoryStatConverter().toChunk(stat);
-
-        assertEquals((Long) 0l, chunk.get(Key.TIMESTAMP));
-        assertEquals((Long) 1l, chunk.get(new Key<Long>("total", false)));
-        assertEquals((Long) 2l, chunk.get(new Key<Long>("free", false)));
-        assertEquals((Long) 3l, chunk.get(new Key<Long>("buffers", false)));
-        assertEquals((Long) 4l, chunk.get(new Key<Long>("cached", false)));
-        assertEquals((Long) 5l, chunk.get(new Key<Long>("swap-total", false)));
-        assertEquals((Long) 6l, chunk.get(new Key<Long>("swap-free", false)));
-        assertEquals((Long) 7l, chunk.get(new Key<Long>("commit-limit", false)));
-    }
-
-    @Test
-    public void testChunkToMemoryStat() {
-        long TIMESTAMP = 1;
-        long TOTAL = 2;
-        long FREE = 3;
-        long BUFFERS = 4;
-        long CACHED = 5;
-        long SWAP_TOTAL = 6;
-        long SWAP_FREE = 7;
-        long COMMIT_LIMIT = 8;
-
-        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
-        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
-        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
-        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
-        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
-        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
-        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
-
-        MemoryStat stat = new MemoryStatConverter().fromChunk(chunk);
-
-        assertEquals(TIMESTAMP, stat.getTimeStamp());
-        assertEquals(TOTAL, stat.getTotal());
-        assertEquals(FREE, stat.getFree());
-        assertEquals(BUFFERS, stat.getBuffers());
-        assertEquals(CACHED, stat.getCached());
-        assertEquals(SWAP_TOTAL, stat.getSwapTotal());
-        assertEquals(SWAP_FREE, stat.getSwapFree());
-        assertEquals(COMMIT_LIMIT, stat.getCommitLimit());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import static org.mockito.Mockito.any;
-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.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class MemoryStatDAOTest {
-
-
-    private static long TIMESTAMP = 1;
-    private static long TOTAL = 2;
-    private static long FREE = 3;
-    private static long BUFFERS = 4;
-    private static long CACHED = 5;
-    private static long SWAP_TOTAL = 6;
-    private static long SWAP_FREE = 7;
-    private static long COMMIT_LIMIT = 8;
-
-    @Test
-    public void testCategory() {
-        assertEquals("memory-stats", MemoryStatDAO.memoryStatCategory.getName());
-        Collection<Key<?>> keys = MemoryStatDAO.memoryStatCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<Long>("total", false)));
-        assertTrue(keys.contains(new Key<Long>("free", false)));
-        assertTrue(keys.contains(new Key<Long>("buffers", false)));
-        assertTrue(keys.contains(new Key<Long>("cached", false)));
-        assertTrue(keys.contains(new Key<Long>("swap-total", false)));
-        assertTrue(keys.contains(new Key<Long>("swap-free", false)));
-        assertTrue(keys.contains(new Key<Long>("commit-limit", false)));
-        assertEquals(9, keys.size());
-
-    }
-
-    @Test
-    public void testGetLatestMemoryStats() {
-
-        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
-        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
-        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
-        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
-        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
-        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
-        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
-        List<MemoryStat> memoryStats = dao.getLatestMemoryStats(hostRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, memoryStats.size());
-        MemoryStat stat = memoryStats.get(0);
-
-        assertEquals(TIMESTAMP, stat.getTimeStamp());
-        assertEquals(TOTAL, stat.getTotal());
-        assertEquals(FREE, stat.getFree());
-        assertEquals(BUFFERS, stat.getBuffers());
-        assertEquals(CACHED, stat.getCached());
-        assertEquals(SWAP_TOTAL, stat.getSwapTotal());
-        assertEquals(SWAP_FREE, stat.getSwapFree());
-        assertEquals(COMMIT_LIMIT, stat.getCommitLimit());
-    }
-
-    @Test
-    public void testGetLatestMemoryStatsTwice() {
-
-        Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(MemoryStatDAO.memoryTotalKey, TOTAL);
-        chunk.put(MemoryStatDAO.memoryFreeKey, FREE);
-        chunk.put(MemoryStatDAO.memoryBuffersKey, BUFFERS);
-        chunk.put(MemoryStatDAO.memoryCachedKey, CACHED);
-        chunk.put(MemoryStatDAO.memorySwapTotalKey, SWAP_TOTAL);
-        chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
-        chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
-        dao.getLatestMemoryStats(hostRef);
-        dao.getLatestMemoryStats(hostRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        assertEquals("this.timestamp > 1", arg.getValue().get(new Key<String>("$where", false)));
-    }
-
-    @Test
-    public void testPutHostInfo() {
-        Storage storage = mock(Storage.class);
-        MemoryStat stat = new MemoryStat(TIMESTAMP, TOTAL, FREE, BUFFERS, CACHED, SWAP_TOTAL, SWAP_FREE, COMMIT_LIMIT);
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
-        dao.putMemoryStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(MemoryStatDAO.memoryStatCategory, chunk.getCategory());
-        assertEquals((Long) TIMESTAMP, chunk.get(Key.TIMESTAMP));
-        assertEquals((Long) TOTAL, chunk.get(MemoryStatDAO.memoryTotalKey));
-        assertEquals((Long) FREE, chunk.get(MemoryStatDAO.memoryFreeKey));
-        assertEquals((Long) BUFFERS, chunk.get(MemoryStatDAO.memoryBuffersKey));
-        assertEquals((Long) CACHED, chunk.get(MemoryStatDAO.memoryCachedKey));
-        assertEquals((Long) SWAP_TOTAL, chunk.get(MemoryStatDAO.memorySwapTotalKey));
-        assertEquals((Long) SWAP_FREE, chunk.get(MemoryStatDAO.memorySwapFreeKey));
-        assertEquals((Long) COMMIT_LIMIT, chunk.get(MemoryStatDAO.memoryCommitLimitKey));
-    }
-
-    @Test
-    public void testGetCount() {
-        Storage storage = mock(Storage.class);
-        when(storage.getCount(any(Category.class))).thenReturn(5L);
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
-        Long count = dao.getCount();
-        assertEquals((Long) 5L, count);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.Storage;
-import com.redhat.thermostat.common.storage.StorageProvider;
-
-public class MongoDAOFactoryTest {
-
-    private Storage storage;
-    private Connection connection;
-    private StorageProvider provider;
-    private DAOFactory daoFactory;
-    HostRef hostRef;
-    VmRef vmRef;
-
-    @Before
-    public void setUp() {
-        storage = mock(Storage.class);
-        connection = mock(Connection.class);
-        when(storage.getConnection()).thenReturn(connection);
-        when(connection.isConnected()).thenReturn(true);
-        provider = mock(StorageProvider.class);
-        when(provider.createStorage()).thenReturn(storage);
-        hostRef = mock(HostRef.class);
-        vmRef = mock(VmRef.class);
-        daoFactory = new MongoDAOFactory(provider);
-    }
-
-    @Test
-    public void testGetConnection() {
-        assertSame(storage, daoFactory.getStorage());
-    }
-
-    @Test
-    public void testGetVmClassStatsDAO() {
-        VmClassStatDAO dao = daoFactory.getVmClassStatsDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetVmGcStatDAO() {
-        VmGcStatDAO dao = daoFactory.getVmGcStatDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetVmInfoDAO() {
-        VmInfoDAO dao = daoFactory.getVmInfoDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetVmMemoryStatDAO() {
-        VmMemoryStatDAO dao = daoFactory.getVmMemoryStatDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetHostInfoDAO() {
-        HostInfoDAO dao = daoFactory.getHostInfoDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetCpuStatDAO() {
-        CpuStatDAO dao = daoFactory.getCpuStatDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetMemoryStatDAO() {
-        MemoryStatDAO dao = daoFactory.getMemoryStatDAO();
-        assertNotNull(dao);
-    }
-
-    @Test
-    public void testGetNetworkInterfaceInfoDAO() {
-        NetworkInterfaceInfoDAO dao = daoFactory.getNetworkInterfaceInfoDAO();
-        assertNotNull(dao);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class NetworkInterfaceInfoConverterTest {
-
-    @Test
-    public void testNetworkInfoToChunk() {
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo("eth0");
-        info.setIp4Addr("4");
-        info.setIp6Addr("6");
-
-        Chunk chunk = new NetworkInterfaceInfoConverter().toChunk(info);
-
-        assertEquals("network-info", chunk.getCategory().getName());
-        assertEquals("eth0", chunk.get(new Key<String>("iface", true)));
-        assertEquals("4", chunk.get(new Key<String>("ipv4addr", false)));
-        assertEquals("6", chunk.get(new Key<String>("ipv6addr", false)));
-
-    }
-
-    @Test
-    public void testChunkToNetworkInfo() {
-        final String INTERFACE_NAME = "some interface. maybe eth0";
-        final String IPV4_ADDR = "256.256.256.256";
-        final String IPV6_ADDR = "100:100:100::::1";
-
-        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, false);
-        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, INTERFACE_NAME);
-        chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, IPV4_ADDR);
-        chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, IPV6_ADDR);
-
-        NetworkInterfaceInfo info = new NetworkInterfaceInfoConverter().fromChunk(chunk);
-        assertNotNull(info);
-        assertEquals(INTERFACE_NAME, info.getInterfaceName());
-        assertEquals(IPV4_ADDR, info.getIp4Addr());
-        assertEquals(IPV6_ADDR, info.getIp6Addr());
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class NetworkInterfaceInfoDAOTest {
-
-    private static final String INTERFACE_NAME = "some interface. maybe eth0";
-    private static final String IPV4_ADDR = "256.256.256.256";
-    private static final String IPV6_ADDR = "100:100:100::::1";
-
-    @Test
-    public void testCategory() {
-        Collection<Key<?>> keys;
-
-        assertEquals("network-info", NetworkInterfaceInfoDAO.networkInfoCategory.getName());
-        keys = NetworkInterfaceInfoDAO.networkInfoCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<String>("iface", true)));
-        assertTrue(keys.contains(new Key<String>("ipv4addr", false)));
-        assertTrue(keys.contains(new Key<String>("ipv6addr", false)));
-        assertEquals(5, keys.size());
-    }
-
-    @Test
-    public void testGetNetworkInterfaces() {
-
-        Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, false);
-        chunk.put(NetworkInterfaceInfoDAO.ifaceKey, INTERFACE_NAME);
-        chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, IPV4_ADDR);
-        chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, IPV6_ADDR);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage);
-        List<NetworkInterfaceInfo> netInfo = dao.getNetworkInterfaces(hostRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, netInfo.size());
-
-        NetworkInterfaceInfo info = netInfo.get(0);
-
-        assertEquals(INTERFACE_NAME, info.getInterfaceName());
-        assertEquals(IPV4_ADDR, info.getIp4Addr());
-        assertEquals(IPV6_ADDR, info.getIp6Addr());
-    }
-
-    @Test
-    public void testPutNetworkInterfaceInfo() {
-        Storage storage = mock(Storage.class);
-        NetworkInterfaceInfo info = new NetworkInterfaceInfo(INTERFACE_NAME);
-        info.setIp4Addr(IPV4_ADDR);
-        info.setIp6Addr(IPV6_ADDR);
-        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage);
-        dao.putNetworkInterfaceInfo(info);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(NetworkInterfaceInfoDAO.networkInfoCategory, chunk.getCategory());
-        assertEquals(INTERFACE_NAME, chunk.get(NetworkInterfaceInfoDAO.ifaceKey));
-        assertEquals(IPV4_ADDR, chunk.get(NetworkInterfaceInfoDAO.ip4AddrKey));
-        assertEquals(IPV6_ADDR, chunk.get(NetworkInterfaceInfoDAO.ip6AddrKey));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmClassStatConverterTest {
-
-    @Test
-    public void testVmClassStatToChunk() {
-        VmClassStat stat = new VmClassStat(123, 1234L, 12345L);
-
-        VmClassStatConverter dao = new VmClassStatConverter();
-        Chunk chunk = dao.toChunk(stat);
-
-        assertEquals("vm-class-stats", chunk.getCategory().getName());
-        assertEquals((Long) 1234L, chunk.get(Key.TIMESTAMP));
-        assertEquals((Integer) 123, chunk.get(new Key<Integer>("vm-id", false)));
-        assertEquals((Long) 12345L, chunk.get(new Key<Long>("loadedClasses", false)));
-    }
-
-    @Test
-    public void testChunkToVmClassStat() {
-        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        chunk.put(Key.VM_ID, 123);
-        chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
-
-        VmClassStat stat = new VmClassStatConverter().fromChunk(chunk);
-
-        assertEquals(123, stat.getVmId());
-        assertEquals(1234L, stat.getTimeStamp());
-        assertEquals(12345L, stat.getLoadedClasses());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-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.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class VmClassStatDAOTest {
-
-    private static final Long TIMESTAMP = 1234L;
-    private static final Integer VM_ID = 123;
-    private static final Long LOADED_CLASSES = 12345L;
-
-    @Test
-    public void testCategory() {
-        assertEquals("vm-class-stats", VmClassStatDAO.vmClassStatsCategory.getName());
-        Collection<Key<?>> keys = VmClassStatDAO.vmClassStatsCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<Long>("loadedClasses", false)));
-        assertEquals(4, keys.size());
-
-    }
-
-    @Test
-    public void testGetLatestClassStatsBasic() {
-
-        Chunk chunk = getChunk();
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-
-        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
-        List<VmClassStat> vmClassStats = dao.getLatestClassStats(vmRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, vmClassStats.size());
-        VmClassStat stat = vmClassStats.get(0);
-        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
-        assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses());
-        assertEquals(VM_ID, (Integer) stat.getVmId());
-    }
-
-    @Test
-    public void testGetLatestClassStatsTwice() {
-
-        Chunk chunk = getChunk();
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-
-        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
-        dao.getLatestClassStats(vmRef);
-
-        dao.getLatestClassStats(vmRef);
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
-    }
-
-    private Chunk getChunk() {
-        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmClassStatDAO.loadedClassesKey, LOADED_CLASSES);
-        return chunk;
-    }
-
-    @Test
-    public void testPutVmClassStat() {
-
-        Storage storage = mock(Storage.class);
-        VmClassStat stat = new VmClassStat(VM_ID, TIMESTAMP, LOADED_CLASSES);
-        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
-        dao.putVmClassStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmClassStatDAO.vmClassStatsCategory, chunk.getCategory());
-        assertEquals((Long) TIMESTAMP, chunk.get(Key.TIMESTAMP));
-        assertEquals((Integer) VM_ID, chunk.get(Key.VM_ID));
-        assertEquals((Long) LOADED_CLASSES, chunk.get(VmClassStatDAO.loadedClassesKey));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmCpuStatConverterTest {
-
-    final long TIMESTAMP = 12345l;
-    final int VM_ID = 678;
-    final double PROCESSOR_USAGE = 9.9;
-
-    @Test
-    public void testVmCpuStatToChunk() {
-
-        VmCpuStat vmCpuStat = new VmCpuStat(TIMESTAMP, VM_ID, PROCESSOR_USAGE);
-        Chunk chunk = new VmCpuStatConverter().toChunk(vmCpuStat);
-        assertNotNull(chunk);
-        assertEquals("vm-cpu-stats", chunk.getCategory().getName());
-        assertEquals((Long)TIMESTAMP, chunk.get(Key.TIMESTAMP));
-        assertEquals((Integer) VM_ID, chunk.get(new Key<Long>("vm-id", false)));
-        assertEquals(PROCESSOR_USAGE, chunk.get(new Key<Double>("processor-usage", false)), 0.001);
-
-    }
-
-    @Test
-    public void testChunkToVmCpuStat() {
-        Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmCpuStatDAO.vmCpuLoadKey, PROCESSOR_USAGE);
-
-        VmCpuStat stat = new VmCpuStatConverter().fromChunk(chunk);
-        assertNotNull(stat);
-        assertEquals(TIMESTAMP, stat.getTimeStamp());
-        assertEquals(VM_ID, stat.getVmId());
-        assertEquals(PROCESSOR_USAGE, stat.getCpuLoad(), 0.001);
-
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-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.util.Collection;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class VmCpuStatDAOTest {
-
-    private static final Long TIMESTAMP = 1234L;
-    private static final String AGENT_ID = "test-agent-id";
-    private static final Integer VM_ID = 321;
-    private static final Double CPU_LOAD = 9.9;
-
-    private Chunk chunk;
-
-    @Before
-    public void setUp() {
-        chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.AGENT_ID, AGENT_ID);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmCpuStatDAO.vmCpuLoadKey, CPU_LOAD);
-    }
-
-    @Test
-    public void testCategory() {
-        assertEquals("vm-cpu-stats", VmCpuStatDAO.vmCpuStatCategory.getName());
-        Collection<Key<?>> keys = VmCpuStatDAO.vmCpuStatCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
-        assertTrue(keys.contains(new Key<Integer>("processor-usage", false)));
-        assertEquals(4, keys.size());
-    }
-
-    @Test
-    public void testGetLatestCpuStatsBasic() {
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(VM_ID);
-
-
-        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
-        List<VmCpuStat> vmCpuStats = dao.getLatestVmCpuStats(vmRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, vmCpuStats.size());
-        VmCpuStat stat = vmCpuStats.get(0);
-        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
-        assertEquals(CPU_LOAD, stat.getCpuLoad(), 0.001);
-        assertEquals(VM_ID, (Integer) stat.getVmId());
-    }
-
-    @Test
-    public void testGetLatestCpuStatsTwice() {
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
-        dao.getLatestVmCpuStats(vmRef);
-
-        dao.getLatestVmCpuStats(vmRef);
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
-    }
-
-    @Test
-    public void testPutVmCpuStat() {
-        Storage storage = mock(Storage.class);
-        VmCpuStat stat = new VmCpuStat(TIMESTAMP, VM_ID, CPU_LOAD);
-        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
-        dao.putVmCpuStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmCpuStatDAO.vmCpuStatCategory, chunk.getCategory());
-        assertEquals(TIMESTAMP, chunk.get(Key.TIMESTAMP));
-        assertEquals(VM_ID, chunk.get(Key.VM_ID));
-        assertEquals(CPU_LOAD, chunk.get(VmCpuStatDAO.vmCpuLoadKey));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmGcStatConverterTest {
-
-    @Test
-    public void testVmGcStatToChunk() {
-        final Integer VM_ID = 123;
-        final Long TIMESTAMP = 456L;
-        final String COLLECTOR = "collector1";
-        final Long RUN_COUNT = 10L;
-        final Long WALL_TIME = 9L;
-
-        VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
-        Chunk chunk = new VmGcStatConverter().toChunk(stat);
-
-        assertNotNull(chunk);
-        assertEquals("vm-gc-stats", chunk.getCategory().getName());
-        assertEquals(TIMESTAMP, chunk.get(new Key<Long>("timestamp", false)));
-        assertEquals(VM_ID, chunk.get(new Key<Integer>("vm-id", false)));
-        assertEquals(COLLECTOR, chunk.get(new Key<String>("collector", false)));
-        assertEquals(RUN_COUNT, chunk.get(new Key<Long>("runtime-count", false)));
-        assertEquals(WALL_TIME, chunk.get(new Key<Long>("wall-time", false)));
-    }
-
-    @Test
-    public void testChunkToVmGcStat() {
-        final Integer VM_ID = 123;
-        final Long TIMESTAMP = 456L;
-        final String COLLECTOR = "collector1";
-        final Long RUN_COUNT = 10L;
-        final Long WALL_TIME = 9L;
-
-        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
-        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
-        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
-        VmGcStat stat = new VmGcStatConverter().fromChunk(chunk);
-
-        assertNotNull(stat);
-        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
-        assertEquals(VM_ID, (Integer) stat.getVmId());
-        assertEquals(COLLECTOR, stat.getCollectorName());
-        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
-        assertEquals(WALL_TIME, (Long) stat.getWallTime());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-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.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class VmGcStatDAOTest {
-
-    private static final Integer VM_ID = 123;
-    private static final Long TIMESTAMP = 456L;
-    private static final String COLLECTOR = "collector1";
-    private static final Long RUN_COUNT = 10L;
-    private static final Long WALL_TIME = 9L;
-
-    @Test
-    public void testCategory() {
-        assertEquals("vm-gc-stats", VmGcStatDAO.vmGcStatCategory.getName());
-        Collection<Key<?>> keys = VmGcStatDAO.vmGcStatCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<String>("collector", false)));
-        assertTrue(keys.contains(new Key<Long>("runtime-count", false)));
-        assertTrue(keys.contains(new Key<Long>("wall-time", false)));
-        assertEquals(6, keys.size());
-    }
-
-    @Test
-    public void testGetLatestVmGcStatsBasic() {
-
-        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
-        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
-        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-
-        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
-        List<VmGcStat> vmGcStats = dao.getLatestVmGcStats(vmRef);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).findAll(arg.capture());
-        assertNull(arg.getValue().get(new Key<String>("$where", false)));
-
-        assertEquals(1, vmGcStats.size());
-        VmGcStat stat = vmGcStats.get(0);
-        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
-        assertEquals(VM_ID, (Integer) stat.getVmId());
-        assertEquals(COLLECTOR, stat.getCollectorName());
-        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
-        assertEquals(WALL_TIME, (Long) stat.getWallTime());
-    }
-
-    @Test
-    public void testGetLatestVmGcStatsTwice() {
-
-        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatCategory, false);
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
-        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
-        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(chunk);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
-        dao.getLatestVmGcStats(vmRef);
-
-        dao.getLatestVmGcStats(vmRef);
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        assertEquals("this.timestamp > 456", arg.getValue().get(new Key<String>("$where", false)));
-    }
-
-    @Test
-    public void testPutVmGcStat() {
-        Storage storage = mock(Storage.class);
-        VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
-        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
-        dao.putVmGcStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmGcStatDAO.vmGcStatCategory, chunk.getCategory());
-        assertEquals(TIMESTAMP, chunk.get(Key.TIMESTAMP));
-        assertEquals(VM_ID, chunk.get(Key.VM_ID));
-        assertEquals(COLLECTOR, chunk.get(VmGcStatDAO.collectorKey));
-        assertEquals(RUN_COUNT, chunk.get(VmGcStatDAO.runCountKey));
-        assertEquals(WALL_TIME, chunk.get(VmGcStatDAO.wallTimeKey));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.storage.Chunk;
-
-public class VmInfoConverterTest {
-
-    private int vmId;
-    private long startTime;
-    private long stopTime;
-    private String jVersion;
-    private String jHome;
-    private String mainClass;
-    private String commandLine;
-    private String vmName;
-    private String vmInfo;
-    private String vmVersion;
-    private String vmArgs;
-    private Map<String, String> props;
-    private Map<String, String> env;
-    private List<String> libs;
-
-    @Before
-    public void setUp() {
-        vmId = 1;
-        startTime = 2;
-        stopTime = 3;
-        jVersion = "java 1.0";
-        jHome = "/path/to/jdk/home";
-        mainClass = "Hello.class";
-        commandLine = "World";
-        vmArgs = "-XX=+FastestJITPossible";
-        vmName = "Hotspot";
-        vmInfo = "Some info";
-        vmVersion = "1.0";
-        props = new HashMap<>();
-        env = new HashMap<>();
-        libs = new ArrayList<>();
-    }
-
-    @Test
-    public void testVmInfoToChunk() {
-        VmInfo info = new VmInfo(vmId, startTime, stopTime,
-                jVersion, jHome, mainClass, commandLine,
-                vmName, vmInfo, vmVersion, vmArgs,
-                props, env, libs);
-
-        Chunk chunk = new VmInfoConverter().toChunk(info);
-
-        assertNotNull(chunk);
-        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
-        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
-        assertEquals((Long) startTime, chunk.get(VmInfoDAO.startTimeKey));
-        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
-        assertEquals(jVersion, chunk.get(VmInfoDAO.runtimeVersionKey));
-        assertEquals(jHome, chunk.get(VmInfoDAO.javaHomeKey));
-        assertEquals(mainClass, chunk.get(VmInfoDAO.mainClassKey));
-        assertEquals(commandLine, chunk.get(VmInfoDAO.commandLineKey));
-        assertEquals(vmName, chunk.get(VmInfoDAO.vmNameKey));
-        assertEquals(vmInfo, chunk.get(VmInfoDAO.vmInfoKey));
-        assertEquals(vmVersion, chunk.get(VmInfoDAO.vmVersionKey));
-        assertEquals(vmArgs, chunk.get(VmInfoDAO.vmArgumentsKey));
-
-        // FIXME test environment, properties and loaded native libraries later
-    }
-
-    @Test
-    public void testChunkToVmInfo() {
-        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
-
-        chunk.put(VmInfoDAO.vmIdKey, vmId);
-        chunk.put(VmInfoDAO.vmPidKey, vmId);
-        chunk.put(VmInfoDAO.startTimeKey, startTime);
-        chunk.put(VmInfoDAO.stopTimeKey, stopTime);
-        chunk.put(VmInfoDAO.runtimeVersionKey, jVersion);
-        chunk.put(VmInfoDAO.javaHomeKey, jHome);
-        chunk.put(VmInfoDAO.mainClassKey, mainClass);
-        chunk.put(VmInfoDAO.commandLineKey, commandLine);
-        chunk.put(VmInfoDAO.vmNameKey, vmName);
-        chunk.put(VmInfoDAO.vmInfoKey, vmInfo);
-        chunk.put(VmInfoDAO.vmVersionKey, vmVersion);
-        chunk.put(VmInfoDAO.vmArgumentsKey, vmArgs);
-        chunk.put(VmInfoDAO.propertiesKey, props);
-        chunk.put(VmInfoDAO.environmentKey, env);
-        chunk.put(VmInfoDAO.librariesKey, libs);
-
-        VmInfo info = new VmInfoConverter().fromChunk(chunk);
-
-        assertNotNull(info);
-        assertEquals((Integer) vmId, (Integer) info.getVmId());
-        assertEquals((Integer) vmId, (Integer) info.getVmPid());
-        assertEquals((Long) startTime, (Long) info.getStartTimeStamp());
-        assertEquals((Long) stopTime, (Long) info.getStopTimeStamp());
-        assertEquals(jVersion, info.getJavaVersion());
-        assertEquals(jHome, info.getJavaHome());
-        assertEquals(mainClass, info.getMainClass());
-        assertEquals(commandLine, info.getJavaCommandLine());
-        assertEquals(vmName, info.getVmName());
-        assertEquals(vmInfo, info.getVmInfo());
-        assertEquals(vmVersion, info.getVmVersion());
-        assertEquals(vmArgs, info.getVmArguments());
-
-        // FIXME test environment, properties and loaded native libraries later
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.VmInfo;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class VmInfoDAOTest {
-
-    private int vmId;
-    private long startTime;
-    private long stopTime;
-    private String jVersion;
-    private String jHome;
-    private String mainClass;
-    private String commandLine;
-    private String vmName;
-    private String vmInfo;
-    private String vmVersion;
-    private String vmArgs;
-    private Map<String, String> props;
-    private Map<String, String> env;
-    private List<String> libs;
-    private VmInfoDAO dao;
-
-    @Before
-    public void setUp() {
-        vmId = 1;
-        startTime = 2;
-        stopTime = 3;
-        jVersion = "java 1.0";
-        jHome = "/path/to/jdk/home";
-        mainClass = "Hello.class";
-        commandLine = "World";
-        vmArgs = "-XX=+FastestJITPossible";
-        vmName = "Hotspot";
-        vmInfo = "Some info";
-        vmVersion = "1.0";
-        props = new HashMap<>();
-        env = new HashMap<>();
-        libs = new ArrayList<>();
-        Storage storage = setupStorageForSingleVM();
-        dao = new VmInfoDAOImpl(storage);
-    }
-
-    @After
-    public void tearDown() {
-        dao = null;
-    }
-
-    @Test
-    public void testCategory() {
-        assertEquals("vm-info", VmInfoDAO.vmInfoCategory.getName());
-        Collection<Key<?>> keys = VmInfoDAO.vmInfoCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Integer>("vm-id", true)));
-        assertTrue(keys.contains(new Key<Integer>("vm-pid", false)));
-        assertTrue(keys.contains(new Key<String>("runtime-version", false)));
-        assertTrue(keys.contains(new Key<String>("java-home", false)));
-        assertTrue(keys.contains(new Key<String>("main-class", false)));
-        assertTrue(keys.contains(new Key<String>("command-line", false)));
-        assertTrue(keys.contains(new Key<String>("vm-arguments", false)));
-        assertTrue(keys.contains(new Key<String>("vm-name", false)));
-        assertTrue(keys.contains(new Key<String>("vm-info", false)));
-        assertTrue(keys.contains(new Key<String>("vm-version", false)));
-        assertTrue(keys.contains(new Key<Map<String, String>>("properties", false)));
-        assertTrue(keys.contains(new Key<Map<String, String>>("environment", false)));
-        assertTrue(keys.contains(new Key<List<String>>("libraries", false)));
-        assertTrue(keys.contains(new Key<Long>("start-time", false)));
-        assertTrue(keys.contains(new Key<Long>("stop-time", false)));
-        assertEquals(16, keys.size());
-    }
-
-    @Test
-    public void testGetVmInfo() {
-        Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
-        chunk.put(VmInfoDAO.vmIdKey, vmId);
-        chunk.put(VmInfoDAO.vmPidKey, vmId);
-        chunk.put(VmInfoDAO.startTimeKey, startTime);
-        chunk.put(VmInfoDAO.stopTimeKey, stopTime);
-        chunk.put(VmInfoDAO.runtimeVersionKey, jVersion);
-        chunk.put(VmInfoDAO.javaHomeKey, jHome);
-        chunk.put(VmInfoDAO.mainClassKey, mainClass);
-        chunk.put(VmInfoDAO.commandLineKey, commandLine);
-        chunk.put(VmInfoDAO.vmNameKey, vmName);
-        chunk.put(VmInfoDAO.vmInfoKey, vmInfo);
-        chunk.put(VmInfoDAO.vmVersionKey, vmVersion);
-        chunk.put(VmInfoDAO.vmArgumentsKey, vmArgs);
-        chunk.put(VmInfoDAO.propertiesKey, props);
-        chunk.put(VmInfoDAO.environmentKey, env);
-        chunk.put(VmInfoDAO.librariesKey, libs);
-
-        Storage storage = mock(Storage.class);
-        when(storage.find(any(Chunk.class))).thenReturn(chunk);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-        VmInfoDAO dao = new VmInfoDAOImpl(storage);
-        VmInfo info = dao.getVmInfo(vmRef);
-
-        assertNotNull(info);
-        assertEquals((Integer) vmId, (Integer) info.getVmId());
-        assertEquals((Integer) vmId, (Integer) info.getVmPid());
-        assertEquals((Long) startTime, (Long) info.getStartTimeStamp());
-        assertEquals((Long) stopTime, (Long) info.getStopTimeStamp());
-        assertEquals(jVersion, info.getJavaVersion());
-        assertEquals(jHome, info.getJavaHome());
-        assertEquals(mainClass, info.getMainClass());
-        assertEquals(commandLine, info.getJavaCommandLine());
-        assertEquals(vmName, info.getVmName());
-        assertEquals(vmInfo, info.getVmInfo());
-        assertEquals(vmVersion, info.getVmVersion());
-        assertEquals(vmArgs, info.getVmArguments());
-
-        // FIXME test environment, properties and loaded native libraries later
-    }
-
-    @Test
-    public void testGetVmInfoUnknownVM() {
-
-        Storage storage = mock(Storage.class);
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn("system");
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(321);
-
-        VmInfoDAO dao = new VmInfoDAOImpl(storage);
-        try {
-            dao.getVmInfo(vmRef);
-            fail();
-        } catch (DAOException ex) {
-            assertEquals("Unknown VM: host:system;vm:321", ex.getMessage());
-        }
-
-    }
-
-    private Storage setupStorageForSingleVM() {
-        Chunk query1 = new Chunk(VmInfoDAO.vmInfoCategory, false);
-        query1.put(Key.AGENT_ID, "123");
-
-        Chunk query2 = new Chunk(VmInfoDAO.vmInfoCategory, false);
-        query2.put(Key.AGENT_ID, "456");
-
-        Chunk vm1 = new Chunk(VmInfoDAO.vmInfoCategory, false);
-        vm1.put(VmInfoDAO.vmIdKey, 123);
-        vm1.put(VmInfoDAO.mainClassKey, "mainClass1");
-
-        Chunk vm2 = new Chunk(VmInfoDAO.vmInfoCategory, false);
-        vm2.put(VmInfoDAO.vmIdKey, 456);
-        vm2.put(VmInfoDAO.mainClassKey, "mainClass2");
-
-        Cursor singleVMCursor = mock(Cursor.class);
-        when(singleVMCursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(singleVMCursor.next()).thenReturn(vm1);
-
-        Cursor multiVMsCursor = mock(Cursor.class);
-        when(multiVMsCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(multiVMsCursor.next()).thenReturn(vm1).thenReturn(vm2);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(query1)).thenReturn(singleVMCursor);
-        when(storage.findAll(query2)).thenReturn(multiVMsCursor);
-        return storage;
-    }
-
-    @Test
-    public void testSingleVM() {
-        HostRef host = new HostRef("123", "fluffhost");
-
-        Collection<VmRef> vms = dao.getVMs(host);
-
-        assertCollection(vms, new VmRef(host, 123, "mainClass1"));
-    }
-
-    @Test
-    public void testMultiVMs() {
-        HostRef host = new HostRef("456", "fluffhost");
-
-        Collection<VmRef> vms = dao.getVMs(host);
-
-        assertCollection(vms, new VmRef(host, 123, "mainClass1"), new VmRef(host, 456, "mainClass2"));
-    }
-
-    private void assertCollection(Collection<VmRef> vms, VmRef... expectedVMs) {
-        assertEquals(expectedVMs.length, vms.size());
-        for (VmRef expectedVM : expectedVMs) {
-            assertTrue(vms.contains(expectedVM));
-        }
-    }
-
-    @Test
-    public void testGetCount() {
-        Storage storage = mock(Storage.class);
-        when(storage.getCount(any(Category.class))).thenReturn(5L);
-        VmInfoDAO dao = new VmInfoDAOImpl(storage);
-        Long count = dao.getCount();
-        assertEquals((Long) 5L, count);
-    }
-
-    @Test
-    public void testPutVmInfo() {
-
-        Storage storage = mock(Storage.class);
-        VmInfo info = new VmInfo(vmId, startTime, stopTime, jVersion, jHome,
-                mainClass, commandLine, vmName, vmInfo, vmVersion, vmArgs,
-                props, env, libs);
-        VmInfoDAO dao = new VmInfoDAOImpl(storage);
-        dao.putVmInfo(info);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmInfoDAO.vmInfoCategory, chunk.getCategory());
-        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
-        assertEquals((Long) startTime, chunk.get(VmInfoDAO.startTimeKey));
-        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
-        assertEquals(jVersion, chunk.get(VmInfoDAO.runtimeVersionKey));
-        assertEquals(jHome, chunk.get(VmInfoDAO.javaHomeKey));
-        assertEquals(mainClass, chunk.get(VmInfoDAO.mainClassKey));
-        assertEquals(commandLine, chunk.get(VmInfoDAO.commandLineKey));
-        assertEquals(vmName, chunk.get(VmInfoDAO.vmNameKey));
-        assertEquals(vmInfo, chunk.get(VmInfoDAO.vmInfoKey));
-        assertEquals(vmVersion, chunk.get(VmInfoDAO.vmVersionKey));
-        assertEquals(vmArgs, chunk.get(VmInfoDAO.vmArgumentsKey));
-        assertEquals(props, chunk.get(VmInfoDAO.propertiesKey));
-        assertEquals(env, chunk.get(VmInfoDAO.environmentKey));
-        assertEquals(libs, chunk.get(VmInfoDAO.librariesKey));
-    }
-
-    @Test
-    public void testPutVmStoppedTime() {
-        Storage storage = mock(Storage.class);
-        VmInfoDAO dao = new VmInfoDAOImpl(storage);
-        dao.putVmStoppedTime(vmId, stopTime);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).updateChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmInfoDAO.vmInfoCategory, chunk.getCategory());
-        assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
-        assertEquals((Long) stopTime, chunk.get(VmInfoDAO.stopTimeKey));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Category;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-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.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class VmLatestPojoListGetterTest {
-    private static final String AGENT_ID = "agentid";
-    private static final String HOSTNAME = "host.example.com";
-    private static final int VM_PID = 123;
-    private static final String MAIN_CLASS = "Foo.class";
-    private static final String CATEGORY_NAME = "vmcategory";
-    // Make this one static so we don't get IllegalStateException from trying
-    // to make category of same name while running tests in same classloader.
-    private static final Category cat =  new Category(CATEGORY_NAME);
-
-    private static long t1 = 1;
-    private static long t2 = 5;
-    private static long t3 = 10;
-
-    private static long lc1 = 10;
-    private static long lc2 = 20;
-    private static long lc3 = 30;
-
-    private HostRef hostRef;
-    private VmRef vmRef;
-    private Converter<VmClassStat> converter;
-    private Chunk result1, result2, result3;
-
-    @Before
-    public void setUp() {
-        hostRef = new HostRef(AGENT_ID, HOSTNAME);
-        vmRef = new VmRef(hostRef, VM_PID, MAIN_CLASS);
-        converter = new VmClassStatConverter();
-        result1 = new Chunk(cat, false);
-        result1.put(Key.AGENT_ID, AGENT_ID);
-        result1.put(Key.VM_ID, VM_PID);
-        result1.put(Key.TIMESTAMP, t1);
-        result1.put(VmClassStatDAO.loadedClassesKey, lc1);
-        result2 = new Chunk(cat, false);
-        result2.put(Key.AGENT_ID, AGENT_ID);
-        result2.put(Key.VM_ID, VM_PID);
-        result2.put(Key.TIMESTAMP, t2);
-        result2.put(VmClassStatDAO.loadedClassesKey, lc2);
-        result3 = new Chunk(cat, false);
-        result3.put(Key.AGENT_ID, AGENT_ID);
-        result3.put(Key.VM_ID, VM_PID);
-        result3.put(Key.TIMESTAMP, t3);
-        result3.put(VmClassStatDAO.loadedClassesKey, lc3);
-    }
-
-    @Test
-    public void testBuildQuery() {
-        Storage storage = mock(Storage.class);
-        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
-        Chunk query = getter.buildQuery();
-
-        assertNotNull(query);
-        assertEquals(cat, query.getCategory());
-        assertEquals(2, query.getKeys().size());
-        assertTrue(query.getKeys().contains(Key.AGENT_ID));
-        assertTrue(query.getKeys().contains(Key.VM_ID));
-        assertFalse(query.getKeys().contains(Key.WHERE));
-        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
-    }
-
-    @Test
-    public void testBuildQueryPopulatesUpdateTimes() {
-        Storage storage = mock(Storage.class);
-        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
-        getter.buildQuery(); // Ignore first return value.
-        Chunk query = getter.buildQuery();
-
-        assertNotNull(query);
-        assertEquals(cat, query.getCategory());
-        assertEquals(3, query.getKeys().size());
-        assertTrue(query.getKeys().contains(Key.AGENT_ID));
-        assertTrue(query.getKeys().contains(Key.VM_ID));
-        assertTrue(query.getKeys().contains(Key.WHERE));
-        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
-    }
-
-    @Test
-    public void testGetLatest() {
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
-
-        List<VmClassStat> stats = getter.getLatest();
-
-        assertNotNull(stats);
-        assertEquals(2, stats.size());
-        VmClassStat stat1 = stats.get(0);
-        assertEquals(t1, stat1.getTimeStamp());
-        assertEquals(lc1, stat1.getLoadedClasses());
-        VmClassStat stat2 = stats.get(1);
-        assertEquals(t2, stat2.getTimeStamp());
-        assertEquals(lc2, stat2.getLoadedClasses());
-    }
-
-    @Test
-    public void testGetLatestMultipleCalls() {
-        Cursor cursor1 = mock(Cursor.class);
-        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
-
-        Cursor cursor2 = mock(Cursor.class);
-        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor2.next()).thenReturn(result3);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
-
-        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
-        getter.getLatest();
-        getter.getLatest();
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage, times(2)).findAll(arg.capture());
-        List<Chunk> queries = arg.getAllValues();
-
-        assertEquals(2, queries.size());
-        Chunk query = queries.get(1);
-        assertNotNull(query);
-        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
-        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Key;
-
-public class VmMemoryStatConverterTest {
-
-    @Test
-    public void testVmMemoryStatToChunk() {
-        List<Generation> generations = new ArrayList<Generation>();
-
-        int i = 0;
-        for (String genName: new String[] { "new", "old", "perm" }) {
-            Generation gen = new Generation();
-            gen.name = genName;
-            gen.collector = gen.name;
-            generations.add(gen);
-            List<Space> spaces = new ArrayList<Space>();
-            gen.spaces = spaces;
-            String[] spaceNames = null;
-            if (genName.equals("new")) {
-                spaceNames = new String[] { "eden", "s0", "s1" };
-            } else if (genName.equals("old")) {
-                spaceNames = new String[] { "old" };
-            } else {
-                spaceNames = new String[] { "perm" };
-            }
-            for (String spaceName: spaceNames) {
-                Space space = new Space();
-                space.name = spaceName;
-                space.index = 0;
-                space.used = i++;
-                space.capacity = i++;
-                space.maxCapacity = i++;
-                spaces.add(space);
-            }
-        }
-
-        VmMemoryStat stat = new VmMemoryStat(1, 2, generations);
-
-        Chunk chunk = new VmMemoryStatConverter().toChunk(stat);
-
-        assertNotNull(chunk);
-        assertEquals((Long) 1l, chunk.get(new Key<Long>("timestamp", false)));
-        assertEquals((Integer) 2, chunk.get(new Key<Integer>("vm-id", false)));
-        assertEquals("new", chunk.get(new Key<String>("eden.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("eden.collector", false)));
-        assertEquals((Long) 0l, chunk.get(new Key<Long>("eden.used", false)));
-        assertEquals((Long) 1l, chunk.get(new Key<Long>("eden.capacity", false)));
-        assertEquals((Long) 2l, chunk.get(new Key<Long>("eden.max-capacity", false)));
-        assertEquals("new", chunk.get(new Key<String>("s0.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("s0.collector", false)));
-        assertEquals((Long) 3l, chunk.get(new Key<Long>("s0.used", false)));
-        assertEquals((Long) 4l, chunk.get(new Key<Long>("s0.capacity", false)));
-        assertEquals((Long) 5l, chunk.get(new Key<Long>("s0.max-capacity", false)));
-        assertEquals("new", chunk.get(new Key<String>("s1.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("s1.collector", false)));
-        assertEquals((Long) 6l, chunk.get(new Key<Long>("s1.used", false)));
-        assertEquals((Long) 7l, chunk.get(new Key<Long>("s1.capacity", false)));
-        assertEquals((Long) 8l, chunk.get(new Key<Long>("s1.max-capacity", false)));
-        assertEquals("old", chunk.get(new Key<String>("old.gen", false)));
-        assertEquals("old", chunk.get(new Key<String>("old.collector", false)));
-        assertEquals((Long) 9l, chunk.get(new Key<Long>("old.used", false)));
-        assertEquals((Long) 10l, chunk.get(new Key<Long>("old.capacity", false)));
-        assertEquals((Long) 11l, chunk.get(new Key<Long>("old.max-capacity", false)));
-        assertEquals("perm", chunk.get(new Key<String>("perm.gen", false)));
-        assertEquals("perm", chunk.get(new Key<String>("perm.collector", false)));
-        assertEquals((Long) 12l, chunk.get(new Key<Long>("perm.used", false)));
-        assertEquals((Long) 13l, chunk.get(new Key<Long>("perm.capacity", false)));
-        assertEquals((Long) 14l, chunk.get(new Key<Long>("perm.max-capacity", false)));
-
-    }
-
-    @Test
-    public void testChunkToVmMemoryStat() {
-        final long TIMESTAMP = 1234l;
-        final int VM_ID = 4567;
-
-        final long EDEN_USED = 1;
-        final long EDEN_CAPACITY = 2;
-        final long EDEN_MAX_CAPACITY = 3;
-        
-        final long S0_USED = 4;
-        final long S0_CAPACITY = 5;
-        final long S0_MAX_CAPACITY = 6;
-        
-        final long S1_USED = 7;
-        final long S1_CAPACITY = 8;
-        final long S1_MAX_CAPACITY = 9;
-        
-        final long OLD_USED = 10;
-        final long OLD_CAPACITY = 11;
-        final long OLD_MAX_CAPACITY = 12;
-        
-        final long PERM_USED = 13;
-        final long PERM_CAPACITY = 14;
-        final long PERM_MAX_CAPACITY = 15;
-        
-        Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
-
-        chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(Key.VM_ID, VM_ID);
-
-        chunk.put(VmMemoryStatDAO.edenGenKey, "new");
-        chunk.put(VmMemoryStatDAO.edenCollectorKey, "new-collector");
-        chunk.put(VmMemoryStatDAO.edenUsedKey, EDEN_USED);
-        chunk.put(VmMemoryStatDAO.edenCapacityKey, EDEN_CAPACITY);
-        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, EDEN_MAX_CAPACITY);
-
-        chunk.put(VmMemoryStatDAO.s0GenKey, "new");
-        chunk.put(VmMemoryStatDAO.s0CollectorKey, "new-collector");
-        chunk.put(VmMemoryStatDAO.s0UsedKey, S0_USED);
-        chunk.put(VmMemoryStatDAO.s0CapacityKey, S0_CAPACITY);
-        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, S0_MAX_CAPACITY);
-
-        chunk.put(VmMemoryStatDAO.s1GenKey, "new");
-        chunk.put(VmMemoryStatDAO.s1CollectorKey, "new-collector");
-        chunk.put(VmMemoryStatDAO.s1UsedKey, S1_USED);
-        chunk.put(VmMemoryStatDAO.s1CapacityKey, S1_CAPACITY);
-        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, S1_MAX_CAPACITY);
-
-        chunk.put(VmMemoryStatDAO.oldGenKey, "old");
-        chunk.put(VmMemoryStatDAO.oldCollectorKey, "old-collector");
-        chunk.put(VmMemoryStatDAO.oldUsedKey, OLD_USED);
-        chunk.put(VmMemoryStatDAO.oldCapacityKey, OLD_CAPACITY);
-        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, OLD_MAX_CAPACITY);
-
-        chunk.put(VmMemoryStatDAO.permGenKey, "perm");
-        chunk.put(VmMemoryStatDAO.permCollectorKey, "perm-collector");
-        chunk.put(VmMemoryStatDAO.permUsedKey, PERM_USED);
-        chunk.put(VmMemoryStatDAO.permCapacityKey, PERM_CAPACITY);
-        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, PERM_MAX_CAPACITY);
-
-        VmMemoryStat stat = new VmMemoryStatConverter().fromChunk(chunk);
-
-        assertNotNull(stat);
-        assertEquals(TIMESTAMP, stat.getTimeStamp());
-        assertEquals(VM_ID, stat.getVmId());
-
-        assertEquals(3, stat.getGenerations().size());
-
-        Generation newGen = stat.getGeneration("new");
-        assertNotNull(newGen);
-        assertEquals(3, newGen.spaces.size());
-        assertEquals("new-collector", newGen.collector);
-        
-        Space eden = newGen.getSpace("eden");
-        assertNotNull(eden);
-        assertEquals(EDEN_USED, eden.used);
-        assertEquals(EDEN_CAPACITY, eden.capacity);
-        assertEquals(EDEN_MAX_CAPACITY, eden.maxCapacity);
-        
-        Space s0 = newGen.getSpace("s0");
-        assertNotNull(s0);
-        assertEquals(S0_USED, s0.used);
-        assertEquals(S0_CAPACITY, s0.capacity);
-        assertEquals(S0_MAX_CAPACITY, s0.maxCapacity);
-        
-        Space s1 = newGen.getSpace("s1");
-        assertNotNull(s1);
-        assertEquals(S1_USED, s1.used);
-        assertEquals(S1_CAPACITY, s1.capacity);
-        assertEquals(S1_MAX_CAPACITY, s1.maxCapacity);
-        
-        Generation oldGen = stat.getGeneration("old");
-        assertNotNull(oldGen);
-        assertEquals(1, oldGen.spaces.size());
-        assertEquals("old-collector", oldGen.collector);
-
-        Space old = oldGen.getSpace("old");
-        assertNotNull(old);
-        assertEquals(OLD_USED, old.used);
-        assertEquals(OLD_CAPACITY, old.capacity);
-        assertEquals(OLD_MAX_CAPACITY, old.maxCapacity);
-        
-        Generation permGen = stat.getGeneration("perm");
-        assertNotNull(permGen);
-        assertEquals(1, permGen.spaces.size());
-        assertEquals("perm-collector", permGen.collector);
-        
-        Space permSpace = permGen.getSpace("perm");
-        assertNotNull(permSpace);
-        assertEquals(PERM_USED, permSpace.used);
-        assertEquals(PERM_CAPACITY, permSpace.capacity);
-        assertEquals(PERM_MAX_CAPACITY, permSpace.maxCapacity);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Cursor.SortDirection;
-import com.redhat.thermostat.common.storage.Key;
-import com.redhat.thermostat.common.storage.Storage;
-
-public class VmMemoryStatDAOTest {
-    @Test
-    public void testCategories() {
-        Collection<Key<?>> keys;
-
-        assertEquals("vm-memory-stats", VmMemoryStatDAO.vmMemoryStatsCategory.getName());
-        keys = VmMemoryStatDAO.vmMemoryStatsCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agent-id", false)));
-        assertTrue(keys.contains(new Key<Integer>("vm-id", false)));
-        assertTrue(keys.contains(new Key<Long>("timestamp", false)));
-        assertTrue(keys.contains(new Key<String>("eden.gen", false)));
-        assertTrue(keys.contains(new Key<String>("eden.collector", false)));
-        assertTrue(keys.contains(new Key<Long>("eden.capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("eden.max-capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("eden.used", false)));
-        assertTrue(keys.contains(new Key<String>("s0.gen", false)));
-        assertTrue(keys.contains(new Key<String>("s0.collector", false)));
-        assertTrue(keys.contains(new Key<Long>("s0.capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("s0.max-capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("s0.used", false)));
-        assertTrue(keys.contains(new Key<String>("s1.gen", false)));
-        assertTrue(keys.contains(new Key<String>("s1.collector", false)));
-        assertTrue(keys.contains(new Key<Long>("s1.capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("s1.max-capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("s1.used", false)));
-        assertTrue(keys.contains(new Key<String>("old.gen", false)));
-        assertTrue(keys.contains(new Key<String>("old.collector", false)));
-        assertTrue(keys.contains(new Key<Long>("old.capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("old.max-capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("old.used", false)));
-        assertTrue(keys.contains(new Key<String>("perm.gen", false)));
-        assertTrue(keys.contains(new Key<String>("perm.collector", false)));
-        assertTrue(keys.contains(new Key<Long>("perm.capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("perm.max-capacity", false)));
-        assertTrue(keys.contains(new Key<Long>("perm.used", false)));
-        assertEquals(28, keys.size());
-    }
-
-    @Test
-    public void testGetLatest() {
-        final int VM_ID = 0xcafe;
-        final String AGENT_ID = "agent";
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn(AGENT_ID);
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(VM_ID);
-
-        Storage storage = mock(Storage.class);
-
-        final Object[] savedQuery = new Object[1];
-        final Cursor cursor = mock(Cursor.class);
-        when(storage.findAll(any(Chunk.class))).thenAnswer(new Answer<Cursor>() {
-            @Override
-            public Cursor answer(InvocationOnMock invocation) throws Throwable {
-                savedQuery[0] = invocation.getArguments()[0];
-                return cursor;
-            }
-
-        });
-        when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor);
-        when(cursor.limit(any(Integer.class))).thenReturn(cursor);
-        when(cursor.hasNext()).thenReturn(false);
-
-        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
-        impl.getLatestMemoryStat(vmRef);
-
-        @SuppressWarnings("rawtypes")
-        ArgumentCaptor<Key> sortKey = ArgumentCaptor.forClass(Key.class);
-        ArgumentCaptor<SortDirection> sortDirection = ArgumentCaptor.forClass(SortDirection.class);
-        verify(cursor).sort(sortKey.capture(), sortDirection.capture());
-
-        Chunk query = (Chunk) savedQuery[0];
-        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-        assertEquals((Integer)VM_ID, query.get(Key.VM_ID));
-
-        assertTrue(sortKey.getValue().equals(Key.TIMESTAMP));
-        assertTrue(sortDirection.getValue().equals(SortDirection.DESCENDING));
-    }
-
-    @Test
-    public void testGetLatestReturnsNullWhenStorageEmpty() {
-        final int VM_ID = 0xcafe;
-        final String AGENT_ID = "agent";
-
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getAgentId()).thenReturn(AGENT_ID);
-
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn(VM_ID);
-
-        Cursor cursor = mock(Cursor.class);
-        when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor);
-        when(cursor.limit(any(Integer.class))).thenReturn(cursor);
-        when(cursor.hasNext()).thenReturn(false);
-        when(cursor.next()).thenReturn(null);
-
-        Storage storage = mock(Storage.class);
-        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
-
-        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
-        VmMemoryStat latest = impl.getLatestMemoryStat(vmRef);
-        assertTrue(latest == null);
-    }
-
-    @Test
-    public void testPutVmMemoryStat() {
-
-        List<Generation> generations = new ArrayList<Generation>();
-
-        int i = 0;
-        for (String genName: new String[] { "new", "old", "perm" }) {
-            Generation gen = new Generation();
-            gen.name = genName;
-            gen.collector = gen.name;
-            generations.add(gen);
-            List<Space> spaces = new ArrayList<Space>();
-            gen.spaces = spaces;
-            String[] spaceNames = null;
-            if (genName.equals("new")) {
-                spaceNames = new String[] { "eden", "s0", "s1" };
-            } else if (genName.equals("old")) {
-                spaceNames = new String[] { "old" };
-            } else {
-                spaceNames = new String[] { "perm" };
-            }
-            for (String spaceName: spaceNames) {
-                Space space = new Space();
-                space.name = spaceName;
-                space.index = 0;
-                space.used = i++;
-                space.capacity = i++;
-                space.maxCapacity = i++;
-                spaces.add(space);
-            }
-        }
-        VmMemoryStat stat = new VmMemoryStat(1, 2, generations);
-
-        Storage storage = mock(Storage.class);
-        VmMemoryStatDAO dao = new VmMemoryStatDAOImpl(storage);
-        dao.putVmMemoryStat(stat);
-
-        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
-        verify(storage).putChunk(arg.capture());
-        Chunk chunk = arg.getValue();
-
-        assertEquals(VmMemoryStatDAO.vmMemoryStatsCategory, chunk.getCategory());
-        assertEquals((Long) 1l, chunk.get(new Key<Long>("timestamp", false)));
-        assertEquals((Integer) 2, chunk.get(new Key<Integer>("vm-id", false)));
-        assertEquals("new", chunk.get(new Key<String>("eden.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("eden.collector", false)));
-        assertEquals((Long) 0l, chunk.get(new Key<Long>("eden.used", false)));
-        assertEquals((Long) 1l, chunk.get(new Key<Long>("eden.capacity", false)));
-        assertEquals((Long) 2l, chunk.get(new Key<Long>("eden.max-capacity", false)));
-        assertEquals("new", chunk.get(new Key<String>("s0.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("s0.collector", false)));
-        assertEquals((Long) 3l, chunk.get(new Key<Long>("s0.used", false)));
-        assertEquals((Long) 4l, chunk.get(new Key<Long>("s0.capacity", false)));
-        assertEquals((Long) 5l, chunk.get(new Key<Long>("s0.max-capacity", false)));
-        assertEquals("new", chunk.get(new Key<String>("s1.gen", false)));
-        assertEquals("new", chunk.get(new Key<String>("s1.collector", false)));
-        assertEquals((Long) 6l, chunk.get(new Key<Long>("s1.used", false)));
-        assertEquals((Long) 7l, chunk.get(new Key<Long>("s1.capacity", false)));
-        assertEquals((Long) 8l, chunk.get(new Key<Long>("s1.max-capacity", false)));
-        assertEquals("old", chunk.get(new Key<String>("old.gen", false)));
-        assertEquals("old", chunk.get(new Key<String>("old.collector", false)));
-        assertEquals((Long) 9l, chunk.get(new Key<Long>("old.used", false)));
-        assertEquals((Long) 10l, chunk.get(new Key<Long>("old.capacity", false)));
-        assertEquals((Long) 11l, chunk.get(new Key<Long>("old.max-capacity", false)));
-        assertEquals("perm", chunk.get(new Key<String>("perm.gen", false)));
-        assertEquals("perm", chunk.get(new Key<String>("perm.collector", false)));
-        assertEquals((Long) 12l, chunk.get(new Key<Long>("perm.used", false)));
-        assertEquals((Long) 13l, chunk.get(new Key<Long>("perm.capacity", false)));
-        assertEquals((Long) 14l, chunk.get(new Key<Long>("perm.max-capacity", false)));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/model/TimeStampedPojoCorrelatorTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.model;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Iterator;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.model.TimeStampedPojoCorrelator.Correlation;
-
-public class TimeStampedPojoCorrelatorTest {
-
-    private static class TestTimeStampedPojo implements TimeStampedPojo {
-
-        private long timestamp;
-
-        private TestTimeStampedPojo(long timestamp) {
-            this.timestamp = timestamp;
-        }
-
-        @Override
-        public long getTimeStamp() {
-            return timestamp;
-        }
-        
-    }
-
-    @Test
-    public void testOneSeries() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(1);
-        correlator.add(0, new TestTimeStampedPojo(3));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(2));
-
-        Iterator<Correlation> i = correlator.iterator();
-
-        assertTrue(i.hasNext());
-        Correlation correlation1 = i.next();
-        assertEquals(1, correlation1.get(0).getTimeStamp());
-        assertEquals(1, correlation1.getTimeStamp());
-        assertTrue(i.hasNext());
-        Correlation correlation2 = i.next();
-        assertEquals(2, correlation2.get(0).getTimeStamp());
-        assertEquals(2, correlation2.getTimeStamp());
-        assertTrue(i.hasNext());
-        Correlation correlation3 = i.next();
-        assertEquals(3, correlation3.get(0).getTimeStamp());
-        assertEquals(3, correlation3.getTimeStamp());
-        assertFalse(i.hasNext());
-    }
-
-    @Test(expected=UnsupportedOperationException.class)
-    public void testOneSeriesRemove() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(1);
-        correlator.add(0, new TestTimeStampedPojo(3));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(2));
-
-        Iterator<Correlation> i = correlator.iterator();
-        i.next();
-        i.remove();
-    }
-
-    @Test
-    public void test3SeriesInterleaving() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(9));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(4));
-        correlator.add(1, new TestTimeStampedPojo(8));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(5));
-        correlator.add(2, new TestTimeStampedPojo(7));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(6));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 4, 4l, 2l, 3l);
-        assertNextCorrelation(i, 5, 4l, 5l, 3l);
-        assertNextCorrelation(i, 6, 4l, 5l, 6l);
-        assertNextCorrelation(i, 7, 4l, 5l, 7l);
-        assertNextCorrelation(i, 8, 4l, 8l, 7l);
-        assertNextCorrelation(i, 9, 9l, 8l, 7l);
-        assertFalse(i.hasNext());
-    }
-
-    @Test
-    public void test3SeriesColliding() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(3));
-        correlator.add(0, new TestTimeStampedPojo(2));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(1));
-        correlator.add(1, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(1));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(2));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, 1l, 1l);
-        assertNextCorrelation(i, 2, 2l, 2l, 2l);
-        assertNextCorrelation(i, 3, 3l, 3l, 3l);
-        assertFalse(i.hasNext());
-    }
-
-    @Test
-    public void test3SeriesMissing1() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(3));
-        correlator.add(0, new TestTimeStampedPojo(2));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(1));
-        correlator.add(1, new TestTimeStampedPojo(3));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, 1l, null);
-        assertNextCorrelation(i, 2, 2l, 2l, null);
-        assertNextCorrelation(i, 3, 3l, 3l, null);
-        assertFalse(i.hasNext());
-    }
-
-    @Test
-    public void test3SeriesEquals() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(3));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertFalse(i.hasNext());
-    }
-
-    @Test
-    public void test3SeriesContinuous() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(9));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(4));
-        correlator.add(1, new TestTimeStampedPojo(8));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(5));
-        correlator.add(2, new TestTimeStampedPojo(7));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(6));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 4, 4l, 2l, 3l);
-        assertNextCorrelation(i, 5, 4l, 5l, 3l);
-        assertNextCorrelation(i, 6, 4l, 5l, 6l);
-        assertNextCorrelation(i, 7, 4l, 5l, 7l);
-        assertNextCorrelation(i, 8, 4l, 8l, 7l);
-        assertNextCorrelation(i, 9, 9l, 8l, 7l);
-        assertFalse(i.hasNext());
-
-        correlator.clear();
-        correlator.add(0, new TestTimeStampedPojo(10));
-        correlator.add(1, new TestTimeStampedPojo(11));
-        correlator.add(2, new TestTimeStampedPojo(12));
-
-        Iterator<Correlation> i2 = correlator.iterator();
-        assertNextCorrelation(i2, 10, 10l, 8l, 7l);
-        assertNextCorrelation(i2, 11, 10l, 11l, 7l);
-        assertNextCorrelation(i2, 12, 10l, 11l, 12l);
-        assertFalse(i2.hasNext());
-    }
-
-    @Test
-    public void test3SeriesContinuousNoData() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(9));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(4));
-        correlator.add(1, new TestTimeStampedPojo(8));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(5));
-        correlator.add(2, new TestTimeStampedPojo(7));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(6));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 4, 4l, 2l, 3l);
-        assertNextCorrelation(i, 5, 4l, 5l, 3l);
-        assertNextCorrelation(i, 6, 4l, 5l, 6l);
-        assertNextCorrelation(i, 7, 4l, 5l, 7l);
-        assertNextCorrelation(i, 8, 4l, 8l, 7l);
-        assertNextCorrelation(i, 9, 9l, 8l, 7l);
-        assertFalse(i.hasNext());
-
-        correlator.clear();
-
-        Iterator<Correlation> i2 = correlator.iterator();
-        assertFalse(i2.hasNext());
-    }
-
-    @Test
-    public void test3SeriesContinuousOnlySingleSeries() {
-        TimeStampedPojoCorrelator correlator = new TimeStampedPojoCorrelator(3);
-        correlator.add(0, new TestTimeStampedPojo(9));
-        correlator.add(0, new TestTimeStampedPojo(1));
-        correlator.add(0, new TestTimeStampedPojo(4));
-        correlator.add(1, new TestTimeStampedPojo(8));
-        correlator.add(1, new TestTimeStampedPojo(2));
-        correlator.add(1, new TestTimeStampedPojo(5));
-        correlator.add(2, new TestTimeStampedPojo(7));
-        correlator.add(2, new TestTimeStampedPojo(3));
-        correlator.add(2, new TestTimeStampedPojo(6));
-
-        Iterator<Correlation> i = correlator.iterator();
-        assertNextCorrelation(i, 1, 1l, null, null);
-        assertNextCorrelation(i, 2, 1l, 2l, null);
-        assertNextCorrelation(i, 3, 1l, 2l, 3l);
-        assertNextCorrelation(i, 4, 4l, 2l, 3l);
-        assertNextCorrelation(i, 5, 4l, 5l, 3l);
-        assertNextCorrelation(i, 6, 4l, 5l, 6l);
-        assertNextCorrelation(i, 7, 4l, 5l, 7l);
-        assertNextCorrelation(i, 8, 4l, 8l, 7l);
-        assertNextCorrelation(i, 9, 9l, 8l, 7l);
-        assertFalse(i.hasNext());
-
-        correlator.clear();
-        correlator.add(0, new TestTimeStampedPojo(10));
-
-        Iterator<Correlation> i2 = correlator.iterator();
-        assertNextCorrelation(i2, 10, 10l, 8l, 7l);
-        assertFalse(i2.hasNext());
-    }
-
-    private void assertNextCorrelation(Iterator<Correlation> iter, long timestamp, Long... timestamps) {
-        assertTrue(iter.hasNext());
-        Correlation correlation = iter.next();
-        assertEquals(timestamp, correlation.getTimeStamp());
-        for (int i = 0 ; i < timestamps.length; i++) {
-            if (timestamps[i] == null) {
-                assertEquals(null, correlation.get(i));
-            } else {
-                assertEquals(timestamps[i].longValue(), correlation.get(i).getTimeStamp());
-            }
-        }
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/BackendInformationTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Map;
-
-import org.junit.Test;
-
-public class BackendInformationTest {
-
-    @Test
-    public void testConfigurationNotNull() {
-        BackendInformation backendInfo = new BackendInformation();
-        Map<String,String> config = backendInfo.getConfiguration();
-        assertNotNull(config);
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/CategoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collection;
-
-import org.junit.Test;
-
-public class CategoryTest {
-
-    @Test
-    public void testHasBeenRegistered() {
-        Category category1 = new Category("testHasBeenRegistered");
-        assertFalse(category1.hasBeenRegistered());
-        ConnectionKey connKey = new ConnectionKey(){};
-        category1.setConnectionKey(connKey);
-        assertTrue(category1.hasBeenRegistered());
-    }
-
-    @Test
-    public void testGetKey() {
-        Key<String> key1 = new Key<String>("key1", false);
-        Category category = new Category("testGetKey", key1);
-        assertEquals(key1, category.getKey("key1"));
-    }
-
-    @Test
-    public void testGetNonExistingKey() {
-        Key<String> key1 = new Key<String>("key1", false);
-        Category category = new Category("testGetNonExistingKey", key1);
-        assertNull(category.getKey("key2"));
-    }
-
-    @Test
-    public void testGetKeys() {
-        Key<String> key1 = new Key<String>("key1", false);
-        Key<String> key2 = new Key<String>("key2", false);
-        Key<String> key3 = new Key<String>("key3", false);
-        Key<String> key4 = new Key<String>("key4", false);
-        Category category = new Category("testGetKeys", key1, key2, key3, key4);
-        assertEquals(4, category.getKeys().size());
-        assertTrue(category.getKeys().contains(key1));
-        assertTrue(category.getKeys().contains(key2));
-        assertTrue(category.getKeys().contains(key3));
-        assertTrue(category.getKeys().contains(key4));
-    }
-
-    @Test(expected=UnsupportedOperationException.class)
-    public void verifyThatKeysAreUnmodifiable() {
-        Key<String> key1 = new Key<String>("key1", false);
-        Key<String> key2 = new Key<String>("key2", false);
-        Key<String> key3 = new Key<String>("key3", false);
-        Category category = new Category("verifyThatKeysAreUnmodifiable", key1, key2, key3);
-
-        Collection<Key<?>> keys = category.getKeys();
-
-        keys.remove(key1);
-
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/ChunkConverterTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,334 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-
-public class ChunkConverterTest {
-
-    private static final Key<String> key1 = new Key<>("key1", false);
-    private static final Key<String> key2 = new Key<>("key2", false);
-    private static final Key<String> key3 = new Key<>("key3", false);
-    private static final Key<String> key4 = new Key<>("key4", false);
-    private static final Key<String> key5 = new Key<>("key5", false);
-
-    private static final Key<String> key1_key1 = new Key<>("key1.key1", false);
-    private static final Key<String> key1_key2 = new Key<>("key1.key2", false);
-    private static final Key<String> key1_key2_key1 = new Key<>("key1.key2.key1", false);
-    private static final Key<String> key1_key2_key2 = new Key<>("key1.key2.key2", false);
-    private static final Key<String> key1_key2_key3 = new Key<>("key1.key2.key3", false);
-    private static final Key<String> key2_key1 = new Key<>("key2.key1", false);
-    private static final Key<String> key2_key2 = new Key<>("key2.key2", false);
-    private static final Key<String> key2_key3 = new Key<>("key2.key3", false);
-
-    private static final String mongoId = "_id";
-    private static final Key<String> invalidMongoIdKey = new Key<>(mongoId, false);
-
-    private static final Category testCategory = new Category("ChunkConverterTest", key1, key2, key3, key4, key5,
-                                                             key1_key1, key1_key2, key2_key1, key2_key2, key2_key3,
-                                                             key1_key2_key1, key1_key2_key2, key1_key2_key3);
-    private static final Category smallerCategory = new Category("SmallerTest", key1, key2);
-
-    @Test
-    public void verifyBasicChunkToDBObject() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, "test1");
-
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbObject = converter.chunkToDBObject(chunk);
-
-        assertEquals(1, dbObject.keySet().size());
-        assertTrue(dbObject.keySet().contains("key1"));
-        assertEquals("test1", dbObject.get("key1"));
-    }
-
-    @Test
-    public void verifyChunkToDBObjectInOrder() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key5, "test1");
-        chunk.put(key4, "test2");
-        chunk.put(key3, "test3");
-        chunk.put(key2, "test4");
-        chunk.put(key1, "test5");
-
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbObject = converter.chunkToDBObject(chunk);
-
-        assertEquals(5, dbObject.keySet().size());
-        assertArrayEquals(new String[]{"key5", "key4", "key3", "key2", "key1"}, dbObject.keySet().toArray());
-    }
-
-    @Test
-    public void verifyBasicDBObjectToChunk() {
-        BasicDBObject dbObject = new BasicDBObject();
-        dbObject.put("key1", "test1");
-
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
-
-        assertSame(testCategory, chunk.getCategory());
-        assertEquals(1, chunk.getKeys().size());
-        assertTrue(chunk.getKeys().contains(key1));
-        assertEquals("test1", chunk.get(key1));
-
-    }
-
-    @Test
-    public void verifyDBObjectToChunkInOrder() {
-        BasicDBObject dbObject = new BasicDBObject();
-        dbObject.put("key5", "test1");
-        dbObject.put("key4", "test2");
-        dbObject.put("key3", "test3");
-        dbObject.put("key2", "test4");
-        dbObject.put("key1", "test5");
-
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
-
-        assertSame(testCategory, chunk.getCategory());
-        assertEquals(5, chunk.getKeys().size());
-        assertArrayEquals(new Key<?>[]{ key5, key4, key3, key2, key1 }, chunk.getKeys().toArray());
-        assertEquals("test5", chunk.get(key1));
-        assertEquals("test4", chunk.get(key2));
-        assertEquals("test3", chunk.get(key3));
-        assertEquals("test2", chunk.get(key4));
-        assertEquals("test1", chunk.get(key5));
-
-    }
-
-    @Test
-    public void verifySimpleNestedChunkToObject() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1_key1, "test1");
-
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbObject = converter.chunkToDBObject(chunk);
-
-        assertEquals(1, dbObject.keySet().size());
-        assertTrue(dbObject.keySet().contains("key1"));
-        DBObject nested = (DBObject) dbObject.get("key1");
-        assertEquals(1, nested.keySet().size());
-        assertTrue(nested.keySet().contains("key1"));
-        assertEquals("test1", nested.get("key1"));
-    }
-
-    @Test
-    public void verifyComplexNestedChunkToObject() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1_key1, "test1");
-        chunk.put(key1_key2, "test2");
-        chunk.put(key2_key1, "test3");
-        chunk.put(key2_key2, "test4");
-        chunk.put(key2_key3, "test5");
-        chunk.put(key3, "test6");
-
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbObject = converter.chunkToDBObject(chunk);
-
-        assertEquals(3, dbObject.keySet().size());
-        assertTrue(dbObject.keySet().contains("key1"));
-        assertTrue(dbObject.keySet().contains("key2"));
-        assertTrue(dbObject.keySet().contains("key3"));
-        assertEquals("test6", dbObject.get("key3"));
-
-        DBObject nested1 = (DBObject) dbObject.get("key1");
-        assertEquals(2, nested1.keySet().size());
-        assertTrue(nested1.keySet().contains("key1"));
-        assertTrue(nested1.keySet().contains("key2"));
-        assertEquals("test1", nested1.get("key1"));
-        assertEquals("test2", nested1.get("key2"));
-
-        DBObject nested2 = (DBObject) dbObject.get("key2");
-        assertEquals(3, nested2.keySet().size());
-        assertTrue(nested2.keySet().contains("key1"));
-        assertTrue(nested2.keySet().contains("key2"));
-        assertTrue(nested2.keySet().contains("key3"));
-        assertEquals("test3", nested2.get("key1"));
-        assertEquals("test4", nested2.get("key2"));
-        assertEquals("test5", nested2.get("key3"));
-    }
-
-    @Test
-    public void verifyComplex3LevelChunkToObject() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1_key1, "test1");
-        chunk.put(key1_key2_key1, "test3");
-        chunk.put(key1_key2_key2, "test4");
-        chunk.put(key1_key2_key3, "test5");
-        chunk.put(key3, "test6");
-
-        ChunkConverter converter = new ChunkConverter();
-        DBObject dbObject = converter.chunkToDBObject(chunk);
-
-        assertEquals(2, dbObject.keySet().size());
-        assertTrue(dbObject.keySet().contains("key1"));
-        assertTrue(dbObject.keySet().contains("key3"));
-        assertEquals("test6", dbObject.get("key3"));
-
-        DBObject nested1 = (DBObject) dbObject.get("key1");
-        assertEquals(2, nested1.keySet().size());
-        assertTrue(nested1.keySet().contains("key1"));
-        assertTrue(nested1.keySet().contains("key2"));
-        assertEquals("test1", nested1.get("key1"));
-
-        DBObject nested2 = (DBObject) nested1.get("key2");
-        assertEquals(3, nested2.keySet().size());
-        assertTrue(nested2.keySet().contains("key1"));
-        assertTrue(nested2.keySet().contains("key2"));
-        assertTrue(nested2.keySet().contains("key3"));
-        assertEquals("test3", nested2.get("key1"));
-        assertEquals("test4", nested2.get("key2"));
-        assertEquals("test5", nested2.get("key3"));
-    }
-
-    @Test
-    public void verifySimpleNestedObjectToChunk() {
-        BasicDBObject nested = new BasicDBObject();
-        nested.put("key1", "test1");
-        BasicDBObject dbObject = new BasicDBObject();
-        dbObject.put("key1", nested);
-
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
-
-        assertSame(testCategory, chunk.getCategory());
-        assertEquals(1, chunk.getKeys().size());
-        assertTrue(chunk.getKeys().contains(key1_key1));
-        assertEquals("test1", chunk.get(key1_key1));
-    }
-
-    @Test
-    public void verifyComplexNestedObjectToChunk() {
-        BasicDBObject nested1 = new BasicDBObject();
-        nested1.put("key1", "test1");
-        nested1.put("key2", "test2");
-
-        BasicDBObject nested2 = new BasicDBObject();
-        nested2.put("key1", "test3");
-        nested2.put("key2", "test4");
-        nested2.put("key3", "test5");
-
-        BasicDBObject dbObject = new BasicDBObject();
-        dbObject.put("key1", nested1);
-        dbObject.put("key2", nested2);
-        dbObject.put("key3", "test6");
-
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
-
-        assertSame(testCategory, chunk.getCategory());
-
-        assertEquals(6, chunk.getKeys().size());
-        assertTrue(chunk.getKeys().contains(key1_key1));
-        assertTrue(chunk.getKeys().contains(key1_key2));
-        assertTrue(chunk.getKeys().contains(key2_key1));
-        assertTrue(chunk.getKeys().contains(key2_key2));
-        assertTrue(chunk.getKeys().contains(key2_key3));
-        assertTrue(chunk.getKeys().contains(key3));
-        assertEquals("test1", chunk.get(key1_key1));
-        assertEquals("test2", chunk.get(key1_key2));
-        assertEquals("test3", chunk.get(key2_key1));
-        assertEquals("test4", chunk.get(key2_key2));
-        assertEquals("test5", chunk.get(key2_key3));
-        assertEquals("test6", chunk.get(key3));
-    }
-
-    @Test
-    public void verifyComplex3LevelObjectToChunk() {
-
-        BasicDBObject nested2 = new BasicDBObject();
-        nested2.put("key1", "test3");
-        nested2.put("key2", "test4");
-        nested2.put("key3", "test5");
-
-        BasicDBObject nested1 = new BasicDBObject();
-        nested1.put("key1", "test1");
-        nested1.put("key2", nested2);
-
-        BasicDBObject dbObject = new BasicDBObject();
-        dbObject.put("key1", nested1);
-        dbObject.put("key3", "test6");
-
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(dbObject, testCategory);
-
-        assertSame(testCategory, chunk.getCategory());
-
-        assertEquals(5, chunk.getKeys().size());
-        assertTrue(chunk.getKeys().contains(key1_key1));
-        assertTrue(chunk.getKeys().contains(key1_key2_key1));
-        assertTrue(chunk.getKeys().contains(key1_key2_key2));
-        assertTrue(chunk.getKeys().contains(key1_key2_key3));
-        assertTrue(chunk.getKeys().contains(key3));
-
-        assertEquals("test1", chunk.get(key1_key1));
-        assertEquals("test3", chunk.get(key1_key2_key1));
-        assertEquals("test4", chunk.get(key1_key2_key2));
-        assertEquals("test5", chunk.get(key1_key2_key3));
-        assertEquals("test6", chunk.get(key3));
-    }
-
-    @Test
-    public void verifyDBObjectToChunkIgnoresMongoID() {
-        DBObject obj = new BasicDBObject(mongoId, "mongo_private_info");
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(obj, new Category("invalidCategory", invalidMongoIdKey));
-
-        assertEquals(0, chunk.getKeys().size());
-    }
-
-    @Test
-    public void verifyDBObjectToChunkAvoidsNonExistentKeys() {
-        DBObject obj = new BasicDBObject("key1", "data1");
-        obj.put("key2", "data2");
-        obj.put("key3", "data3"); // This one is not a part of smallerCategory
-        ChunkConverter converter = new ChunkConverter();
-        Chunk chunk = converter.dbObjectToChunk(obj, smallerCategory);
-
-        assertEquals(2, chunk.getKeys().size());
-        assertFalse(chunk.getKeys().contains(key3));
-        assertTrue(chunk.getKeys().contains(key1));
-        assertTrue(chunk.getKeys().contains(key2));
-        assertEquals("data1", chunk.get(key1));
-        assertEquals("data2", chunk.get(key2));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/ChunkTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-public class ChunkTest {
-
-    private static final Key<String> key1 = new Key<>("key1", false);
-    private static final Key<String> key2 = new Key<>("key2", false);
-    private static final Key<String> key3 = new Key<>("key3", false);
-    private static final Key<String> key4 = new Key<>("key4", false);
-    private static final Key<String> key5 = new Key<>("key5", false);
-    private static final Key<Integer> key6 = new Key<>("key6", false);
-    private static final Key<Object> key7 = new Key<>("key7", false);
-
-    private static final String value1 = "test1";
-    private static final String value2 = "test2";
-    private static final String value3 = "test3";
-    private static final String value4 = "test4";
-    private static final String value5 = "test5";
-    private static final int value6 = 12345;
-    private static final Object value7 = "test7";
-
-    private static final Category testCategory = new Category("ChunkTest", key1, key2, key3, key4, key5);
-    private static final Category testCategory2 = new Category("ChunkTest2", key1, key2, key3, key4, key5);
-
-    @Test
-    public void verifyGetCategoryNotNull() {
-        Chunk chunk = new Chunk(testCategory, false);
-        Category cat = chunk.getCategory();
-        assertNotNull(cat);
-    }
-
-    @Test
-    public void verifyGetCategoryReturnsCorrectCategory() {
-        Chunk chunk = new Chunk(testCategory, false);
-        Category cat = chunk.getCategory();
-        assertEquals(cat, testCategory);
-    }
-
-    @Test
-    public void verifyGetReplaceReturnsCorrectValue() {
-        Chunk chunk = new Chunk(testCategory, false);
-        boolean replace = chunk.getReplace();
-        assertFalse(replace);
-        chunk = new Chunk(testCategory, true);
-        replace = chunk.getReplace();
-        assertTrue(replace);
-    }
-
-    @Test
-    public void verifyPutActuallyPuts() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, value1);
-        int pieces = chunk.getKeys().size();
-        assertEquals(pieces, 1);
-    }
-
-    @Test
-    public void verifyPutPutsCorrectly() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, value1);
-        String value = chunk.get(key1);
-        assertEquals(value, value1);
-    }
-
-    @Test
-    public void verifyPutAcceptsVariousTypes() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, value1);
-        chunk.put(key5, value5);
-        chunk.put(key6, value6);
-        chunk.put(key7, value7);
-        int pieces = chunk.getKeys().size();
-        assertEquals(pieces, 4);
-    }
-
-    @Test
-    public void verifyEntriesAreKeptInOrder() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key5, value5);
-        chunk.put(key4, value4);
-        chunk.put(key3, value3);
-        chunk.put(key2, value2);
-        chunk.put(key1, value1);
-
-        assertArrayEquals(new Key<?>[]{key5, key4, key3, key2, key1}, chunk.getKeys().toArray());
-    }
-
-    @Test
-    public void verifyGetNotNull() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, value1);
-        String value = chunk.get(key1);
-        assertNotNull(value);
-    }
-
-    @Test
-    public void verifyGetNullWhenExpected() {
-        Chunk chunk = new Chunk(testCategory, false);
-        chunk.put(key1, value1);
-        String value = chunk.get(key2);
-        assertNull(value);
-    }
-
-
-    @Test
-    public void testEqualsBasicEquals() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        Chunk chunk2 = new Chunk(testCategory, false);
-        assertTrue(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsDifferentCategory() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        Chunk chunk2 = new Chunk(testCategory2, false);
-        assertFalse(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsDifferentReplace() {
-        // TODO: Do we want to differentiate chunks by that flag? I think not. Maybe it doesn't even belong in chunk.
-        Chunk chunk1 = new Chunk(testCategory, false);
-        Chunk chunk2 = new Chunk(testCategory, true);
-        assertTrue(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsDifferentType() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        assertFalse(chunk1.equals("fluff"));
-    }
-
-    @Test
-    public void testEqualsNull() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        assertFalse(chunk1.equals(null));
-    }
-
-    @Test
-    public void testEqualsDifferentNumberOfValues() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        chunk1.put(key1, "value1");
-        chunk1.put(key2, "value2");
-        Chunk chunk2 = new Chunk(testCategory, true);
-        chunk2.put(key1, "value1");
-        assertFalse(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsDifferentKeys() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        chunk1.put(key1, "value1");
-        chunk1.put(key2, "value2");
-        Chunk chunk2 = new Chunk(testCategory, true);
-        chunk2.put(key1, "value1");
-        chunk2.put(key3, "value2");
-        assertFalse(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsDifferentValues() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        chunk1.put(key1, "value1");
-        chunk1.put(key2, "value2.1");
-        Chunk chunk2 = new Chunk(testCategory, true);
-        chunk2.put(key1, "value1");
-        chunk2.put(key2, "value2.2");
-        assertFalse(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsSameValues() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        chunk1.put(key1, "value1");
-        chunk1.put(key2, "value2");
-        Chunk chunk2 = new Chunk(testCategory, true);
-        chunk2.put(key1, "value1");
-        chunk2.put(key2, "value2");
-        assertTrue(chunk1.equals(chunk2));
-    }
-
-    @Test
-    public void testEqualsNullValues() {
-        Chunk chunk1 = new Chunk(testCategory, false);
-        chunk1.put(key1, "value1");
-        chunk1.put(key2, null);
-        Chunk chunk2 = new Chunk(testCategory, true);
-        chunk2.put(key1, "value1");
-        chunk2.put(key2, null);
-        assertTrue(chunk1.equals(chunk2));
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.storage.Connection;
-import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
-
-public class ConnectionTest {
-
-    private Connection connection;
-
-    private Connection.ConnectionListener listener1;
-    private Connection.ConnectionListener listener2;
-
-    @Before
-    public void setUp() {
-
-        connection = new Connection() {
-            
-            @Override
-            public void disconnect() {
-                // TODO Auto-generated method stub
-                
-            }
-            
-            @Override
-            public void connect() {
-                // TODO Auto-generated method stub
-                
-            }
-        };
-        listener1 = mock(Connection.ConnectionListener.class);
-        listener2 = mock(Connection.ConnectionListener.class);
-        connection.addListener(listener1);
-        connection.addListener(listener2);
-    }
-
-    @After
-    public void tearDown() {
-        connection = null;
-        listener1 = null;
-        listener2 = null;
-    }
-
-    @Test
-    public void testListenersConnecting() throws Exception {
-        verifyListenersStatus(ConnectionStatus.CONNECTING);
-    }
-
-    @Test
-    public void testListenersConnected() throws Exception {
-        verifyListenersStatus(ConnectionStatus.CONNECTED);
-    }
-
-    @Test
-    public void testListenersFailedToConnect() throws Exception {
-        verifyListenersStatus(ConnectionStatus.FAILED_TO_CONNECT);
-    }
-
-    @Test
-    public void testListenersDisconnected() throws Exception {
-        verifyListenersStatus(ConnectionStatus.DISCONNECTED);
-    }
-
-    private void verifyListenersStatus(ConnectionStatus status) {
-        connection.fireChanged(status);
-        verify(listener1).changed(status);
-        verify(listener2).changed(status);
-    }
-
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/KeyTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-public class KeyTest {
-    private static final String name1 = "key1";
-    private static final String name2 = "key2";
-    private static final String name3 = "key3";
-
-    private static final Key<String> key1 = new Key<>(name1, true);
-    private static final Key<String> key2 = new Key<>(name2, true);
-    private static final Key<String> key3 = new Key<>(name3, false);
-    private static final Key<String> key4 = new Key<>(name1, false);
-    private static final Key<String> key5 = new Key<>(name1, true);
-
-    @Test
-    public void verifyConstructorResultsInExpectedValues() {
-        Key<String> key = new Key<>(name1, true);
-        assertEquals(key.getName(), name1);
-        assertTrue(key.isPartialCategoryKey());
-        key = new Key<>(name2, false);
-        assertEquals(key.getName(), name2);
-        assertFalse(key.isPartialCategoryKey());
-    }
-
-    @Test (expected=IllegalArgumentException.class)
-    public void verifyConstructorThrowsExceptionOnNullName() {
-        @SuppressWarnings("unused")
-        Key<String> key = new Key<>(null, true);
-    }
-
-    @Test (expected=IllegalArgumentException.class)
-    public void verifyConstructorThrowsExceptionZeroLengthName() {
-        @SuppressWarnings("unused")
-        Key<String> key = new Key<>("", true);
-    }
-
-    @Test
-    public void verifyGetNameNotNull() {
-        String name = key1.getName();
-        assertNotNull(name);
-    }
-
-    @Test
-    public void verifyGetNameReturnsCorrectName() {
-        String name = key1.getName();
-        assertEquals(name, name1);
-        name = key2.getName();
-        assertEquals(name, name2);
-    }
-
-    @Test
-    public void verifyIsPartialCategoryKeyReturnsCorrectValue() {
-        boolean value = key1.isPartialCategoryKey();
-        assertTrue(value);
-        value = key3.isPartialCategoryKey();
-        assertFalse(value);
-    }
-
-    @Test
-    public void verifyEqualsReturnsCorrectValue() {
-        assertThat(key1, not(equalTo(key2)));
-        assertThat(key1, not(equalTo(key3)));
-        assertThat(key1, not(equalTo(key4)));
-        assertThat(key1, equalTo(key5));
-    }
-
-    @Test
-    public void verifyHashCodeReturnsValidCode() {
-        int key1hash1 = key1.hashCode();
-        int key1hash2 = key1.hashCode();
-        assertEquals(key1hash1, key1hash2);
-        int key5hash1 = key5.hashCode();
-        assertEquals(key1hash1, key5hash1);
-    }
-
-    @Test
-    public void toStringNotNull() {
-        String string1 = key1.toString();
-        assertNotNull(string1);
-    }
-
-    @Test
-    public void toStringReturnsExpectedString() {
-        String string1 = key1.toString();
-        assertEquals(string1, "Key: key1");
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.Mongo;
-import com.mongodb.MongoException;
-import com.mongodb.MongoURI;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
-import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
-
-@PrepareForTest(MongoConnection.class)
-@RunWith(PowerMockRunner.class)
-public class MongoConnectionTest {
-
-    private MongoConnection conn;
-    private ConnectionListener listener;
-
-    @Before
-    public void setUp() {
-        StartupConfiguration conf = mock(StartupConfiguration.class);
-        when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518");
-        conn = new MongoConnection(conf);
-        listener = mock(ConnectionListener.class);
-        conn.addListener(listener);
-    }
-
-    @After
-    public void tearDown() {
-        conn = null;
-    }
-
-    @Test
-    public void testConnectSuccess() throws Exception {
-        DBCollection collection = mock(DBCollection.class);
-        DB db = mock(DB.class);
-        when(db.getCollection("agent-config")).thenReturn(collection);
-        Mongo m = mock(Mongo.class);
-        when(m.getDB(StorageConstants.THERMOSTAT_DB_NAME)).thenReturn(db);
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        conn.connect();
-
-        verify(listener).changed(ConnectionStatus.CONNECTED);
-    }
-
-    @Test
-    public void testConnectIOException() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new IOException());
-        boolean exceptionThrown = false;
-        try {
-            conn.connect();
-        } catch (ConnectionException ex) {
-            exceptionThrown = true;
-        }
-        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
-        assertTrue(exceptionThrown);
-    }
-
-    @Test
-    public void testConnectMongoException() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new MongoException("fluff"));
-        boolean exceptionThrown = false;
-        try {
-            conn.connect();
-        } catch (ConnectionException ex) {
-            exceptionThrown = true;
-        }
-
-        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
-        assertTrue(exceptionThrown);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-
-public class MongoCursorTest {
-
-    private static final Key<String> key1 = new Key<>("key1", false);
-    private static final Key<String> key2 = new Key<>("key2", false);
-    private static final Key<String> key3 = new Key<>("key3", false);
-    private static final Key<String> key4 = new Key<>("key4", false);
-
-    private static final Category testCategory = new Category("MongoCursorTest", key1, key2, key3, key4);
-
-    private DBCursor dbCursor;
-    private Cursor cursor;
-
-    @Before
-    public void setUp() {
-        
-        BasicDBObject value1 = new BasicDBObject();
-        value1.put("key1", "test1");
-        value1.put("key2", "test2");
-        BasicDBObject value2 = new BasicDBObject();
-        value2.put("key3", "test3");
-        value2.put("key4", "test4");
-
-        dbCursor = mock(DBCursor.class);
-        when(dbCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(dbCursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
-        when(dbCursor.sort(any(DBObject.class))).thenReturn(dbCursor);
-        when(dbCursor.limit(anyInt())).thenReturn(dbCursor);
-        cursor = new MongoCursor(dbCursor, testCategory);
-
-    }
-
-    @After
-    public void tearDown() {
-        dbCursor = null;
-        cursor = null;
-    }
-
-    @Test
-    public void verifySimpleCursor() {
-
-        assertTrue(cursor.hasNext());
-        Chunk chunk1 = cursor.next();
-        assertArrayEquals(new Key<?>[]{key1, key2}, chunk1.getKeys().toArray());
-        assertEquals("test1", chunk1.get(key1));
-        assertEquals("test2", chunk1.get(key2));
-
-        assertTrue(cursor.hasNext());
-        Chunk chunk2 = cursor.next();
-        assertArrayEquals(new Key<?>[]{key3, key4}, chunk2.getKeys().toArray());
-        assertEquals("test3", chunk2.get(key3));
-        assertEquals("test4", chunk2.get(key4));
-
-        assertFalse(cursor.hasNext());
-        assertNull(cursor.next());
-    }
-
-    @Test
-    public void verifyCursorSort() {
-        ArgumentCaptor<DBObject> arg = ArgumentCaptor.forClass(DBObject.class);
-        Cursor sorted = cursor.sort(key1, Cursor.SortDirection.ASCENDING);
-
-        verify(dbCursor).sort(arg.capture());
-        DBObject orderByDBObject = arg.getValue();
-        assertEquals(1, orderByDBObject.keySet().size());
-        assertEquals((Integer) Cursor.SortDirection.ASCENDING.getValue(), orderByDBObject.get(key1.getName()));
-        // Verify that the sorted cursor is still return the same number of items. We leave the actual
-        // sorting to Mongo and won't check it here.
-        assertTrue(sorted.hasNext());
-        sorted.next();
-        assertTrue(sorted.hasNext());
-        sorted.next();
-        assertFalse(sorted.hasNext());
-    }
-
-    @Test
-    public void verifyCursorLimit() {
-
-        Cursor sorted = cursor.limit(1);
-
-        verify(dbCursor).limit(1);
-
-        // We cannot really test if the cursor really got limited, this is up to the mongo implementation.
-        // In any case, we can verify that the returned cursor actually is 'active'.
-        assertTrue(sorted.hasNext());
-        sorted.next();
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-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.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-import com.mongodb.MongoURI;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ DBCollection.class, DB.class, Mongo.class, MongoStorage.class, MongoConnection.class })
-public class MongoStorageTest {
-
-    private static final Key<String> key1 = new Key<>("key1", false);
-    private static final Key<String> key2 = new Key<>("key2", false);
-    private static final Key<String> key3 = new Key<>("key3", false);
-    private static final Key<String> key4 = new Key<>("key4", false);
-    private static final Key<String> key5 = new Key<>("key5", false);
-    private static final Category testCategory = new Category("MongoStorageTest", key1, key2, key3, key4, key5);
-    private static final Category emptyTestCategory = new Category("MongoEmptyCategory");
-
-    private StartupConfiguration conf;
-    private Chunk multiKeyQuery;
-    private Mongo m;
-    private DB db;
-    private DBCollection testCollection, emptyTestCollection, mockedCollection;
-
-    private MongoStorage makeStorage() throws Exception {
-        MongoStorage storage = new MongoStorage(conf);
-        storage.mapCategoryToDBCollection(testCategory, testCollection);
-        storage.mapCategoryToDBCollection(emptyTestCategory, emptyTestCollection);
-        return storage;
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        conf = mock(StartupConfiguration.class);
-        when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518");
-        db = PowerMockito.mock(DB.class);
-        m = PowerMockito.mock(Mongo.class);
-        mockedCollection = mock(DBCollection.class);
-        when(m.getDB(anyString())).thenReturn(db);
-        when(db.getCollection("agent-config")).thenReturn(mockedCollection);
-        when(db.collectionExists(anyString())).thenReturn(true);
-
-        BasicDBObject value1 = new BasicDBObject();
-        value1.put("key1", "test1");
-        value1.put("key2", "test2");
-        BasicDBObject value2 = new BasicDBObject();
-        value2.put("key3", "test3");
-        value2.put("key4", "test4");
-
-        multiKeyQuery = new Chunk(testCategory, false);
-        multiKeyQuery.put(key5, "test1");
-        multiKeyQuery.put(key4, "test2");
-        multiKeyQuery.put(key3, "test3");
-        multiKeyQuery.put(key2, "test4");
-        multiKeyQuery.put(key1, "test5");
-
-        DBCursor cursor = mock(DBCursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
-
-        testCollection = PowerMockito.mock(DBCollection.class);
-        when(testCollection.find(any(DBObject.class))).thenReturn(cursor);
-        when(testCollection.find()).thenReturn(cursor);
-        when(testCollection.findOne(any(DBObject.class))).thenReturn(value1);
-        when(testCollection.getCount()).thenReturn(2L);
-        emptyTestCollection = PowerMockito.mock(DBCollection.class);
-        when(emptyTestCollection.getCount()).thenReturn(0L);
-        when(db.collectionExists(anyString())).thenReturn(false);
-        when(db.createCollection(anyString(), any(DBObject.class))).thenReturn(testCollection);
-    }
-
-    @After
-    public void tearDown() {
-        conf = null;
-        m = null;
-        db = null;
-        testCollection = null;
-        emptyTestCollection = null;
-        multiKeyQuery = null;
-    }
-
-    @Test
-    public void testCreateConnectionKey() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        storage.getConnection().connect();
-        Category category = new Category("testCreateConnectionKey");
-        ConnectionKey connKey = storage.createConnectionKey(category);
-        assertNotNull(connKey);
-    }
-
-    @Test 
-    public void verifyFindAllReturnsCursor() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        Cursor cursor = storage.findAll(query);
-        assertNotNull(cursor);
-    }
-
-    @Test
-    public void verifyFindReturnsChunk() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        query.put(key1, "test1");
-        Chunk result = storage.find(query);
-        assertNotNull(result);
-    }
-
-    @Test
-    public void verifyFindAllCallsDBCollectionFind() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        storage.findAll(query);
-        verify(testCollection).find(any(DBObject.class));
-    }
-
-    @Test
-    public void verifyFindCallsDBCollectionFindOne() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        storage.find(query);
-        verify(testCollection).findOne(any(DBObject.class));
-    }
-
-    @Test
-    public void verifyFindAllCallsDBCollectionFindWithCorrectQuery() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        query.put(key1, "test");
-        storage.findAll(query);
-
-        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
-        verify(testCollection).find(findArg.capture());
-
-        DBObject arg = findArg.getValue();
-        assertEquals(1, arg.keySet().size());
-        assertTrue(arg.keySet().contains("key1"));
-        assertEquals("test", arg.get("key1"));
-    }
-
-    @Test
-    public void verifyFindCallsDBCollectionFindOneWithCorrectQuery() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Chunk query = new Chunk(testCategory, false);
-        query.put(key1, "test");
-        storage.find(query);
-
-        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
-        verify(testCollection).findOne(findArg.capture());
-
-        DBObject arg = findArg.getValue();
-        assertEquals(1, arg.keySet().size());
-        assertTrue(arg.keySet().contains("key1"));
-        assertEquals("test", arg.get("key1"));
-    }
-
-    @Test
-    public void verifyFindAllWithMultiKeys() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        storage.findAll(multiKeyQuery);
-
-        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
-        verify(testCollection).find(findArg.capture());
-
-        DBObject arg = findArg.getValue();
-        assertArrayEquals(new String[]{ "key5", "key4", "key3", "key2", "key1" }, arg.keySet().toArray());
-    }
-
-    @Test
-    public void verifyFindWithMultiKeys() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        storage.find(multiKeyQuery);
-
-        ArgumentCaptor<DBObject> findArg = ArgumentCaptor.forClass(DBObject.class);
-        verify(testCollection).findOne(findArg.capture());
-
-        DBObject arg = findArg.getValue();
-        assertArrayEquals(new String[]{ "key5", "key4", "key3", "key2", "key1" }, arg.keySet().toArray());
-    }
-
-    @Test
-    public void verifyFindReturnsCorrectChunk() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        // TODO find a way to test this that isn't just testing mock and converters
-        Chunk query = new Chunk(testCategory, false);
-        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        query.put(key5, "test1");
-
-        Chunk result = storage.find(query);
-
-        assertNotNull(result);
-        assertArrayEquals(new Key<?>[]{key1, key2}, result.getKeys().toArray());
-        assertEquals("test1", result.get(key1));
-        assertEquals("test2", result.get(key2));
-    }
-
-    @Test
-    public void verifyFindAllReturnsCorrectCursor() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        // TODO find a way to test this that isn't just testing MongoCursor
-        Chunk query = new Chunk(testCategory, false);
-        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        query.put(key5, "test1");
-
-        Cursor cursor = storage.findAll(query);
-
-        verifyDefaultCursor(cursor);
-    }
-
-    @Test
-    public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        storage.findAllFromCategory(testCategory);
-        verify(testCollection).find();
-    }
-
-    @Test
-    public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        Cursor cursor = storage.findAllFromCategory(testCategory);
-
-        verifyDefaultCursor(cursor);
-    }
-
-    @Test
-    public void verifyGetCount() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        long count = storage.getCount(testCategory);
-        assertEquals(2, count);
-    }
-
-    @Test
-    public void verifyGetCountForEmptyCategory() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        long count = storage.getCount(emptyTestCategory);
-        assertEquals(0, count);
-    }
-
-    @Test
-    public void verifyGetCountForNonexistentCategory() throws Exception {
-        PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m);
-        MongoStorage storage = makeStorage();
-        storage.getConnection().connect();
-        long count = storage.getCount(new Category("NonExistent"));
-        assertEquals(0, count);
-    }
-
-    private void verifyDefaultCursor(Cursor cursor) {
-        assertTrue(cursor.hasNext());
-        Chunk chunk1 = cursor.next();
-        assertArrayEquals(new Key<?>[]{key1, key2}, chunk1.getKeys().toArray());
-        assertEquals("test1", chunk1.get(key1));
-        assertEquals("test2", chunk1.get(key2));
-
-        assertTrue(cursor.hasNext());
-        Chunk chunk2 = cursor.next();
-        assertArrayEquals(new Key<?>[]{key3, key4}, chunk2.getKeys().toArray());
-        assertEquals("test3", chunk2.get(key3));
-        assertEquals("test4", chunk2.get(key4));
-
-        assertFalse(cursor.hasNext());
-        assertNull(cursor.next());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/StorageTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.storage;
-
-import static org.junit.Assert.assertSame;
-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.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class StorageTest {
-
-    private Storage storage;
-    private ConnectionKey connKey;
-
-    @Before
-    public void setUp() {
-        storage = mock(Storage.class);
-        connKey = new ConnectionKey(){};
-        when(storage.createConnectionKey(any(Category.class))).thenReturn(connKey);
-    }
-
-    @After
-    public void tearDown() {
-        storage = null;
-        connKey = null;
-    }
-
-    @Test
-    public void testRegisterCategory() {
-        Category category = new Category("testRegisterCategory");
-        storage.registerCategory(category);
-
-        verify(storage).createConnectionKey(category);
-        assertSame(connKey, category.getConnectionKey());
-    }
-
-    @Test(expected=IllegalStateException.class)
-    public void testRegisterCategoryTwice() {
-
-        Category category = new Category("test");
-        storage.registerCategory(category);
-        storage.registerCategory(category);
-    }
-
-    @Test(expected=IllegalStateException.class)
-    public void testRegisterCategorySameName() {
-
-        Category category1 = new Category("test");
-        storage.registerCategory(category1);
-        Category category2 = new Category("test");
-        storage.registerCategory(category2);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/tools/BasicCommandTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.tools;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Collection;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.ArgumentSpec;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.config.StartupConfiguration;
-import com.redhat.thermostat.common.tools.BasicCommand;
-
-public class BasicCommandTest {
-
-    private BasicCommand application;
-
-    @Before
-    public void setUp() {
-        application = new BasicCommand() {
-
-            @Override
-            public void run(CommandContext ctx) throws CommandException {
-                // Nothing to do here.
-            }
-
-            @Override
-            public void disable() {
-                // Move along
-            }
-
-            @Override
-            public String getName() {
-                return null;
-            }
-
-            @Override
-            public String getDescription() {
-                return null;
-            }
-
-            @Override
-            public String getUsage() {
-                return null;
-            }
-
-            @Override
-            public StartupConfiguration getConfiguration() {
-                return null;
-            }
-
-            @Override
-            public Collection<ArgumentSpec> getAcceptedArguments() {
-                return null;
-            }
-
-            @Override
-            public boolean isStorageRequired() {
-                return false;
-            }
-        };
-    }
-
-    @After
-    public void tearDown() {
-        application = null;
-    }
-
-    @Test
-    public void testNotfier() {
-        assertNotNull(application.getNotifier());
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/common/utils/DisplayableValuesTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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.utils;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Locale;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.utils.DisplayableValues.Scale;
-
-public class DisplayableValuesTest {
-
-    private static Locale defaultLocale;
-
-    @BeforeClass
-    public static void setUp() {
-        defaultLocale = Locale.getDefault();
-        Locale.setDefault(Locale.US);
-    }
-
-    @AfterClass
-    public static void tearDown() {
-        Locale.setDefault(defaultLocale);
-    }
-
-    @Test
-    public void testBytes() {
-        testBytesOutput("1", "B", DisplayableValues.bytes(1));
-        testBytesOutput("1023", "B", DisplayableValues.bytes(1023));
-        testBytesOutput("1.0", "KiB", DisplayableValues.bytes(1024));
-        testBytesOutput("1024.0", "KiB", DisplayableValues.bytes(1_048_575));
-        testBytesOutput("1.0", "MiB", DisplayableValues.bytes(1_048_576));
-        testBytesOutput("10.0", "MiB", DisplayableValues.bytes(10_480_000));
-        testBytesOutput("42.0", "MiB", DisplayableValues.bytes(44_040_000));
-        testBytesOutput("99.9", "MiB", DisplayableValues.bytes(104_752_742));
-        testBytesOutput("100.0", "MiB", DisplayableValues.bytes(104_857_600));
-        testBytesOutput("500.0", "MiB", DisplayableValues.bytes(524_288_000));
-        testBytesOutput("900.0", "MiB", DisplayableValues.bytes(943_718_400));
-        testBytesOutput("999.9", "MiB", DisplayableValues.bytes(1_048_471_000));
-        testBytesOutput("1.0", "GiB", DisplayableValues.bytes(1_073_741_824));
-        testBytesOutput("1.1", "GiB", DisplayableValues.bytes(1_181_116_000));
-        testBytesOutput("9.9", "GiB", DisplayableValues.bytes(10_630_044_000l));
-        testBytesOutput("99.9", "GiB", DisplayableValues.bytes(107_266_808_000l));
-        testBytesOutput("1.0", "TiB", DisplayableValues.bytes(1_099_511_627_776l));
-    }
-
-    private void testBytesOutput(String number, String units, String[] output) {
-        assertEquals(2, output.length);
-        assertEquals(number, output[0]);
-        assertEquals(units, output[1]);
-    }
-    
-    @Test
-    public void testScales() {
-        
-        double value = Scale.convertTo(Scale.KiB, 1024);
-        assertEquals(1, value, 0);
-        
-        value = Scale.convertTo(Scale.KiB, 2048);
-        assertEquals(2, value, 0);
-        
-        value = Scale.convertTo(Scale.KiB, 524_288);
-        assertEquals(512, value, 0);
-        
-        value = Scale.convertTo(Scale.MiB, 524_288_000);
-        assertEquals(500, value, 0);
-    }
-}
--- a/common/src/test/java/com/redhat/thermostat/test/ExceptionThrowingInputStreamTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/src/test/java/com/redhat/thermostat/test/TestCommandContextFactoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/src/test/java/com/redhat/thermostat/test/TestTimerFactoryTest.java	Tue Jun 12 17:22:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are 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/distribution/config/osgi-export.properties	Tue Jun 12 17:22:06 2012 +0200
+++ b/distribution/config/osgi-export.properties	Tue Jun 12 14:02:16 2012 -0400
@@ -54,3 +54,12 @@
 sun.jvmstat
 sun.jvmstat.monitor
 sun.jvmstat.monitor.event
+
+org.jboss.netty=3.2.4.Final
+org.jboss.netty.bootstrap=3.2.4.Final
+org.jboss.netty.buffer=3.2.4.Final
+org.jboss.netty.channel=3.2.4.Final
+org.jboss.netty.channel.group=3.2.4.Final
+org.jboss.netty.channel.socket.nio=3.2.4.Final
+org.jboss.netty.handler.codec.frame=3.2.4.Final
+
--- a/distribution/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/distribution/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -208,12 +208,17 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent</artifactId>
+      <artifactId>thermostat-agent-core</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-agent-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
--- a/distribution/scripts/thermostat	Tue Jun 12 17:22:06 2012 +0200
+++ b/distribution/scripts/thermostat	Tue Jun 12 14:02:16 2012 -0400
@@ -51,8 +51,9 @@
 BSON_JAR="${THERMOSTAT_LIBS}/bson.jar"
 JOPT_JAR="${THERMOSTAT_LIBS}/jopt-simple-4.3.jar"
 TOOLS_JAR="@java.home@/../lib/tools.jar"
+NETTY_JAR="${THERMOSTAT_LIBS}/netty-3.2.4.Final.jar"
 
-#SERVICE_CLASSPATH="${JCOMMON_JAR}:${MONGO_JAR}:${BSON_JAR}:${TOOLS_JAR}:${JOPT_JAR}"
+#SERVICE_CLASSPATH="${JCOMMON_JAR}:${MONGO_JAR}:${BSON_JAR}:${TOOLS_JAR}:${JOPT_JAR}:${NETTY_JAR}"
 SERVICE_CLASSPATH="${THERMOSTAT_LIBS}/*"
 
 THERM_DIR=${THERMOSTAT_LIBS}
--- a/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -78,8 +78,20 @@
     <osgi.compendium.version>4.2.0</osgi.compendium.version>
     <felix.framework.version>4.0.2</felix.framework.version>
 
+    <netty.version>3.2.4.Final</netty.version>
+
   </properties>
 
+  <repositories>
+    <repository>
+      <id>repository.jboss.org</id>
+      <url>https://repository.jboss.org/nexus/content/repositories/releases/</url>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+
   <modules>
     <module>common</module>
     <module>agent</module>
@@ -195,6 +207,11 @@
         <artifactId>cacio-tta</artifactId>
         <version>1.1</version>
       </dependency>
+      <dependency>
+        <groupId>org.jboss.netty</groupId>
+        <artifactId>netty</artifactId>
+        <version>${netty.version}</version>
+      </dependency>
 
       <dependency>
         <groupId>org.jfree</groupId>
--- a/tools/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/tools/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -77,12 +77,12 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent</artifactId>
+      <artifactId>thermostat-agent-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>
--- a/unix-process-handler/pom.xml	Tue Jun 12 17:22:06 2012 +0200
+++ b/unix-process-handler/pom.xml	Tue Jun 12 14:02:16 2012 -0400
@@ -51,7 +51,7 @@
     
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common</artifactId>
+      <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
       <type>bundle</type>
     </dependency>