Mercurial > hg > release > thermostat-0.15
changeset 233:023cdedfdb8c
Merge
author | Roman Kennke <rkennke@redhat.com> |
---|---|
date | Mon, 16 Apr 2012 15:41:08 +0200 |
parents | 581d71ba9125 (current diff) 9d74f4672d6c (diff) |
children | 001b59e74e8d 2bdcc631a4dc |
files | common/src/main/java/com/redhat/thermostat/cli/AppContextSetupImpl.java common/src/main/java/com/redhat/thermostat/common/dao/Connection.java common/src/main/java/com/redhat/thermostat/common/dao/ConnectionProvider.java common/src/main/java/com/redhat/thermostat/common/dao/MongoConnection.java common/src/main/java/com/redhat/thermostat/common/dao/MongoConnectionProvider.java common/src/main/java/com/redhat/thermostat/common/storage/ConnectionFailedException.java common/src/test/java/com/redhat/thermostat/cli/AppContextSetupImplTest.java common/src/test/java/com/redhat/thermostat/common/dao/ConnectionTest.java common/src/test/java/com/redhat/thermostat/common/dao/MongoConnectionTest.java |
diffstat | 127 files changed, 3983 insertions(+), 1201 deletions(-) [+] |
line wrap: on
line diff
--- a/agent/src/main/java/com/redhat/thermostat/agent/Agent.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/Agent.java Mon Apr 16 15:41:08 2012 +0200 @@ -44,6 +44,7 @@ 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; @@ -60,18 +61,21 @@ private final BackendRegistry backendRegistry; private final AgentStartupConfiguration config; + private AgentInformation agentInfo; + private Storage storage; private Thread configWatcherThread = null; - public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, Storage storage) { - this(backendRegistry, UUID.randomUUID(), config, storage); + public Agent(BackendRegistry backendRegistry, AgentStartupConfiguration config, DAOFactory daos) { + this(backendRegistry, UUID.randomUUID(), config, daos); } - public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, Storage storage) { + public Agent(BackendRegistry registry, UUID agentId, AgentStartupConfiguration config, DAOFactory daos) { this.id = agentId; this.backendRegistry = registry; this.config = config; - this.storage = storage; + this.storage = daos.getStorage(); + this.storage.setAgentId(agentId); } private void startBackends() throws LaunchException { @@ -99,7 +103,8 @@ public synchronized void start() throws LaunchException { if (configWatcherThread == null) { startBackends(); - storage.addAgentInformation(createAgentInformation()); + agentInfo = createAgentInformation(); + storage.addAgentInformation(agentInfo); configWatcherThread = new Thread(new ConfigurationWatcher(storage, backendRegistry), "Configuration Watcher"); configWatcherThread.start(); } else { @@ -117,6 +122,7 @@ backendInfo.setObserveNewJvm(backend.getObserveNewJvm()); agentInfo.addBackend(backendInfo); } + agentInfo.setAlive(true); return agentInfo; } @@ -131,12 +137,19 @@ } } configWatcherThread = null; - storage.removeAgentInformation(); + stopBackends(); - // TODO -// if (config.getLocalMode()) { -// storage.purge(); -// } + 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"); }
--- a/agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java Mon Apr 16 15:41:08 2012 +0200 @@ -51,18 +51,23 @@ import com.redhat.thermostat.cli.CommandException; 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.config.InvalidConfigurationException; -import com.redhat.thermostat.common.dao.Connection; -import com.redhat.thermostat.common.dao.ConnectionProvider; -import com.redhat.thermostat.common.dao.MongoConnectionProvider; -import com.redhat.thermostat.common.storage.ConnectionFailedException; -import com.redhat.thermostat.common.storage.MongoStorage; -import com.redhat.thermostat.common.storage.Storage; +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.StorageProvider; +import com.redhat.thermostat.common.storage.MongoStorageProvider; +import com.redhat.thermostat.common.storage.Connection.ConnectionListener; +import com.redhat.thermostat.common.storage.Connection.ConnectionStatus; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.tools.BasicCommand; public final class AgentApplication extends BasicCommand { + private CommandContext contex; private static final String NAME = "agent"; // TODO: Use LocaleResources for i18n-ized strings. @@ -96,30 +101,50 @@ } LoggingUtils.setGlobalLogLevel(configuration.getLogLevel()); - Logger logger = LoggingUtils.getLogger(AgentApplication.class); + final Logger logger = LoggingUtils.getLogger(AgentApplication.class); - ConnectionProvider connProv = new MongoConnectionProvider(configuration); - Connection connection = connProv.createConnection(); + StorageProvider connProv = new MongoStorageProvider(configuration); + DAOFactory daoFactory = new MongoDAOFactory(connProv); + ApplicationContext.getInstance().setDAOFactory(daoFactory); + TimerFactory timerFactory = new ThreadPoolTimerFactory(1); + ApplicationContext.getInstance().setTimerFactory(timerFactory); - Storage storage = new MongoStorage(connection); - try { - storage.connect(); - logger.fine("Storage configured with database URI."); - } catch (ConnectionFailedException ex) { - logger.log(Level.SEVERE, "Could not initialize storage layer.", ex); - System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE); - } + 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, storage); + backendRegistry = new BackendRegistry(configuration); } catch (BackendLoadException ble) { logger.log(Level.SEVERE, "Could not get BackendRegistry instance.", ble); System.exit(Constants.EXIT_BACKEND_LOAD_ERROR); } - Agent agent = new Agent(backendRegistry, configuration, storage); - storage.setAgentId(agent.getId()); + Agent agent = new Agent(backendRegistry, configuration, daoFactory); try { logger.fine("Starting agent."); agent.start(); @@ -131,6 +156,9 @@ } logger.fine("Agent started."); + contex.getConsole().getOutput().println("Agent id: " + agent.getId()); + logger.fine("Agent id: " + agent.getId()); + try { System.in.read(); } catch (IOException e) { @@ -144,6 +172,7 @@ @Override public void run(CommandContext ctx) throws CommandException { try { + contex = ctx; parseArguments(Arrays.asList(ctx.getArguments())); if (!parser.isHelp()) { runAgent();
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/config/AgentConfigsUtils.java Mon Apr 16 15:41:08 2012 +0200 @@ -89,6 +89,12 @@ 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)); + } } public static Level getLogLevel(String logLevel) {
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/config/AgentOptionParser.java Mon Apr 16 15:41:08 2012 +0200 @@ -67,6 +67,7 @@ parser.accepts(Args.DEBUG.option, Args.DEBUG.description); parser.accepts(Args.HELP.option, Args.HELP.description); + parser.accepts(Args.SAVE_ON_EXIT.option, Args.SAVE_ON_EXIT.description); OptionSpec<String> logLevel = parser.accepts(Args.LEVEL.option, Args.LEVEL.description). @@ -82,6 +83,10 @@ return; } + if (options.has(Args.SAVE_ON_EXIT.option)) { + configuration.setPurge(false); + } + if (options.has(Args.LEVEL.option)) { String levelString = logLevel.value(options); Level level = AgentConfigsUtils.getLogLevel(levelString); @@ -119,6 +124,7 @@ // TODO: localize LEVEL("logLevel", "log level"), + 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");
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/config/AgentProperties.java Mon Apr 16 15:41:08 2012 +0200 @@ -42,5 +42,6 @@ BACKENDS, LOG_LEVEL, DEBUG_CONSOLE, - DB_URL + DB_URL, + SAVE_ON_EXIT }
--- a/agent/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/config/AgentStartupConfiguration.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,9 +38,7 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -58,6 +56,7 @@ private Level logLevel; private boolean debugConsole; + private boolean purge; private String url; @@ -135,4 +134,12 @@ 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/backend/Backend.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/Backend.java Mon Apr 16 15:41:08 2012 +0200 @@ -42,8 +42,8 @@ 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.Chunk; import com.redhat.thermostat.common.storage.Storage; /** @@ -53,6 +53,7 @@ public abstract class Backend { private boolean initialConfigurationComplete = false; + protected DAOFactory df = null; private Storage storage = null; private boolean observeNewJvm = attachToNewProcessByDefault(); @@ -61,7 +62,7 @@ private String description; private BackendID id; - + /** * * @param configMap a map containing the settings that this backend has been configured with. @@ -69,7 +70,7 @@ */ protected final void setInitialConfiguration(Map<String, String> configMap) throws BackendLoadException { if (initialConfigurationComplete) { - throw new BackendLoadException("A backend may only receive intitial configuration once."); + throw new BackendLoadException("A backend may only receive initial configuration once."); } for (Entry<String, String> e : configMap.entrySet()) { String key = e.getKey(); @@ -84,13 +85,17 @@ initialConfigurationComplete = true; } - public final void setStorage(Storage storage) { - this.storage = storage; + 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(); /** @@ -228,14 +233,6 @@ observeNewJvm = newValue; } - public void store(Chunk chunk) { - storage.putChunk(chunk); - } - - public void update(Chunk chunk) { - storage.updateChunk(chunk); - } - void setID(BackendID backendID) { this.id = backendID; }
--- a/agent/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/BackendRegistry.java Mon Apr 16 15:41:08 2012 +0200 @@ -45,7 +45,8 @@ import java.util.logging.Logger; import com.redhat.thermostat.agent.config.AgentStartupConfiguration; -import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.utils.LoggingUtils; /** @@ -58,14 +59,17 @@ private final Map<String, Backend> registeredBackends; - public BackendRegistry(AgentStartupConfiguration config, Storage storage) throws BackendLoadException { - this(config, new BackendConfigurationLoader(), storage); + public BackendRegistry(AgentStartupConfiguration config) throws BackendLoadException { + this(config, new BackendConfigurationLoader()); } - public BackendRegistry(AgentStartupConfiguration config, BackendConfigurationLoader backendConfigLoader, Storage storage) throws BackendLoadException { + 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 @@ -78,11 +82,11 @@ 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())); - backend.setStorage(storage); } catch (Exception e) { throw new BackendLoadException("Could not instantiate configured backend class: " + backendID.getClassName(), e); }
--- a/agent/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/sample/SampleBackend.java Mon Apr 16 15:41:08 2012 +0200 @@ -130,4 +130,10 @@ return false; } + @Override + protected void setDAOFactoryAction() { + // TODO Auto-generated method stub + + } + }
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Mon Apr 16 15:41:08 2012 +0200 @@ -56,24 +56,25 @@ import com.redhat.thermostat.agent.JvmStatusListener; import com.redhat.thermostat.agent.JvmStatusNotifier; -import com.redhat.thermostat.common.dao.VmInfoConverter; +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.storage.Chunk; import com.redhat.thermostat.common.utils.LoggingUtils; public class JvmStatHostListener implements HostListener, JvmStatusNotifier { private static final Logger logger = LoggingUtils.getLogger(JvmStatHostListener.class); - private SystemBackend backend; - - private Map<Integer, JvmStatVmListener> listenerMap = new HashMap<Integer, JvmStatVmListener>(); + private boolean attachNew; + private final DAOFactory df; + private final VmInfoDAO vmInfoDAO; private Set<JvmStatusListener> statusListeners = new CopyOnWriteArraySet<JvmStatusListener>(); - public void setBackend(SystemBackend backend) { - this.backend = backend; + JvmStatHostListener(DAOFactory df, boolean attachNew) { + this.df = df; + this.vmInfoDAO = df.getVmInfoDAO(); + this.attachNew = attachNew; } @Override @@ -129,17 +130,15 @@ extractor.getMainClass(), extractor.getCommandLine(), extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(), properties, environment, loadedNativeLibraries); - backend.store(new VmInfoConverter().toChunk(info)); + vmInfoDAO.putVmInfo(info); logger.finer("Sent VM_STARTED messsage"); } catch (MonitorException me) { logger.log(Level.WARNING, "error getting vm info for " + vmId, me); } - if (backend.getObserveNewJvm()) { - JvmStatVmListener listener = new JvmStatVmListener(backend, vmId); - listenerMap.put(vmId, listener); - vm.addVmListener(listener); - vm.addVmListener(new JvmStatVmClassListener(backend, vmId)); + if (attachNew) { + vm.addVmListener(new JvmStatVmListener(df, vmId)); + vm.addVmListener(new JvmStatVmClassListener(df, vmId)); } else { logger.log(Level.FINE, "skipping new vm " + vmId); } @@ -155,22 +154,13 @@ new VmIdentifier(vmId.toString())); if (resolvedVmID != null) { long stopTime = System.currentTimeMillis(); - listenerMap.remove(vmId); for (JvmStatusListener statusListener : statusListeners) { statusListener.jvmStopped(vmId); } - backend.update(makeVmInfoUpdateStoppedChunk(vmId, stopTime)); + vmInfoDAO.putVmStoppedTime(vmId, stopTime); } } - private Chunk makeVmInfoUpdateStoppedChunk(int vmId, long stopTimeStamp) { - // FIXME later - Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, false); - chunk.put(VmInfoDAO.vmIdKey, vmId); - chunk.put(VmInfoDAO.stopTimeKey, stopTimeStamp); - return chunk; - } - @Override public void addJvmStatusListener(JvmStatusListener listener) { statusListeners.add(listener);
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java Mon Apr 16 15:41:08 2012 +0200 @@ -45,7 +45,8 @@ import sun.jvmstat.monitor.event.VmEvent; import sun.jvmstat.monitor.event.VmListener; -import com.redhat.thermostat.common.dao.VmClassStatConverter; +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; @@ -53,11 +54,11 @@ private static final Logger logger = LoggingUtils.getLogger(JvmStatVmClassListener.class); - private SystemBackend backend; + private VmClassStatDAO dao; private int vmId; - JvmStatVmClassListener(SystemBackend backend, int vmId) { - this.backend = backend; + JvmStatVmClassListener(DAOFactory df, int vmId) { + this.dao = df.getVmClassStatsDAO(); this.vmId = vmId; } @@ -79,8 +80,7 @@ long loadedClasses = extractor.getLoadedClasses(); long timestamp = System.currentTimeMillis(); VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses); - VmClassStatConverter dao = new VmClassStatConverter(); - backend.store(dao.toChunk(stat)); + 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java Mon Apr 16 15:41:08 2012 +0200 @@ -47,8 +47,9 @@ import sun.jvmstat.monitor.event.VmEvent; import sun.jvmstat.monitor.event.VmListener; -import com.redhat.thermostat.common.dao.VmGcStatConverter; -import com.redhat.thermostat.common.dao.VmMemoryStatConverter; +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; @@ -60,10 +61,12 @@ private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class); private final int vmId; - private final SystemBackend backend; + private final VmGcStatDAO gcDAO; + private final VmMemoryStatDAO memDAO; - public JvmStatVmListener(SystemBackend backend, int vmId) { - this.backend = backend; + public JvmStatVmListener(DAOFactory df, int vmId) { + gcDAO = df.getVmGcStatDAO(); + memDAO = df.getVmMemoryStatDAO(); this.vmId = vmId; } @@ -97,7 +100,7 @@ extractor.getCollectorName(i), extractor.getCollectorInvocations(i), extractor.getCollectorTime(i)); - backend.store(new VmGcStatConverter().toChunk(stat)); + gcDAO.putVmGcStat(stat); } } catch (MonitorException e) { logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e); @@ -132,7 +135,7 @@ s.used = extractor.getSpaceUsed(generation, space); } } - backend.store(new VmMemoryStatConverter().toChunk(stat)); + 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/SystemBackend.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Mon Apr 16 15:41:08 2012 +0200 @@ -57,16 +57,11 @@ import com.redhat.thermostat.backend.Backend; import com.redhat.thermostat.common.Clock; import com.redhat.thermostat.common.SystemClock; -import com.redhat.thermostat.common.dao.CpuStatConverter; import com.redhat.thermostat.common.dao.CpuStatDAO; -import com.redhat.thermostat.common.dao.HostInfoConverter; import com.redhat.thermostat.common.dao.HostInfoDAO; -import com.redhat.thermostat.common.dao.MemoryStatConverter; import com.redhat.thermostat.common.dao.MemoryStatDAO; -import com.redhat.thermostat.common.dao.NetworkInterfaceInfoConverter; import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.dao.VmCpuStatConverter; import com.redhat.thermostat.common.dao.VmCpuStatDAO; import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmInfoDAO; @@ -79,6 +74,12 @@ 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>(); @@ -89,13 +90,17 @@ private HostIdentifier hostId = null; private MonitoredHost host = null; - private JvmStatHostListener hostListener = new JvmStatHostListener(); + 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); @@ -110,6 +115,20 @@ ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource()); long ticksPerSecond = SysConf.getClockTicksPerSecond(); vmCpuBuilder = new VmCpuStatBuilder(clock, ticksPerSecond, builder); + ProcDataSource source = new ProcDataSource(); + hostInfoBuilder = new HostInfoBuilder(source); + cpuStatBuilder = new CpuStatBuilder(source); + memoryStatBuilder = new MemoryStatBuilder(source); + } + + @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 @@ -117,28 +136,30 @@ 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"); } - store(new HostInfoConverter().toChunk(new HostInfoBuilder(new ProcDataSource()).build())); + hostInfos.putHostInfo(hostInfoBuilder.build()); timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - ProcDataSource dataSource = new ProcDataSource(); - store(new CpuStatConverter().toChunk(new CpuStatBuilder(dataSource).build())); + cpuStats.putCpuStat(cpuStatBuilder.build()); for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) { - store(new NetworkInterfaceInfoConverter().toChunk(info)); + networkInterfaces.putNetworkInterfaceInfo(info); } - store(new MemoryStatConverter().toChunk(new MemoryStatBuilder(dataSource).build())); + memoryStats.putMemoryStat(memoryStatBuilder.build()); for (Integer pid : pidsToMonitor) { if (vmCpuBuilder.knowsAbout(pid)) { - store(new VmCpuStatConverter().toChunk(vmCpuBuilder.build(pid))); + vmCpuStats.putVmCpuStat(vmCpuBuilder.build(pid)); } else { vmCpuBuilder.learnAbout(pid); } @@ -149,7 +170,6 @@ try { hostId = new HostIdentifier((String) null); host = MonitoredHost.getMonitoredHost(hostId); - hostListener.setBackend(this); host.addHostListener(hostListener); } catch (MonitorException me) { logger.log(Level.WARNING, "problems with connecting jvmstat to local machine", me);
--- a/agent/src/test/java/com/redhat/thermostat/TestUtils.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/TestUtils.java Mon Apr 16 15:41:08 2012 +0200 @@ -43,10 +43,6 @@ import java.util.Properties; import java.util.Random; -import junit.framework.Assert; - -import org.junit.BeforeClass; - import com.redhat.thermostat.agent.config.AgentProperties; import com.redhat.thermostat.backend.BackendsProperties; @@ -85,6 +81,7 @@ Properties props = new Properties(); props.setProperty(AgentProperties.BACKENDS.name(), "system"); + props.setProperty(AgentProperties.SAVE_ON_EXIT.name(), "false"); props.setProperty(AgentProperties.LOG_LEVEL.name(), "WARNING"); props.store(new FileOutputStream(tmpConfigs), "thermostat agent test properties");
--- a/agent/src/test/java/com/redhat/thermostat/agent/AgentTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/agent/AgentTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,45 +39,61 @@ 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 { - @Test - public void testStartAgent() throws Exception { - // Setup class under test and test data (config, backendRegistry). - AgentStartupConfiguration config = mock(AgentStartupConfiguration.class); + 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); - - Storage storage = mock(Storage.class); - - Backend backend = mock(Backend.class); + 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 backendRegistry = mock(BackendRegistry.class); + + backendRegistry = mock(BackendRegistry.class); when(backendRegistry.getAll()).thenReturn(backends); - + } + + @Test + public void testStartAgent() throws Exception { + // Start agent. - Agent agent = new Agent(backendRegistry, config, storage); + Agent agent = new Agent(backendRegistry, config, daos); agent.start(); // Verify that backend has been activated and storage received the agent information. @@ -94,4 +110,39 @@ // 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/config/AgentOptionParserTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/agent/config/AgentOptionParserTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -37,11 +37,9 @@ package com.redhat.thermostat.agent.config; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.logging.Level; import junit.framework.Assert; @@ -77,13 +75,14 @@ args.add("testURL"); args.add("--debug"); - AgentStartupConfiguration configs = new AgentStartupConfiguration(); + AgentStartupConfiguration configs = AgentConfigsUtils.createAgentConfigs(); AgentOptionParser parser = new AgentOptionParser(configs, args); parser.parse(); Assert.assertEquals("testURL", configs.getDBConnectionString()); Assert.assertEquals(Level.ALL, configs.getLogLevel()); Assert.assertTrue(configs.isDebugConsole()); + Assert.assertTrue(configs.purge()); } @Test @@ -94,6 +93,7 @@ args.add("FINE"); args.add("--dbUrl"); args.add("testURL2"); + args.add("--saveOnExit"); AgentStartupConfiguration configs = new AgentStartupConfiguration(); AgentOptionParser parser = new AgentOptionParser(configs, args); @@ -102,5 +102,6 @@ Assert.assertEquals("testURL2", configs.getDBConnectionString()); Assert.assertEquals(Level.FINE, configs.getLogLevel()); Assert.assertFalse(configs.isDebugConsole()); + Assert.assertFalse(configs.purge()); } }
--- a/agent/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/backend/BackendRegistryTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -53,13 +53,19 @@ 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(); @@ -84,23 +90,32 @@ public boolean attachToNewProcessByDefault() { return false; } + + @Override + protected void setDAOFactoryAction() { + // TODO Auto-generated method stub + + } } private List<BackendID> backends; private AgentStartupConfiguration config; private BackendConfigurationLoader configLoader; - private Storage storage; @Before public void setUp() throws InvalidConfigurationException { backends = new ArrayList<>(); - storage = mock(Storage.class); 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 @@ -108,7 +123,6 @@ backends = null; config = null; configLoader = null; - storage = null; } @Test @@ -116,14 +130,14 @@ /* setup fake backend */ backends.add(new BackendID("mock", MockBackend.class.getName())); - BackendRegistry registry = new BackendRegistry(config, configLoader, storage); + 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, storage); + BackendRegistry registry = new BackendRegistry(config, configLoader); assertEquals(0, registry.getAll().size()); assertEquals(null, registry.getByName("system")); assertEquals(null, registry.getByName("mock")); @@ -137,7 +151,7 @@ backends.add(new BackendID("mock", MockBackend.class.getClass().getName())); /* load the backends */ - new BackendRegistry(config, configLoader, storage); + new BackendRegistry(config, configLoader); } }
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -48,6 +48,10 @@ 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; @@ -75,10 +79,14 @@ when(host.getMonitoredVm(any(VmIdentifier.class))).thenReturn(vm); when(vmEvent.getMonitoredHost()).thenReturn(host); - JvmStatHostListener l = new JvmStatHostListener(); + 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.setBackend(backend); l.vmStatusChanged(vmEvent);
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/backend/system/JvmStatVmClassListenerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -48,42 +48,49 @@ import sun.jvmstat.monitor.MonitoredVm; import sun.jvmstat.monitor.event.VmEvent; -import com.redhat.thermostat.common.storage.Chunk; -import com.redhat.thermostat.common.storage.Key; +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 { - SystemBackend backend = mock(SystemBackend.class); - int vmId = 123; - JvmStatVmClassListener l = new JvmStatVmClassListener(backend, vmId); + 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(new Long(1234)); + when(m.getValue()).thenReturn(LOADED_CLASSES); when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm); l.monitorsUpdated(vmEvent); - ArgumentCaptor<Chunk> chunkArg = ArgumentCaptor.forClass(Chunk.class); - verify(backend).store(chunkArg.capture()); - assertEquals((Long) 1234L, chunkArg.getValue().get(new Key<Long>("loadedClasses", false))); - assertEquals((Integer) 123, chunkArg.getValue().get(new Key<Integer>("vm-id", false))); + 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 { - SystemBackend backend = mock(SystemBackend.class); - int vmId = 123; - JvmStatVmClassListener l = new JvmStatVmClassListener(backend, vmId); + 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(new Long(1234)); + when(m.getValue()).thenReturn(LOADED_CLASSES); when(monitoredVm.findByName("java.cls.loadedClasses")).thenReturn(m); when(vmEvent.getMonitoredVm()).thenReturn(monitoredVm);
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/agent/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,6 +39,7 @@ 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; @@ -46,6 +47,7 @@ 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; @@ -63,9 +65,21 @@ @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(); - Storage s = mock(Storage.class); - b.setStorage(s); + b.setDAOFactory(df); } @Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/AgentConfigurationSource.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class AgentConfigurationSource { + + // FIXME fix this properly + + public List<String> getKnownAgents() { + return Arrays.asList(new String[] { "Agent Smith", "Agent Jones", "Agent Brown" }); + } + + public Map<String, Boolean> getAgentBackends(String agentName) { + Map<String, Boolean> fake = new HashMap<>(); + fake.put("Monitor New JVMs", true); + fake.put("Use up all my CPU Cycles", false); + return fake; + } + + public void updateAgentConfig(String agentName, Map<String, Boolean> newBackendStatus) { + // TODO Auto-generated method stub + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/DefaultViewFactory.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.View; +import com.redhat.thermostat.common.ViewFactory; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class DefaultViewFactory implements ViewFactory { + + private static final Logger logger = LoggingUtils.getLogger(SwingViewFactory.class); + private final Map<Class<?>, Class<?>> lookupTable = Collections.synchronizedMap(new HashMap<Class<?>, Class<?>>()); + + @Override + public <T extends View> T getView(Class<T> viewClass) { + Class<? extends T> klass = getViewClass(viewClass); + if (klass == null) { + logger.log(Level.WARNING, "no view class registered for " + viewClass.toString()); + return null; + } + + try { + return klass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + logger.log(Level.WARNING, "error instantiaitng" + klass); + return null; + } + } + + @Override + public <T extends View> Class<? extends T> getViewClass(Class<T> viewClass) { + // the cast is safe because the only way to insert an entry into the table is through + // a method that enforces this constraint + @SuppressWarnings("unchecked") + Class<? extends T> result = (Class<? extends T>) lookupTable.get(viewClass); + return result; + } + + @Override + public <T extends View> void setViewClass(Class<T> viewClass, Class<? extends T> implClass) { + lookupTable.put(viewClass, implClass); + } + +} \ No newline at end of file
--- a/client/src/main/java/com/redhat/thermostat/client/Main.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/Main.java Mon Apr 16 15:41:08 2012 +0200 @@ -47,6 +47,7 @@ import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; +import com.redhat.thermostat.client.config.ClientPreferences; import com.redhat.thermostat.client.config.ConnectionConfiguration; import com.redhat.thermostat.client.locale.LocaleResources; import com.redhat.thermostat.client.ui.ConnectionSelectionDialog; @@ -56,13 +57,13 @@ import com.redhat.thermostat.common.TimerFactory; import com.redhat.thermostat.common.appctx.ApplicationContext; import com.redhat.thermostat.common.config.StartupConfiguration; -import com.redhat.thermostat.common.dao.Connection; -import com.redhat.thermostat.common.dao.Connection.ConnectionListener; -import com.redhat.thermostat.common.dao.Connection.ConnectionStatus; -import com.redhat.thermostat.common.dao.ConnectionProvider; import com.redhat.thermostat.common.dao.DAOFactory; -import com.redhat.thermostat.common.dao.MongoConnectionProvider; import com.redhat.thermostat.common.dao.MongoDAOFactory; +import com.redhat.thermostat.common.storage.Connection; +import com.redhat.thermostat.common.storage.StorageProvider; +import com.redhat.thermostat.common.storage.MongoStorageProvider; +import com.redhat.thermostat.common.storage.Connection.ConnectionListener; +import com.redhat.thermostat.common.storage.Connection.ConnectionStatus; import com.redhat.thermostat.common.utils.LoggingUtils; public class Main { @@ -80,13 +81,16 @@ System.exit(-1); } - StartupConfiguration config = new ConnectionConfiguration(); - - ConnectionProvider connProv = new MongoConnectionProvider(config); + ClientPreferences prefs = new ClientPreferences(); + StartupConfiguration config = new ConnectionConfiguration(prefs); + + StorageProvider connProv = new MongoStorageProvider(config); DAOFactory daoFactory = new MongoDAOFactory(connProv); ApplicationContext.getInstance().setDAOFactory(daoFactory); TimerFactory timerFactory = new ThreadPoolTimerFactory(1); ApplicationContext.getInstance().setTimerFactory(timerFactory); + SwingViewFactory viewFactory = new SwingViewFactory(); + ApplicationContext.getInstance().setViewFactory(viewFactory); } private void showGui() {
--- a/client/src/main/java/com/redhat/thermostat/client/MainView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/MainView.java Mon Apr 16 15:41:08 2012 +0200 @@ -43,7 +43,10 @@ enum Action { HOST_VM_TREE_FILTER, - SHUTDOWN + SHOW_AGENT_CONFIG, + SHOW_CLIENT_CONFIG, + SWITCH_HISTORY_MODE, + SHUTDOWN, } void addActionListener(ActionListener<Action> capture);
--- a/client/src/main/java/com/redhat/thermostat/client/MainWindowControllerImpl.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/MainWindowControllerImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,8 +38,13 @@ import java.util.Collection; import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; +import com.redhat.thermostat.client.config.ClientPreferences; +import com.redhat.thermostat.client.ui.AgentConfigurationController; +import com.redhat.thermostat.client.ui.AgentConfigurationModel; +import com.redhat.thermostat.client.ui.AgentConfigurationView; +import com.redhat.thermostat.client.ui.ClientConfigurationController; +import com.redhat.thermostat.client.ui.ClientConfigurationView; import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.Timer; @@ -49,7 +54,6 @@ import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.common.dao.VmInfoDAO; import com.redhat.thermostat.common.dao.VmRef; -import com.redhat.thermostat.common.utils.LoggingUtils; public class MainWindowControllerImpl implements MainWindowController { @@ -62,6 +66,8 @@ private final HostInfoDAO hostsDAO; private final VmInfoDAO vmsDAO; + private boolean showHistory; + public MainWindowControllerImpl(MainView view) { ApplicationContext ctx = ApplicationContext.getInstance(); @@ -78,14 +84,18 @@ @Override public Collection<HostRef> getHosts() { - return hostsDAO.getHosts(); + if (showHistory) { + return hostsDAO.getHosts(); + } else { + return hostsDAO.getAliveHosts(); + } } @Override public Collection<VmRef> getVMs(HostRef host) { return vmsDAO.getVMs(host); } - + } private void initializeTimer() { @@ -135,6 +145,15 @@ String filter = view.getHostVmTreeFilter(); setHostVmTreeFilter(filter); break; + case SHOW_AGENT_CONFIG: + showAgentConfiguration(); + break; + case SHOW_CLIENT_CONFIG: + showConfigureClientPreferences(); + break; + case SWITCH_HISTORY_MODE: + switchHistoryMode(); + break; case SHUTDOWN: stop(); break; @@ -142,7 +161,6 @@ assert false; } } - }); } @@ -151,4 +169,23 @@ view.showMainWindow(); } + private void showAgentConfiguration() { + AgentConfigurationSource agentPrefs = new AgentConfigurationSource(); + AgentConfigurationModel model = new AgentConfigurationModel(agentPrefs); + AgentConfigurationView view = ApplicationContext.getInstance().getViewFactory().getView(AgentConfigurationView.class); + AgentConfigurationController controller = new AgentConfigurationController(model, view); + controller.showView(); + } + + private void showConfigureClientPreferences() { + ClientPreferences prefs = new ClientPreferences(); + ClientConfigurationView view = ApplicationContext.getInstance().getViewFactory().getView(ClientConfigurationView.class); + ClientConfigurationController controller = new ClientConfigurationController(prefs, view); + controller.showDialog(); + } + + private void switchHistoryMode() { + showHistory = !showHistory; + doUpdateTreeAsync(); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/SwingViewFactory.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client; + + +import com.redhat.thermostat.client.ui.AgentConfigurationFrame; +import com.redhat.thermostat.client.ui.AgentConfigurationView; +import com.redhat.thermostat.client.ui.ClientConfigurationFrame; +import com.redhat.thermostat.client.ui.ClientConfigurationView; +import com.redhat.thermostat.client.ui.HostCpuPanel; +import com.redhat.thermostat.client.ui.HostCpuView; +import com.redhat.thermostat.client.ui.HostMemoryPanel; +import com.redhat.thermostat.client.ui.HostMemoryView; +import com.redhat.thermostat.client.ui.HostOverviewPanel; +import com.redhat.thermostat.client.ui.HostOverviewView; +import com.redhat.thermostat.client.ui.VmClassStatPanel; +import com.redhat.thermostat.client.ui.VmClassStatView; +import com.redhat.thermostat.client.ui.VmCpuPanel; +import com.redhat.thermostat.client.ui.VmCpuView; +import com.redhat.thermostat.client.ui.VmGcPanel; +import com.redhat.thermostat.client.ui.VmGcView; +import com.redhat.thermostat.client.ui.VmMemoryPanel; +import com.redhat.thermostat.client.ui.VmMemoryView; +import com.redhat.thermostat.client.ui.VmOverviewPanel; +import com.redhat.thermostat.client.ui.VmOverviewView; +import com.redhat.thermostat.common.ViewFactory; + +public class SwingViewFactory extends DefaultViewFactory implements ViewFactory { + + public SwingViewFactory() { + setViewClass(AgentConfigurationView.class, AgentConfigurationFrame.class); + setViewClass(ClientConfigurationView.class, ClientConfigurationFrame.class); + + setViewClass(HostCpuView.class, HostCpuPanel.class); + setViewClass(HostMemoryView.class, HostMemoryPanel.class); + setViewClass(HostOverviewView.class, HostOverviewPanel.class); + + setViewClass(VmClassStatView.class, VmClassStatPanel.class); + setViewClass(VmCpuView.class, VmCpuPanel.class); + setViewClass(VmGcView.class, VmGcPanel.class); + setViewClass(VmMemoryView.class, VmMemoryPanel.class); + setViewClass(VmOverviewView.class, VmOverviewPanel.class); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/config/ClientPreferences.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.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/client/src/main/java/com/redhat/thermostat/client/config/ConnectionConfiguration.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/config/ConnectionConfiguration.java Mon Apr 16 15:41:08 2012 +0200 @@ -40,10 +40,14 @@ public class ConnectionConfiguration implements StartupConfiguration { + private final ClientPreferences clientPrefs; + + public ConnectionConfiguration(ClientPreferences clientPrefs) { + this.clientPrefs = clientPrefs; + } + @Override public String getDBConnectionString() { - // TODO: this needs to be read from preferences or from the agent - // configuration - return "mongodb://127.0.0.1:27518"; + return clientPrefs.getConnectionUrl(); } }
--- a/client/src/main/java/com/redhat/thermostat/client/locale/LocaleResources.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/locale/LocaleResources.java Mon Apr 16 15:41:08 2012 +0200 @@ -55,9 +55,13 @@ MENU_FILE_IMPORT, MENU_FILE_EXPORT, MENU_FILE_EXIT, + MENU_EDIT, + MENU_EDIT_CONFIGURE_AGENT, + MENU_EDIT_CONFIGURE_CLIENT, + MENU_EDIT_ENABLE_HISTORY_MODE, MENU_HELP, MENU_HELP_ABOUT, - + GARBAGE_COLLECTION, YOUNG_GEN, EDEN_GEN, @@ -172,7 +176,16 @@ VM_LOADED_CLASSES, VM_CLASSES_CHART_REAL_TIME_LABEL, - VM_CLASSES_CHART_LOADED_CLASSES_LABEL; + VM_CLASSES_CHART_LOADED_CLASSES_LABEL, + + CONFIGURE_AGENT_WINDOW_TITLE, + CONFIGURE_AGENT_AGENTS_LIST, + CONFIGURE_ENABLE_BACKENDS, + + CLIENT_PREFS_WINDOW_TITLE, + CLIENT_PREFS_GENERAL, + CLIENT_PREFS_STORAGE_URL, + ; static final String RESOURCE_BUNDLE = "com.redhat.thermostat.client.locale.strings";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationController.java Mon Apr 16 15:41:08 2012 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are 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.ui; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.redhat.thermostat.client.ui.AgentConfigurationView.ConfigurationAction; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; + +public class AgentConfigurationController implements ActionListener<ConfigurationAction> { + + private final AgentConfigurationView view; + private final AgentConfigurationModel model; + private String agentName = null; + + public AgentConfigurationController(AgentConfigurationModel model, AgentConfigurationView view) { + this.view = view; + this.model = model; + + view.addActionListener(this); + + } + + public void showView() { + Collection<String> agents = model.getAgents(); + agentName = null; + for (String agentName: agents) { + if (this.agentName == null) { + this.agentName = agentName; + } + view.addAgent(agentName); + } + view.showDialog(); + updateViewFromModel(); + } + + public void hideView() { + view.hideDialog(); + } + + @Override + public void actionPerformed(ActionEvent<ConfigurationAction> actionEvent) { + switch (actionEvent.getActionId()) { + case SWITCH_AGENT: + updateModelFromCurrentView(); + String agentName = view.getSelectedAgent(); + this.agentName = agentName; + updateViewFromModel(); + break; + case CLOSE_ACCEPT: + updateModelFromCurrentView(); + model.saveConfiguration(); + /* fall through */ + case CLOSE_CANCEL: + hideView(); + break; + default: + throw new IllegalArgumentException("unknown event"); + } + } + + private void updateModelFromCurrentView() { + Map<String, Boolean> map = view.getBackendStatus(); + for (Entry<String, Boolean> entry: map.entrySet()) { + model.setBackendEnabled(agentName, entry.getKey(), entry.getValue()); + } + + } + + private void updateViewFromModel() { + Map<String, Boolean> map = new HashMap<>(); + for (String backendName: model.getBackends(agentName)) { + map.put(backendName, model.getAgentBackendEnabled(agentName, backendName)); + } + view.setBackendStatus(map); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationFrame.java Mon Apr 16 15:41:08 2012 +0200 @@ -0,0 +1,308 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are 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.ui; + +import static com.redhat.thermostat.client.locale.Translate.localize; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.Box; +import javax.swing.DefaultListModel; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.SwingUtilities; + +import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import javax.swing.JScrollPane; +import javax.swing.JList; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +public class AgentConfigurationFrame extends JFrame implements AgentConfigurationView, java.awt.event.ActionListener, ListSelectionListener { + + private static final long serialVersionUID = -6049272471909474886L; + + private final CopyOnWriteArrayList<ActionListener<ConfigurationAction>> listeners = new CopyOnWriteArrayList<>(); + + private final Map<String, JCheckBox> backends = Collections.synchronizedMap(new HashMap<String, JCheckBox>()); + + private final JPanel availableBackendsPanel; + private final GridBagConstraints availableBackendsPanelContstraints = new GridBagConstraints(); + + private final JButton okayButton; + private final JButton cancelButton; + + private final JList<String> agentList; + private final DefaultListModel<String> listModel; + + + public AgentConfigurationFrame() { + assertInEDT(); + + setTitle(localize(LocaleResources.CONFIGURE_AGENT_WINDOW_TITLE)); + + JLabel lblEnabledisableBackends = new JLabel(localize(LocaleResources.CONFIGURE_ENABLE_BACKENDS)); + + availableBackendsPanel = new JPanel(); + + okayButton = new JButton(localize(LocaleResources.BUTTON_OK)); + okayButton.addActionListener(this); + + cancelButton = new JButton(localize(LocaleResources.BUTTON_CANCEL)); + cancelButton.addActionListener(this); + + JScrollPane scrollPane = new JScrollPane(); + + JLabel lblAgents = new JLabel(localize(LocaleResources.CONFIGURE_AGENT_AGENTS_LIST)); + + GroupLayout groupLayout = new GroupLayout(getContentPane()); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addContainerGap() + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 127, GroupLayout.PREFERRED_SIZE) + .addGap(0) + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup() + .addComponent(cancelButton) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(okayButton)) + .addGroup(groupLayout.createSequentialGroup() + .addGap(12) + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addGap(12) + .addComponent(availableBackendsPanel, GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE)) + .addComponent(lblEnabledisableBackends))))) + .addComponent(lblAgents)) + .addContainerGap()) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.TRAILING) + .addGroup(groupLayout.createSequentialGroup() + .addGap(6) + .addComponent(lblAgents) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.TRAILING) + .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE) + .addGroup(groupLayout.createSequentialGroup() + .addComponent(lblEnabledisableBackends) + .addGap(2) + .addComponent(availableBackendsPanel, GroupLayout.DEFAULT_SIZE, 365, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(okayButton) + .addComponent(cancelButton)))) + .addContainerGap()) + ); + + listModel = new DefaultListModel<String>(); + agentList = new JList<String>(listModel); + agentList.addListSelectionListener(this); + scrollPane.setViewportView(agentList); + + availableBackendsPanel.setLayout(new GridBagLayout()); + getContentPane().setLayout(groupLayout); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.CLOSE_CANCEL)); + } + }); + } + + private void resetConstraints() { + availableBackendsPanelContstraints.gridwidth = 1; + availableBackendsPanelContstraints.gridy = 0; + availableBackendsPanelContstraints.gridx = 0; + availableBackendsPanelContstraints.weightx = 0; + availableBackendsPanelContstraints.weighty = 0; + availableBackendsPanelContstraints.anchor = GridBagConstraints.LINE_START; + availableBackendsPanelContstraints.fill = GridBagConstraints.BOTH; + } + + + @Override + public void addActionListener(ActionListener<ConfigurationAction> listener) { + listeners.add(listener); + } + + @Override + public void removeActionListener(ActionListener<ConfigurationAction> listener) { + listeners.remove(listener); + } + + @Override + public void addAgent(final String agentName) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listModel.addElement(agentName); + } + }); + } + + @Override + public String getSelectedAgent() { + assertInEDT(); + return agentList.getSelectedValue(); + } + + @Override + public void clearAllAgents() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listModel.clear(); + } + }); + } + + + @Override + public void setBackendStatus(final Map<String, Boolean> backendStatus) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + backends.clear(); + availableBackendsPanel.removeAll(); + resetConstraints(); + + for (Entry<String, Boolean> entry: backendStatus.entrySet()) { + String backendName = entry.getKey(); + boolean checked = entry.getValue(); + JCheckBox checkBox = new JCheckBox(backendName); + checkBox.setSelected(checked); + checkBox.setActionCommand(backendName); + checkBox.addActionListener(AgentConfigurationFrame.this); + backends.put(backendName, checkBox); + availableBackendsPanel.add(checkBox, availableBackendsPanelContstraints); + availableBackendsPanelContstraints.gridy++; + } + availableBackendsPanelContstraints.weighty = 1.0; + availableBackendsPanelContstraints.weightx = 1.0; + availableBackendsPanelContstraints.fill = GridBagConstraints.BOTH; + availableBackendsPanel.add(Box.createGlue(), availableBackendsPanelContstraints); + AgentConfigurationFrame.this.revalidate(); + } + }); + } + + @Override + public Map<String, Boolean> getBackendStatus() { + assertInEDT(); + + Map<String,Boolean> latestUserSpecified = new HashMap<>(); + for (Entry<String, JCheckBox> entry: backends.entrySet()) { + latestUserSpecified.put(entry.getKey(), entry.getValue().isSelected()); + } + return latestUserSpecified; + } + + @Override + public void showDialog() { + assertInEDT(); + + pack(); + setVisible(true); + + agentList.setSelectedIndex(0); + } + + @Override + public void hideDialog() { + assertInEDT(); + + setVisible(false); + dispose(); + } + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + Object source = e.getSource(); + if (source == okayButton) { + fireAction(new ActionEvent<>(this, ConfigurationAction.CLOSE_ACCEPT)); + } else if (source == cancelButton) { + fireAction(new ActionEvent<>(this, ConfigurationAction.CLOSE_CANCEL)); + } + } + + @Override + public void valueChanged(ListSelectionEvent e) { + if (e.getSource() == agentList) { + if (e.getValueIsAdjusting()) { + return; + } + fireAction(new ActionEvent<>(this, ConfigurationAction.SWITCH_AGENT)); + } else { + throw new IllegalStateException("unknown trigger"); + } + } + + private void fireAction(ActionEvent<ConfigurationAction> actionEvent) { + for (ActionListener<ConfigurationAction> l: listeners) { + l.actionPerformed(actionEvent); + } + } + + private static void assertInEDT() { + if (!SwingUtilities.isEventDispatchThread()) { + throw new IllegalStateException("must be called from within the swing EDT"); + } + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationModel.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.redhat.thermostat.client.AgentConfigurationSource; + +/** + * This model sits between the current view and the remote model, and allows + * us to make changes and later throw them away. + */ +public class AgentConfigurationModel { + + private final AgentConfigurationSource remoteConfiguration; + + private final List<String> knownAgents; + private Map<String, Map<String, Boolean>> enabledBackends; + + public AgentConfigurationModel(AgentConfigurationSource configSource) { + this.remoteConfiguration = configSource; + + knownAgents = new ArrayList<>(remoteConfiguration.getKnownAgents()); + enabledBackends = new HashMap<>(); + for (String agent: knownAgents) { + enabledBackends.put(agent, new HashMap<String, Boolean>(remoteConfiguration.getAgentBackends(agent))); + } + } + + public Collection<String> getAgents() { + return Collections.unmodifiableList(knownAgents); + } + + public Collection<String> getBackends(String agentName) { + return Collections.unmodifiableSet(enabledBackends.get(agentName).keySet()); + } + + public void setBackendEnabled(String agentName, String backendName, boolean enabled) { + enabledBackends.get(agentName).put(backendName, enabled); + } + + public boolean getAgentBackendEnabled(String agentName, String backendName) { + return enabledBackends.get(agentName).get(backendName); + } + + public void saveConfiguration() { + for (Entry<String, Map<String, Boolean>> entry: enabledBackends.entrySet()) { + remoteConfiguration.updateAgentConfig(entry.getKey(), entry.getValue()); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationView.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.ui; + +import java.util.Map; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.View; + +public interface AgentConfigurationView extends View { + + enum ConfigurationAction { + SWITCH_AGENT, + CLOSE_ACCEPT, + CLOSE_CANCEL, + } + + void showDialog(); + + void hideDialog(); + + void addActionListener(ActionListener<ConfigurationAction> listener); + + void removeActionListener(ActionListener<ConfigurationAction> listener); + + void addAgent(String agentName); + + String getSelectedAgent(); + + void clearAllAgents(); + + void setBackendStatus(Map<String,Boolean> agentConfiguration); + + Map<String,Boolean> getBackendStatus(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/ClientConfigurationController.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.prefs.BackingStoreException; + +import com.redhat.thermostat.client.config.ClientPreferences; +import com.redhat.thermostat.client.ui.ClientConfigurationView.Action; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class ClientConfigurationController implements ActionListener<Action> { + + private static final Logger logger = LoggingUtils.getLogger(ClientConfigurationController.class); + + private final ClientConfigurationView view; + private final ClientPreferences model; + + public ClientConfigurationController(ClientPreferences model, ClientConfigurationView view) { + this.model = model; + this.view = view; + + view.addListener(this); + } + + public void showDialog() { + updateViewFromModel(); + view.showDialog(); + } + + private void updateViewFromModel() { + view.setConnectionUrl(model.getConnectionUrl()); + } + + private void updateModelFromView() { + model.setConnectionUrl(view.getConnectionUrl()); + + try { + model.flush(); + } catch (BackingStoreException e) { + logger.log(Level.WARNING, "error saving client preferences", e); + } + } + + @Override + public void actionPerformed(ActionEvent<Action> actionEvent) { + if (actionEvent.getSource() != view) { + return; + } + + switch (actionEvent.getActionId()) { + case CLOSE_ACCEPT: + updateModelFromView(); + /* fall through */ + case CLOSE_CANCEL: + view.hideDialog(); + break; + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/ClientConfigurationFrame.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import static com.redhat.thermostat.client.locale.Translate.localize; + +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.LayoutStyle.ComponentPlacement; + +import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; + +public class ClientConfigurationFrame extends JFrame implements ClientConfigurationView, java.awt.event.ActionListener { + + private static final long serialVersionUID = 6888957994092403516L; + + private final JTextField storageUrl; + private final JButton btnOk; + private final JButton btnCancel; + + private CopyOnWriteArrayList<ActionListener<Action>> listeners = new CopyOnWriteArrayList<>(); + + public ClientConfigurationFrame() { + setTitle(localize(LocaleResources.CLIENT_PREFS_WINDOW_TITLE)); + + btnOk = new JButton(localize(LocaleResources.BUTTON_OK)); + btnOk.addActionListener(this); + btnOk.setName("ok"); + btnCancel = new JButton(localize(LocaleResources.BUTTON_CANCEL)); + btnCancel.addActionListener(this); + btnCancel.setName("cancel"); + JLabel lblClientConfiguration = new JLabel(localize(LocaleResources.CLIENT_PREFS_GENERAL)); + + JLabel lblStorageUrl = new JLabel(localize(LocaleResources.CLIENT_PREFS_STORAGE_URL)); + + storageUrl = new JTextField(); + storageUrl.setColumns(10); + storageUrl.setName("connectionUrl"); + + GroupLayout groupLayout = new GroupLayout(getContentPane()); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup() + .addContainerGap(251, Short.MAX_VALUE) + .addComponent(btnCancel) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(btnOk) + .addContainerGap()) + .addGroup(groupLayout.createSequentialGroup() + .addContainerGap() + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addGap(12) + .addComponent(lblStorageUrl) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(storageUrl, GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE)) + .addComponent(lblClientConfiguration)) + .addContainerGap()) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup() + .addContainerGap() + .addComponent(lblClientConfiguration) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblStorageUrl) + .addComponent(storageUrl, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(ComponentPlacement.RELATED, 185, Short.MAX_VALUE) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(btnOk) + .addComponent(btnCancel)) + .addContainerGap()) + ); + getContentPane().setLayout(groupLayout); + } + + @Override + public void showDialog() { + assertInEDT(); + this.pack(); + this.setVisible(true); + } + + @Override + public void hideDialog() { + assertInEDT(); + + this.setVisible(false); + this.dispose(); + } + + @Override + public String getConnectionUrl() { + assertInEDT(); + return storageUrl.getText(); + } + + @Override + public void setConnectionUrl(final String url) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + storageUrl.setText(url); + } + }); + } + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (e.getSource() == btnOk) { + fireAction(new ActionEvent<>(this, Action.CLOSE_ACCEPT)); + } else if (e.getSource() == btnCancel) { + fireAction(new ActionEvent<>(this, Action.CLOSE_CANCEL)); + } + } + + @Override + public void addListener(ActionListener<Action> listener) { + listeners.add(listener); + } + + @Override + public void removeListener(ActionListener<Action> listener) { + listeners.remove(listener); + } + + private void fireAction(ActionEvent<Action> actionEvent) { + for (ActionListener<Action> listener: listeners) { + listener.actionPerformed(actionEvent); + } + } + + private void assertInEDT() { + if (!SwingUtilities.isEventDispatchThread()) { + throw new IllegalStateException("must be invoked in the EDT"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/ClientConfigurationView.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.View; + +public interface ClientConfigurationView extends View { + + enum Action { + CLOSE_CANCEL, + CLOSE_ACCEPT, + } + + void addListener(ActionListener<Action> listener); + + void removeListener(ActionListener<Action> listener); + + void setConnectionUrl(String url); + String getConnectionUrl(); + + void showDialog(); + void hideDialog(); + +}
--- a/client/src/main/java/com/redhat/thermostat/client/ui/ConnectionSelectionDialog.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/ConnectionSelectionDialog.java Mon Apr 16 15:41:08 2012 +0200 @@ -58,8 +58,8 @@ import javax.swing.JPanel; import com.redhat.thermostat.client.locale.LocaleResources; -import com.redhat.thermostat.common.dao.Connection; -import com.redhat.thermostat.common.dao.Connection.ConnectionType; +import com.redhat.thermostat.common.storage.Connection; +import com.redhat.thermostat.common.storage.Connection.ConnectionType; public class ConnectionSelectionDialog extends JDialog {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java Mon Apr 16 15:41:08 2012 +0200 @@ -64,7 +64,7 @@ public HostCpuController(HostRef ref) { this.ref = ref; - view = createView(); + view = ApplicationContext.getInstance().getViewFactory().getView(HostCpuView.class); view.clearCpuLoadData(); DAOFactory daos = ApplicationContext.getInstance().getDAOFactory(); hostInfoDAO = daos.getHostInfoDAO(); @@ -72,7 +72,7 @@ backgroundUpdateTimer = ApplicationContext.getInstance().getTimerFactory().createTimer(); backgroundUpdateTimer.setAction(new Runnable() { - + @Override public void run() { updateView(); @@ -114,10 +114,6 @@ view.addCpuLoadData(result); } - protected HostCpuView createView() { - return new HostCpuPanel(); - } - public Component getComponent() { return view.getUiComponent(); }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuView.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,9 +39,10 @@ import java.awt.Component; import java.util.List; +import com.redhat.thermostat.common.View; import com.redhat.thermostat.common.model.DiscreteTimeData; -public interface HostCpuView { +public interface HostCpuView extends View { void setCpuCount(String count);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java Mon Apr 16 15:41:08 2012 +0200 @@ -74,7 +74,7 @@ hostInfoDAO = daos.getHostInfoDAO(); memoryStatDAO = daos.getMemoryStatDAO(); - view = createView(); + view = ApplicationContext.getInstance().getViewFactory().getView(HostMemoryView.class); view.addMemoryChart(MemoryType.MEMORY_TOTAL.name(), localize(LocaleResources.HOST_MEMORY_TOTAL)); view.addMemoryChart(MemoryType.MEMORY_FREE.name(), localize(LocaleResources.HOST_MEMORY_FREE)); @@ -117,10 +117,6 @@ return view.getUiComponent(); } - protected HostMemoryView createView() { - return new HostMemoryPanel(); - } - private void doMemoryChartUpdate() { List<DiscreteTimeData<? extends Number>> memFree = new LinkedList<>(); List<DiscreteTimeData<? extends Number>> memTotal = new LinkedList<>(); @@ -128,7 +124,7 @@ List<DiscreteTimeData<? extends Number>> buf = new LinkedList<>(); List<DiscreteTimeData<? extends Number>> swapTotal = new LinkedList<>(); List<DiscreteTimeData<? extends Number>> swapFree = new LinkedList<>(); - + for (MemoryStat stat : memoryStatDAO.getLatestMemoryStats(ref)) { long timeStamp = stat.getTimeStamp(); memFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getFree()));
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryView.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,9 +39,10 @@ import java.awt.Component; import java.util.List; +import com.redhat.thermostat.common.View; import com.redhat.thermostat.common.model.DiscreteTimeData; -public interface HostMemoryView { +public interface HostMemoryView extends View { public interface GraphVisibilityChangeListener { public void show(String tag);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewController.java Mon Apr 16 15:41:08 2012 +0200 @@ -87,15 +87,11 @@ networkTableColumnVector.add(localize(LocaleResources.NETWORK_IPV6_COLUMN)); backgroundUpdateTimer = new Timer(); - view = createView(); + view = ApplicationContext.getInstance().getViewFactory().getView(HostOverviewView.class); view.setNetworkTableColumns(networkTableColumnVector.toArray()); } - public HostOverviewView createView() { - return new HostOverviewPanel(); - } - private void doNetworkTableUpdateAsync() { new NetworkTableModelUpdater().execute(); }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewView.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,7 +38,9 @@ import java.awt.Component; -public interface HostOverviewView { +import com.redhat.thermostat.common.View; + +public interface HostOverviewView extends View { void setHostName(String newHostName);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/MainWindow.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/MainWindow.java Mon Apr 16 15:41:08 2012 +0200 @@ -43,6 +43,7 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; +import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; @@ -54,6 +55,7 @@ import java.util.concurrent.ExecutionException; import javax.swing.BorderFactory; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; @@ -223,17 +225,17 @@ private final ShutdownClient shutdownAction; - private ApplicationInfo appInfo; + private ApplicationInfo appInfo; private ActionNotifier<Action> actionNotifier = new ActionNotifier<>(this); - private final DefaultMutableTreeNode publishedRoot = + private final DefaultMutableTreeNode publishedRoot = new DefaultMutableTreeNode(localize(LocaleResources.MAIN_WINDOW_TREE_ROOT_NAME)); private final DefaultTreeModel publishedTreeModel = new DefaultTreeModel(publishedRoot); public MainWindow(UiFacadeFactory facadeFactory) { super(); - + appInfo = new ApplicationInfo(); setTitle(appInfo.getName()); @@ -292,6 +294,40 @@ fileExitMenu.addActionListener(shutdownAction); fileMenu.add(fileExitMenu); + JMenu editMenu = new JMenu(localize(LocaleResources.MENU_EDIT)); + mainMenuBar.add(editMenu); + + JMenuItem configureAgentMenuItem = new JMenuItem(localize(LocaleResources.MENU_EDIT_CONFIGURE_AGENT)); + configureAgentMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + fireViewAction(Action.SHOW_AGENT_CONFIG); + } + }); + editMenu.add(configureAgentMenuItem); + + JMenuItem configureClientMenuItem = new JMenuItem(localize(LocaleResources.MENU_EDIT_CONFIGURE_CLIENT)); + configureClientMenuItem.setName("showClientConfig"); + configureClientMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + fireViewAction(Action.SHOW_CLIENT_CONFIG); + } + }); + editMenu.add(configureClientMenuItem); + + editMenu.addSeparator(); + JMenuItem historyModeMenuItem = new JCheckBoxMenuItem(localize(LocaleResources.MENU_EDIT_ENABLE_HISTORY_MODE)); + historyModeMenuItem.setName("historyModeSwitch"); + historyModeMenuItem.setSelected(false); + historyModeMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + fireViewAction(Action.SWITCH_HISTORY_MODE); + } + }); + + editMenu.add(historyModeMenuItem); JMenu helpMenu = new JMenu(localize(LocaleResources.MENU_HELP)); helpMenu.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); mainMenuBar.add(helpMenu); @@ -499,6 +535,7 @@ } } + @Override public void addActionListener(ActionListener<Action> l) { actionNotifier.addActionListener(l); } @@ -511,6 +548,7 @@ actionNotifier.fireAction(action); } + @Override public void updateTree(String filter, HostsVMsLoader hostsVMsLoader) { BackgroundTreeModelWorker worker = new BackgroundTreeModelWorker(publishedTreeModel, publishedRoot, filter, hostsVMsLoader); worker.execute();
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java Mon Apr 16 15:41:08 2012 +0200 @@ -75,11 +75,7 @@ public VmClassStatController(VmRef ref) { this.ref = ref; dao = ApplicationContext.getInstance().getDAOFactory().getVmClassStatsDAO(); - classesView = createView(); - } - - protected VmClassStatView createView() { - return new VmClassStatPanel(); + classesView = ApplicationContext.getInstance().getViewFactory().getView(VmClassStatView.class); } @Override
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatView.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,9 +39,10 @@ import java.awt.Component; import java.util.List; +import com.redhat.thermostat.common.View; import com.redhat.thermostat.common.model.DiscreteTimeData; -public interface VmClassStatView { +public interface VmClassStatView extends View { void clearClassCount();
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java Mon Apr 16 15:41:08 2012 +0200 @@ -61,12 +61,9 @@ public VmCpuController(VmRef ref) { this.ref = ref; dao = ApplicationContext.getInstance().getDAOFactory().getVmCpuStatDAO(); - view = createView(); + view = ApplicationContext.getInstance().getViewFactory().getView(VmCpuView.class); } - protected VmCpuView createView() { - return new VmCpuPanel(); - } @Override public void start() {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuView.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,9 +39,10 @@ import java.awt.Component; import java.util.List; +import com.redhat.thermostat.common.View; import com.redhat.thermostat.common.model.DiscreteTimeData; -public interface VmCpuView { +public interface VmCpuView extends View { void addData(List<DiscreteTimeData<? extends Number>> data);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java Mon Apr 16 15:41:08 2012 +0200 @@ -75,17 +75,13 @@ public VmGcController(VmRef ref) { this.ref = ref; - this.view = createView(); + this.view = ApplicationContext.getInstance().getViewFactory().getView(VmGcView.class); DAOFactory df = ApplicationContext.getInstance().getDAOFactory(); gcDao = df.getVmGcStatDAO(); memDao = df.getVmMemoryStatDAO(); } - protected VmGcView createView() { - return new VmGcPanel(); - } - @Override public void start() { timer.scheduleAtFixedRate(new TimerTask() {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmGcView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmGcView.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,9 +39,10 @@ import java.awt.Component; import java.util.List; +import com.redhat.thermostat.common.View; import com.redhat.thermostat.common.model.DiscreteTimeData; -public interface VmGcView { +public interface VmGcView extends View { void addChart(String tag, String title);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java Mon Apr 16 15:41:08 2012 +0200 @@ -61,7 +61,7 @@ public VmMemoryController(VmRef ref) { this.ref = ref; dao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO(); - view = createView(); + view = ApplicationContext.getInstance().getViewFactory().getView(VmMemoryView.class); } @Override @@ -88,10 +88,6 @@ timer.cancel(); } - protected VmMemoryView createView() { - return new VmMemoryPanel(); - } - public Component getComponent() { return view.getUiComponent(); }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryView.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,7 +38,9 @@ import java.awt.Component; -public interface VmMemoryView { +import com.redhat.thermostat.common.View; + +public interface VmMemoryView extends View { void setMemoryRegionSize(String name, long used, long allocated, long max);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java Mon Apr 16 15:41:08 2012 +0200 @@ -64,7 +64,7 @@ public VmOverviewController(VmRef vmRef) { this.ref = vmRef; - this.view = createView(); + this.view = ApplicationContext.getInstance().getViewFactory().getView(VmOverviewView.class); dao = ApplicationContext.getInstance().getDAOFactory().getVmInfoDAO(); @@ -110,10 +110,6 @@ timer.cancel(); } - protected VmOverviewView createView() { - return new VmOverviewPanel(); - } - public Component getComponent() { return view.getUiComponent(); }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewView.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewView.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,7 +38,9 @@ import java.awt.Component; -public interface VmOverviewView { +import com.redhat.thermostat.common.View; + +public interface VmOverviewView extends View { void setVmPid(String pid);
--- a/client/src/main/resources/com/redhat/thermostat/client/locale/strings.properties Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/main/resources/com/redhat/thermostat/client/locale/strings.properties Mon Apr 16 15:41:08 2012 +0200 @@ -15,6 +15,10 @@ MENU_FILE_IMPORT = Import MENU_FILE_EXPORT = Export MENU_FILE_EXIT = Exit +MENU_EDIT = Edit +MENU_EDIT_CONFIGURE_AGENT = Configure Agent... +MENU_EDIT_CONFIGURE_CLIENT = Client Preferences... +MENU_EDIT_ENABLE_HISTORY_MODE = Enable History Mode MENU_HELP = Help MENU_HELP_ABOUT = About @@ -135,3 +139,11 @@ VM_CLASSES_CHART_REAL_TIME_LABEL = Time VM_CLASSES_CHART_LOADED_CLASSES_LABEL = Number of loaded classes VM_INFO_TAB_CLASSES = Classes + +CONFIGURE_AGENT_WINDOW_TITLE = Configure Agent Backends +CONFIGURE_AGENT_AGENTS_LIST = Agents +CONFIGURE_ENABLE_BACKENDS = Enable/Disable Backends + +CLIENT_PREFS_WINDOW_TITLE = Preferences +CLIENT_PREFS_GENERAL = General +CLIENT_PREFS_STORAGE_URL = Storage Url \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/test/java/com/redhat/thermostat/client/DefaultViewFactoryTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import com.redhat.thermostat.common.View; + +public class DefaultViewFactoryTest { + + public static class MockView implements View {} + + @Test + public void testGetUnknownClasses() { + DefaultViewFactory factory = new DefaultViewFactory(); + assertEquals(null, factory.getView(MockView.class)); + } + + @Test + public void testSetAndGet() { + DefaultViewFactory factory = new DefaultViewFactory(); + factory.setViewClass(MockView.class, MockView.class); + assertEquals(MockView.class, factory.getViewClass(MockView.class)); + } + + @Test + public void testInstantiation() { + DefaultViewFactory factory = new DefaultViewFactory(); + factory.setViewClass(MockView.class, MockView.class); + MockView view = factory.getView(MockView.class); + assertNotNull(view); + assertEquals(MockView.class.getName(), view.getClass().getName()); + } +}
--- a/client/src/test/java/com/redhat/thermostat/client/MainWindowControllerImplTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/MainWindowControllerImplTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -79,6 +79,7 @@ private HostInfoDAO mockHostsDAO; private VmInfoDAO mockVmsDAO; + @SuppressWarnings({ "unchecked", "rawtypes" }) // ActionListener fluff @Before public void setUp() { ApplicationContextUtil.resetApplicationContext(); @@ -149,7 +150,7 @@ controller.showMainMainWindow(); verify(view).showMainWindow(); } - + @Test public void verifyUpdateHostsVMsLoadsCorrectHosts() { @@ -157,8 +158,8 @@ expectedHosts.add(new HostRef("123", "fluffhost1")); expectedHosts.add(new HostRef("456", "fluffhost2")); - when(mockHostsDAO.getHosts()).thenReturn(expectedHosts); - + when(mockHostsDAO.getAliveHosts()).thenReturn(expectedHosts); + controller.doUpdateTreeAsync(); ArgumentCaptor<HostsVMsLoader> arg = ArgumentCaptor.forClass(HostsVMsLoader.class); @@ -170,6 +171,35 @@ } @Test + public void verifyHistoryModeUpdateHostsVMCorrectly() { + + Collection<HostRef> liveHost = new ArrayList<>(); + liveHost.add(new HostRef("123", "fluffhost1")); + liveHost.add(new HostRef("456", "fluffhost2")); + + Collection<HostRef> allHosts = new ArrayList<>(); + allHosts.addAll(liveHost); + allHosts.add(new HostRef("789", "fluffhost3")); + + when(mockHostsDAO.getAliveHosts()).thenReturn(liveHost); + when(mockHostsDAO.getHosts()).thenReturn(allHosts); + + controller.doUpdateTreeAsync(); + + ArgumentCaptor<HostsVMsLoader> arg = ArgumentCaptor.forClass(HostsVMsLoader.class); + verify(view).updateTree(anyString(), arg.capture()); + HostsVMsLoader loader = arg.getValue(); + + Collection<HostRef> actualHosts = loader.getHosts(); + assertEqualCollection(liveHost, actualHosts); + + l.actionPerformed(new ActionEvent<MainView.Action>(view, MainView.Action.SWITCH_HISTORY_MODE)); + + actualHosts = loader.getHosts(); + assertEqualCollection(allHosts, actualHosts); + } + + @Test public void verifyUpdateHostsVMsLoadsCorrectVMs() { Collection<VmRef> expectedVMs = new ArrayList<>();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/test/java/com/redhat/thermostat/client/SwingViewFactoryTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client; + +import static org.junit.Assert.assertNotNull; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.SwingUtilities; + +import org.junit.Test; + +import com.redhat.thermostat.client.ui.AgentConfigurationView; +import com.redhat.thermostat.client.ui.ClientConfigurationView; +import com.redhat.thermostat.client.ui.HostCpuView; +import com.redhat.thermostat.client.ui.HostMemoryView; +import com.redhat.thermostat.client.ui.HostOverviewView; +import com.redhat.thermostat.client.ui.VmClassStatView; +import com.redhat.thermostat.client.ui.VmCpuView; +import com.redhat.thermostat.client.ui.VmGcView; +import com.redhat.thermostat.client.ui.VmMemoryView; +import com.redhat.thermostat.client.ui.VmOverviewView; +import com.redhat.thermostat.common.View; + +public class SwingViewFactoryTest { + + @Test + public void test() throws InvocationTargetException, InterruptedException { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + SwingViewFactory factory = new SwingViewFactory(); + + List<Class<? extends View>> knownViewClasses = new ArrayList<>(); + + knownViewClasses.add(AgentConfigurationView.class); + knownViewClasses.add(ClientConfigurationView.class); + knownViewClasses.add(HostCpuView.class); + knownViewClasses.add(HostMemoryView.class); + knownViewClasses.add(HostOverviewView.class); + knownViewClasses.add(VmClassStatView.class); + knownViewClasses.add(VmCpuView.class); + knownViewClasses.add(VmGcView.class); + knownViewClasses.add(VmMemoryView.class); + knownViewClasses.add(VmOverviewView.class); + + for (Class<? extends View> klass: knownViewClasses) { + assertNotNull(factory.getViewClass(klass)); + assertNotNull(factory.getView(klass)); + } + } + + }); + + } +}
--- a/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.client; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -49,6 +50,7 @@ import com.redhat.thermostat.client.ui.VmClassStatController; import com.redhat.thermostat.client.ui.VmClassStatView; +import com.redhat.thermostat.common.ViewFactory; import com.redhat.thermostat.common.appctx.ApplicationContext; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.dao.MongoDAOFactory; @@ -58,6 +60,7 @@ public class VmClassStatControllerTest { + @SuppressWarnings("unchecked") // any(List.class) @Test public void testChartUpdate() { @@ -74,15 +77,13 @@ ApplicationContext.getInstance().setDAOFactory(daoFactory); VmRef ref = mock(VmRef.class); - final VmClassStatView view = mock(VmClassStatView.class); + VmClassStatView view = mock(VmClassStatView.class); + ViewFactory viewFactory = mock(ViewFactory.class); + when(viewFactory.getView(eq(VmClassStatView.class))).thenReturn(view); - // TODO: Consider to pass the ClassesView or a factory for it to the controller instead. - VmClassStatController controller = new VmClassStatController(ref) { - @Override - protected VmClassStatView createView() { - return view; - } - }; + ApplicationContext.getInstance().setViewFactory(viewFactory); + + VmClassStatController controller = new VmClassStatController(ref); controller.start();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/test/java/com/redhat/thermostat/client/config/ClientPreferencesTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.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/client/src/test/java/com/redhat/thermostat/client/ui/AgentConfigurationControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +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.InOrder; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import com.redhat.thermostat.client.ui.AgentConfigurationView.ConfigurationAction; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; + +public class AgentConfigurationControllerTest { + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + + /* + * Set up a mock timer factory that always executes actions synchronously on start(); + */ + TimerFactory tf = mock(TimerFactory.class); + Timer timer = mock(Timer.class); + final Runnable[] runnable = new Runnable[1]; + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + runnable[0] = (Runnable) invocation.getArguments()[0]; + return null; + } + + }).when(timer).setAction(any(Runnable.class)); + + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + runnable[0].run(); + return null; + } + + }).when(timer).start(); + when(tf.createTimer()).thenReturn(timer); + ApplicationContext.getInstance().setTimerFactory(tf); + + } + + @After + public void tearDown() { + ApplicationContextUtil.resetApplicationContext(); + } + + @Test + public void testAddingEnabledBackends() { + AgentConfigurationView view = mock(AgentConfigurationView.class); + AgentConfigurationModel model = mock(AgentConfigurationModel.class); + when(model.getAgents()).thenReturn(Arrays.asList(new String[]{"agent1"})); + List<String> backends = Arrays.asList(new String[] {"backend1", "backend2"}); + when(model.getBackends(any(String.class))).thenReturn(backends); + when(model.getAgentBackendEnabled(any(String.class), any(String.class))).thenReturn(true); + + Map<String,Boolean> expected = new HashMap<>(); + expected.put("backend1", true); + expected.put("backend2", true); + + AgentConfigurationController controller = new AgentConfigurationController(model, view); + controller.showView(); + controller.hideView(); + + verify(view).addAgent("agent1"); + verify(view).setBackendStatus(eq(expected)); + verify(view).showDialog(); + verify(view).hideDialog(); + } + + @Test + public void testAddingDisabledBackends() { + AgentConfigurationView view = mock(AgentConfigurationView.class); + AgentConfigurationModel model = mock(AgentConfigurationModel.class); + when(model.getAgents()).thenReturn(Arrays.asList(new String[]{"agent1"})); + List<String> backends = Arrays.asList(new String[] {"backend1",}); + when(model.getBackends(any(String.class))).thenReturn(backends); + when(model.getAgentBackendEnabled(any(String.class), any(String.class))).thenReturn(false); + + Map<String,Boolean> expected = new HashMap<>(); + expected.put("backend1", false); + + AgentConfigurationController controller = new AgentConfigurationController(model, view); + controller.showView(); + controller.hideView(); + + verify(view).addAgent("agent1"); + verify(view).setBackendStatus(eq(expected)); + verify(view).showDialog(); + verify(view).hideDialog(); + } + + /** + * Verify that the accepting the changes signals the controller + */ + @SuppressWarnings("unchecked") // All this ActionListener fluff + @Test + public void testViewEditedBackends() { + final ActionListener<ConfigurationAction>[] listeners = (ActionListener<ConfigurationAction>[]) new ActionListener<?>[1]; + AgentConfigurationView view = mock(AgentConfigurationView.class); + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + listeners[0] = (ActionListener<ConfigurationAction>) invocation.getArguments()[0]; + return null; + } + }).when(view).addActionListener(any(ActionListener.class)); + + + AgentConfigurationModel model = mock(AgentConfigurationModel.class); + when(model.getAgents()).thenReturn(Arrays.asList(new String[]{"agent1"})); + List<String> backends = Arrays.asList(new String[] {"backend1"}); + when(model.getBackends(any(String.class))).thenReturn(backends); + when(model.getAgentBackendEnabled(any(String.class), any(String.class))).thenReturn(true); + + Map<String,Boolean> expected = new HashMap<>(); + expected.put("backend1", true); + + AgentConfigurationController controller = new AgentConfigurationController(model, view); + controller.showView(); + + listeners[0].actionPerformed(new ActionEvent<ConfigurationAction>(view, ConfigurationAction.CLOSE_ACCEPT)); + + controller.hideView(); + + InOrder inOrder = inOrder(view); + + inOrder.verify(view).addAgent("agent1"); + inOrder.verify(view).setBackendStatus(eq(expected)); + inOrder.verify(view).getBackendStatus(); + + verify(model).saveConfiguration(); + } + + /** + * Verify that controller handles cancel properly + */ + @SuppressWarnings("unchecked") // All this ActionListener fluff. + @Test + public void testViewCancelEditingBackends() { + final ActionListener<ConfigurationAction>[] listeners = (ActionListener<ConfigurationAction>[]) new ActionListener<?>[1]; + AgentConfigurationView view = mock(AgentConfigurationView.class); + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + listeners[0] = (ActionListener<ConfigurationAction>) invocation.getArguments()[0]; + return null; + } + }).when(view).addActionListener(any(ActionListener.class)); + + + AgentConfigurationModel model = mock(AgentConfigurationModel.class); + when(model.getAgents()).thenReturn(Arrays.asList(new String[]{"agent1"})); + List<String> backends = Arrays.asList(new String[] {"backend1"}); + when(model.getBackends(any(String.class))).thenReturn(backends); + when(model.getAgentBackendEnabled(any(String.class), any(String.class))).thenReturn(true); + + Map<String,Boolean> expectedConfig = new HashMap<>(); + expectedConfig.put("backend1", true); + + AgentConfigurationController controller = new AgentConfigurationController(model, view); + controller.showView(); + + listeners[0].actionPerformed(new ActionEvent<ConfigurationAction>(view, ConfigurationAction.CLOSE_CANCEL)); + + controller.hideView(); + + verify(view).addAgent("agent1"); + verify(view).setBackendStatus(eq(expectedConfig)); + verify(view, never()).getBackendStatus(); + + verify(model, never()).saveConfiguration(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/ClientConfigurationControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import com.redhat.thermostat.client.config.ClientPreferences; +import com.redhat.thermostat.common.ActionEvent; + +public class ClientConfigurationControllerTest { + + @Test + public void verifyShowDialog() { + ClientPreferences model = mock(ClientPreferences.class); + when(model.getConnectionUrl()).thenReturn("mock-connection-url"); + + ClientConfigurationView view = mock(ClientConfigurationView.class); + ClientConfigurationController controller = new ClientConfigurationController(model, view); + + controller.showDialog(); + + verify(model).getConnectionUrl(); + verify(view).setConnectionUrl(eq("mock-connection-url")); + verify(view).showDialog(); + } + + @Test + public void verifyCloseCancel() { + ClientPreferences model = mock(ClientPreferences.class); + ClientConfigurationView view = mock(ClientConfigurationView.class); + ClientConfigurationController controller = new ClientConfigurationController(model, view); + + controller.actionPerformed(new ActionEvent<>(view, ClientConfigurationView.Action.CLOSE_CANCEL)); + + verify(model, times(0)).setConnectionUrl(any(String.class)); + verify(view, times(0)).getConnectionUrl(); + verify(view, times(0)).showDialog(); + verify(view).hideDialog(); + } + + @Test + public void verifyCloseAccept() { + ClientPreferences model = mock(ClientPreferences.class); + ClientConfigurationView view = mock(ClientConfigurationView.class); + when(view.getConnectionUrl()).thenReturn("mock-connection-url"); + ClientConfigurationController controller = new ClientConfigurationController(model, view); + + controller.actionPerformed(new ActionEvent<>(view, ClientConfigurationView.Action.CLOSE_ACCEPT)); + + verify(model).setConnectionUrl(eq("mock-connection-url")); + verify(view).getConnectionUrl(); + verify(view, times(0)).showDialog(); + verify(view).hideDialog(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/ClientConfigurationFrameTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.client.ui; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.fest.swing.annotation.GUITest; +import org.fest.swing.edt.GuiActionRunner; +import org.fest.swing.edt.GuiTask; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JButtonFixture; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; + +public class ClientConfigurationFrameTest { + + private ClientConfigurationFrame frame; + private FrameFixture frameFixture; + private ActionListener<ClientConfigurationView.Action> l; + + @SuppressWarnings("unchecked") // ActionListener + @Before + public void setUp() { + frame = new ClientConfigurationFrame(); + l = mock(ActionListener.class); + frame.addListener(l); + frameFixture = new FrameFixture(frame); + + } + + @After + public void tearDown() { + frameFixture.cleanUp(); + frame.removeListener(l); + frame = null; + l = null; + } + + @Category(GUITest.class) + @Test + public void testOkayButton() { + frameFixture.show(); + + JButtonFixture button = frameFixture.button("ok"); + button.click(); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + frame.hideDialog(); + } + }); + + verify(l).actionPerformed(eq(new ActionEvent<>(frame, ClientConfigurationView.Action.CLOSE_ACCEPT))); + + + } + + @Category(GUITest.class) + @Test + public void testCancelButton() { + frameFixture.show(); + + JButtonFixture button = frameFixture.button("cancel"); + button.click(); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + frame.hideDialog(); + } + }); + + verify(l).actionPerformed(eq(new ActionEvent<>(frame, ClientConfigurationView.Action.CLOSE_CANCEL))); + + } +}
--- a/client/src/test/java/com/redhat/thermostat/client/ui/HostCpuControllerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/HostCpuControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,6 +38,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNotNull; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -58,6 +59,7 @@ import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.common.ViewFactory; import com.redhat.thermostat.common.appctx.ApplicationContext; import com.redhat.thermostat.common.appctx.ApplicationContextUtil; import com.redhat.thermostat.common.dao.CpuStatDAO; @@ -107,14 +109,13 @@ ApplicationContext.getInstance().setDAOFactory(daoFactory); view = mock(HostCpuView.class); + ViewFactory viewFactory = mock(ViewFactory.class); + when(viewFactory.getView(eq(HostCpuView.class))).thenReturn(view); + + ApplicationContext.getInstance().setViewFactory(viewFactory); + HostRef host = new HostRef("123", "fluffhost"); - controller = new HostCpuController(host) { - // TODO: Reverse dependency. - @Override - protected HostCpuView createView() { - return view; - } - }; + controller = new HostCpuController(host); timerAction = actionCaptor.getValue(); }
--- a/client/src/test/java/com/redhat/thermostat/client/ui/HostMemoryControllerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/HostMemoryControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.client.ui; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -45,9 +46,12 @@ import java.util.LinkedList; import java.util.List; +import org.junit.Before; import org.junit.Test; +import com.redhat.thermostat.common.ViewFactory; import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; @@ -58,6 +62,12 @@ public class HostMemoryControllerTest { + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + } + + @SuppressWarnings("unchecked") // any(List.class) @Test public void testUpdate() { HostInfo hostInfo = new HostInfo("someHost", "someOS", "linux_0.0.1", "lreally_fast_cpu", 2, 1024); @@ -76,14 +86,12 @@ ApplicationContext.getInstance().setDAOFactory(daoFactory); HostRef ref = mock(HostRef.class); - final HostMemoryView view = mock(HostMemoryView.class); - // TODO: Consider to pass the ClassesView or a factory for it to the controller instead. - HostMemoryController controller = new HostMemoryController(ref) { - @Override - protected HostMemoryView createView() { - return view; - } - }; + HostMemoryView view = mock(HostMemoryView.class); + ViewFactory viewFactory = mock(ViewFactory.class); + when(viewFactory.getView(eq(HostMemoryView.class))).thenReturn(view); + ApplicationContext.getInstance().setViewFactory(viewFactory); + + HostMemoryController controller = new HostMemoryController(ref); controller.start();
--- a/client/src/test/java/com/redhat/thermostat/client/ui/MainWindowTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/MainWindowTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -42,22 +42,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.beans.PropertyChangeEvent; -import java.util.Objects; - import org.fest.swing.annotation.GUITest; import org.fest.swing.edt.GuiActionRunner; import org.fest.swing.edt.GuiTask; import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JMenuItemFixture; import org.fest.swing.fixture.JTextComponentFixture; import org.fest.swing.junit.v4_5.runner.GUITestRunner; -import org.hamcrest.Description; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; import com.redhat.thermostat.client.ChangeableText; import com.redhat.thermostat.client.MainView; @@ -69,34 +65,11 @@ @RunWith(GUITestRunner.class) public class MainWindowTest { - private static class PropertyChangeEventMatcher extends ArgumentMatcher<PropertyChangeEvent> { - - private PropertyChangeEvent event; - - private PropertyChangeEventMatcher(PropertyChangeEvent ev) { - event = ev; - } - - @Override - public boolean matches(Object argument) { - PropertyChangeEvent other = (PropertyChangeEvent) argument; - return event.getSource() == other.getSource() - && Objects.equals(event.getPropertyName(), other.getPropertyName()) - && Objects.equals(event.getNewValue(), other.getNewValue()) - && Objects.equals(event.getOldValue(), other.getOldValue()); - } - - @Override - public void describeTo(Description description) { - super.describeTo(description); - description.appendText(event.getSource() + ", " + event.getPropertyName() + ", " + event.getOldValue() + ", " + event.getNewValue()); - } - } - private FrameFixture frameFixture; private MainWindow window; private ActionListener<MainView.Action> l; + @SuppressWarnings("unchecked") // mock(ActionListener.class) @Before public void setUp() { @@ -147,7 +120,7 @@ @Test public void verifyShowMainWindowShowsWindow() { GuiActionRunner.execute(new GuiTask() { - + @Override protected void executeInEDT() throws Throwable { window.showMainWindow(); @@ -158,6 +131,31 @@ @Category(GUITest.class) @Test + public void verifyThatClientPreferencesMenuItemTriggersEvent() { + frameFixture.show(); + JMenuItemFixture menuItem = frameFixture.menuItem("showClientConfig"); + menuItem.click(); + frameFixture.close(); + frameFixture.requireNotVisible(); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHOW_CLIENT_CONFIG)); + + } + + @Category(GUITest.class) + @Test + public void verifyThatHistorySwitchTriggersEvent() { + frameFixture.show(); + JMenuItemFixture menuItem = frameFixture.menuItem("historyModeSwitch"); + menuItem.click(); + frameFixture.close(); + frameFixture.requireNotVisible(); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SWITCH_HISTORY_MODE)); + } + + @Category(GUITest.class) + @Test public void testGetHostVMTreeFilter() { frameFixture.show(); JTextComponentFixture hostVMTreeFilterField = frameFixture.textBox("hostVMTreeFilter"); @@ -166,5 +164,5 @@ assertEquals("test", window.getHostVmTreeFilter()); } - + }
--- a/client/src/test/java/com/redhat/thermostat/client/ui/VmCpuControllerTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/client/src/test/java/com/redhat/thermostat/client/ui/VmCpuControllerTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.client.ui; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -45,9 +46,12 @@ import java.util.ArrayList; import java.util.List; +import org.junit.Before; import org.junit.Test; +import com.redhat.thermostat.common.ViewFactory; import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.dao.MongoDAOFactory; import com.redhat.thermostat.common.dao.VmCpuStatDAO; @@ -57,6 +61,12 @@ public class VmCpuControllerTest { + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + } + + @SuppressWarnings("unchecked") // any(List.class) @Test public void testChartUpdate() { @@ -74,14 +84,12 @@ VmRef ref = mock(VmRef.class); final VmCpuView view = mock(VmCpuView.class); + ViewFactory viewFactory = mock(ViewFactory.class); + when(viewFactory.getView(eq(VmCpuView.class))).thenReturn(view); - // TODO: Consider to pass the ClassesView or a factory for it to the controller instead. - VmCpuController controller = new VmCpuController(ref) { - @Override - protected VmCpuView createView() { - return view; - } - }; + ApplicationContext.getInstance().setViewFactory(viewFactory); + + VmCpuController controller = new VmCpuController(ref); controller.start();
--- a/common/src/main/java/com/redhat/thermostat/cli/AppContextSetupImpl.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/cli/AppContextSetupImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,11 +38,11 @@ import com.redhat.thermostat.common.appctx.ApplicationContext; import com.redhat.thermostat.common.config.StartupConfiguration; -import com.redhat.thermostat.common.dao.Connection; -import com.redhat.thermostat.common.dao.ConnectionProvider; import com.redhat.thermostat.common.dao.DAOFactory; -import com.redhat.thermostat.common.dao.MongoConnectionProvider; 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 { @@ -50,7 +50,7 @@ public void setupAppContext(String dbUrl) { StartupConfiguration config = new ConnectionConfiguration(dbUrl); - ConnectionProvider connProv = new MongoConnectionProvider(config); + StorageProvider connProv = new MongoStorageProvider(config); DAOFactory daoFactory = new MongoDAOFactory(connProv); Connection connection = daoFactory.getConnection(); connection.connect();
--- a/common/src/main/java/com/redhat/thermostat/cli/CommandException.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/cli/CommandException.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,6 +38,8 @@ public class CommandException extends Exception { + private static final long serialVersionUID = 3730368617641245016L; + public CommandException() { super(); }
--- a/common/src/main/java/com/redhat/thermostat/common/ActionEvent.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/ActionEvent.java Mon Apr 16 15:41:08 2012 +0200 @@ -40,6 +40,8 @@ public class ActionEvent<T extends Enum<?>> extends EventObject { + private static final long serialVersionUID = -8648206929150142342L; + public ActionEvent(Object source, T actionId) { super(source); if (actionId == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/View.java Mon Apr 16 15:41:08 2012 +0200 @@ -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/src/main/java/com/redhat/thermostat/common/ViewFactory.java Mon Apr 16 15:41:08 2012 +0200 @@ -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); +}
--- a/common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/appctx/ApplicationContext.java Mon Apr 16 15:41:08 2012 +0200 @@ -37,6 +37,7 @@ 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 { @@ -47,6 +48,8 @@ private TimerFactory timerFactory; + private ViewFactory viewFactory; + public static ApplicationContext getInstance() { return instance; } @@ -76,4 +79,12 @@ return timerFactory; } + public ViewFactory getViewFactory() { + return viewFactory; + } + + public void setViewFactory(ViewFactory viewFactory) { + this.viewFactory = viewFactory; + } + }
--- a/common/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/config/InvalidConfigurationException.java Mon Apr 16 15:41:08 2012 +0200 @@ -39,6 +39,8 @@ public class InvalidConfigurationException extends Exception { + private static final long serialVersionUID = -6555406006758264587L; + public InvalidConfigurationException() { super(); }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/Connection.java Mon Apr 16 14:23:46 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.dao; - -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<ConnectionListener> listeners = new CopyOnWriteArrayList<ConnectionListener>(); - - 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/dao/ConnectionProvider.java Mon Apr 16 14:23:46 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.dao; - -public interface ConnectionProvider { - - Connection createConnection(); -}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -66,12 +66,12 @@ } @Override - public long getCount() { - return storage.getCount(cpuStatCategory); + public void putCpuStat(CpuStat stat) { + storage.putChunk(converter.toChunk(stat)); } @Override - public void putCpuStat(CpuStat stat) { - storage.putChunk(converter.toChunk(stat)); + public long getCount() { + return storage.getCount(cpuStatCategory); } }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Apr 16 15:41:08 2012 +0200 @@ -36,11 +36,14 @@ 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 will be replaced by getStorage() as soon as Storage and Connection have been merged. - */ + + // 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();
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -57,5 +57,8 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -40,6 +40,7 @@ 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; @@ -63,9 +64,19 @@ } @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.findAllFromCategory(hostInfoCategory); + + Cursor hostsCursor = storage.findAll(filter); while(hostsCursor.hasNext()) { Chunk hostChunk = hostsCursor.next(); String agentId = hostChunk.get(Key.AGENT_ID); @@ -74,7 +85,26 @@ } 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/MemoryStatDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -57,4 +57,6 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -66,6 +66,11 @@ } @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/MongoConnection.java Mon Apr 16 14:23:46 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.dao; - -import java.net.UnknownHostException; -import java.util.logging.Logger; - -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; -import com.redhat.thermostat.common.storage.StorageConstants; -import com.redhat.thermostat.common.utils.LoggingUtils; - -public class MongoConnection extends Connection { - private static final Logger logger = LoggingUtils.getLogger(MongoConnection.class); - - private Mongo m = null; - private DB db = null; - - private StartupConfiguration conf; - - private MongoConnection() { /* nothing to do */ } - - public 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 (MongoException | UnknownHostException | - NotImplementedException | IllegalArgumentException e) - { - fireChanged(ConnectionStatus.FAILED_TO_CONNECT); - return; - } - fireChanged(ConnectionStatus.CONNECTED); - connected = true; - } - - private void createConnection() throws MongoException, UnknownHostException { - this.m = new Mongo(getMongoURI()); - this.db = m.getDB(StorageConstants.THERMOSTAT_DB_NAME); - } - - private void testConnection() { - db.getCollection("agent-config").getCount(); - } - - private MongoURI getMongoURI() { - MongoURI uri = new MongoURI(conf.getDBConnectionString()); - return uri; - } - - public DB getDB() { - return db; - } - - @Override - public void disconnect() { - if (m != null) { - m.close(); - } - connected = false; - } -}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoConnectionProvider.java Mon Apr 16 14:23:46 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.dao; - -import com.redhat.thermostat.common.config.StartupConfiguration; - -public class MongoConnectionProvider implements ConnectionProvider { - - private StartupConfiguration configuration; - - public MongoConnectionProvider(StartupConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public Connection createConnection() { - return new MongoConnection(configuration); - } - -}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java Mon Apr 16 15:41:08 2012 +0200 @@ -36,78 +36,84 @@ package com.redhat.thermostat.common.dao; -import com.redhat.thermostat.common.dao.Connection.ConnectionListener; -import com.redhat.thermostat.common.dao.Connection.ConnectionStatus; -import com.redhat.thermostat.common.storage.MongoStorage; +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 Connection connection; private final Storage storage; - public MongoDAOFactory(ConnectionProvider connProv) { - - connection = connProv.createConnection(); - final MongoStorage mongoStorage = new MongoStorage(connection); - storage = mongoStorage; - connection.addListener(new ConnectionListener() { - - @Override - public void changed(ConnectionStatus newStatus) { - if (newStatus == ConnectionStatus.CONNECTED) { - mongoStorage.connect(((MongoConnection) connection).getDB()); - } - } - }); + public MongoDAOFactory(StorageProvider prov) { + storage = prov.createStorage(); } @Override public Connection getConnection() { - return connection; + 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/NetworkInterfaceInfoDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -52,4 +52,6 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -48,9 +48,11 @@ class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO { private Storage storage; + private NetworkInterfaceInfoConverter converter; NetworkInterfaceInfoDAOImpl(Storage storage) { this.storage = storage; + converter = new NetworkInterfaceInfoConverter(); } @Override @@ -59,7 +61,6 @@ query.put(Key.AGENT_ID, ref.getAgentId()); Cursor cursor = storage.findAll(query); - NetworkInterfaceInfoConverter converter = new NetworkInterfaceInfoConverter(); List<NetworkInterfaceInfo> result = new ArrayList<>(); while (cursor.hasNext()) { Chunk chunk = cursor.next(); @@ -69,4 +70,9 @@ return result; } + @Override + public void putNetworkInterfaceInfo(NetworkInterfaceInfo info) { + storage.putChunk(converter.toChunk(info)); + } + }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -51,4 +51,6 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -64,4 +64,9 @@ } return getter.getLatest(); } + + @Override + public void putVmClassStat(VmClassStat stat) { + storage.putChunk(converter.toChunk(stat)); + } }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -51,4 +51,6 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -64,4 +64,9 @@ } return getter.getLatest(); } + + @Override + public void putVmCpuStat(VmCpuStat stat) { + storage.putChunk(converter.toChunk(stat)); + } }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -54,4 +54,6 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -65,4 +65,9 @@ return getter.getLatest(); } + @Override + public void putVmGcStat(VmGcStat stat) { + storage.putChunk(converter.toChunk(stat)); + } + }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -72,4 +72,8 @@ 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -102,4 +102,21 @@ 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/VmMemoryStatDAO.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java Mon Apr 16 15:41:08 2012 +0200 @@ -87,4 +87,6 @@ public VmMemoryStat getLatestMemoryStat(VmRef ref); + public void putVmMemoryStat(VmMemoryStat stat); + }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java Mon Apr 16 15:41:08 2012 +0200 @@ -45,9 +45,11 @@ class VmMemoryStatDAOImpl implements VmMemoryStatDAO { private final Storage storage; + private final VmMemoryStatConverter converter; VmMemoryStatDAOImpl(Storage storage) { this.storage = storage; + converter = new VmMemoryStatConverter(); } @Override @@ -57,9 +59,14 @@ query.put(Key.VM_ID, ref.getId()); Cursor cursor = storage.findAll(query).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1); if (cursor.hasNext()) { - return new VmMemoryStatConverter().fromChunk(cursor.next()); + return converter.fromChunk(cursor.next()); } return null; } + @Override + public void putVmMemoryStat(VmMemoryStat stat) { + storage.putChunk(converter.toChunk(stat)); + } + }
--- a/common/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/AgentInformation.java Mon Apr 16 15:41:08 2012 +0200 @@ -42,9 +42,18 @@ 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; } @@ -53,10 +62,26 @@ 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/ChunkConverter.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/ChunkConverter.java Mon Apr 16 15:41:08 2012 +0200 @@ -117,12 +117,14 @@ } } + @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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/Connection.java Mon Apr 16 15:41:08 2012 +0200 @@ -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); + } + } +}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/ConnectionFailedException.java Mon Apr 16 14:23:46 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 class ConnectionFailedException extends Exception { - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/MongoConnection.java Mon Apr 16 15:41:08 2012 +0200 @@ -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.storage; + +import java.net.UnknownHostException; +import java.util.logging.Level; +import java.util.logging.Logger; + +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; +import com.redhat.thermostat.common.utils.LoggingUtils; + +class MongoConnection extends Connection { + + private static final Logger logger = LoggingUtils.getLogger(MongoConnection.class); + 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 (MongoException | UnknownHostException | + NotImplementedException | IllegalArgumentException e) + { + logger.log(Level.WARNING, "Connection failed.", e); + fireChanged(ConnectionStatus.FAILED_TO_CONNECT); + return; + } + 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/MongoStorage.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Mon Apr 16 15:41:08 2012 +0200 @@ -50,8 +50,9 @@ import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.WriteConcern; -import com.redhat.thermostat.common.dao.Connection; -import com.redhat.thermostat.common.dao.MongoConnection; +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. @@ -60,32 +61,35 @@ */ public class MongoStorage extends Storage { - public MongoStorage(Connection connection) { - super(connection); - } - 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; - @Override - public void connect() throws ConnectionFailedException { - connection.connect(); - db = ((MongoConnection) connection).getDB(); + 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 + } + } + }); } - /** - * Connects to an already existing connection. TODO: This is here for compatibility with the Connection class - * until they have been merged. - * - * @param db - */ - public void connect(DB db) { - this.db = db; + @Override + public Connection getConnection() { + return conn; } @Override @@ -93,35 +97,6 @@ this.agentId = agentId; } - @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 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; - } - private BasicDBObject getAgentDBObject() { return new BasicDBObject(KEY_AGENT_ID, agentId.toString()); } @@ -259,11 +234,15 @@ 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; } @@ -287,13 +266,14 @@ 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 @@ -311,7 +291,8 @@ Category cat = query.getCategory(); DBCollection coll = getCachedCollection(cat.getName()); ChunkConverter converter = new ChunkConverter(); - DBCursor dbCursor = coll.find(converter.chunkToDBObject(query)); + DBObject obj = converter.chunkToDBObject(query); + DBCursor dbCursor = coll.find(obj); return new MongoCursor(dbCursor, query.getCategory()); } @@ -330,7 +311,7 @@ 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()); @@ -346,4 +327,45 @@ } 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/src/main/java/com/redhat/thermostat/common/storage/MongoStorageProvider.java Mon Apr 16 15:41:08 2012 +0200 @@ -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); + } + +}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Storage.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/Storage.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,29 +38,11 @@ import java.util.UUID; -import com.redhat.thermostat.common.dao.Connection; public abstract class Storage { - protected Connection connection; - - public Storage (Connection connection) { - this.connection = connection; - } - - public abstract void connect() throws ConnectionFailedException; - public abstract void setAgentId(UUID id); - public abstract void addAgentInformation(AgentInformation agentInfo); - - public abstract void removeAgentInformation(); - - /** - * @return {@code null} if the value is invalid or missing - */ - public abstract String getBackendConfig(String backendName, String configurationKey); - public final void registerCategory(Category category) { if (category.hasBeenRegistered()) { throw new IllegalStateException("Category may only be associated with one backend."); @@ -69,21 +51,37 @@ 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. + /** + * 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 Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/StorageConstants.java Mon Apr 16 15:41:08 2012 +0200 @@ -48,4 +48,7 @@ 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/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java Mon Apr 16 15:41:08 2012 +0200 @@ -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(); +}
--- a/common/src/main/java/com/redhat/thermostat/tools/ApplicationException.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/tools/ApplicationException.java Mon Apr 16 15:41:08 2012 +0200 @@ -38,6 +38,8 @@ public class ApplicationException extends Exception { + private static final long serialVersionUID = 5910852125476383826L; + public ApplicationException() { }
--- a/common/src/test/java/com/redhat/thermostat/cli/AppContextSetupImplTest.java Mon Apr 16 14:23:46 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.cli; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import com.redhat.thermostat.cli.AppContextSetupImpl; -import com.redhat.thermostat.common.appctx.ApplicationContext; -import com.redhat.thermostat.common.config.StartupConfiguration; -import com.redhat.thermostat.common.dao.MongoConnection; -import com.redhat.thermostat.common.dao.MongoConnectionProvider; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(MongoConnectionProvider.class) -public class AppContextSetupImplTest { - - @Test - public void testSetup() throws Exception { - // TODO: Figure out how to test this class without using PowerMock. - final MongoConnection conn = mock(MongoConnection.class); - PowerMockito.whenNew(MongoConnection.class).withArguments(Mockito.any(StartupConfiguration.class)).thenAnswer(new Answer<MongoConnection>() { - - @Override - public MongoConnection answer(InvocationOnMock invocation) - throws Throwable { - StartupConfiguration conf = (StartupConfiguration) invocation.getArguments()[0]; - assertEquals("mongodb://fluff:27518", conf.getDBConnectionString()); - return conn; - } - - }); - AppContextSetupImpl setup = new AppContextSetupImpl(); - - setup.setupAppContext("mongodb://fluff:27518"); - - assertNotNull(ApplicationContext.getInstance().getDAOFactory()); - } - -}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/ConnectionTest.java Mon Apr 16 14:23:46 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 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.dao.Connection.ConnectionListener; -import com.redhat.thermostat.common.dao.Connection.ConnectionStatus; - -public class ConnectionTest { - - private Connection connection; - - private ConnectionListener listener1; - private 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(ConnectionListener.class); - listener2 = mock(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/dao/CpuStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -139,6 +139,16 @@ 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
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -43,12 +43,16 @@ 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; @@ -57,6 +61,13 @@ 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()); @@ -73,12 +84,6 @@ @Test public void testGetHostInfo() { - 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); @@ -125,7 +130,8 @@ Storage storage = mock(Storage.class); when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor); - + when(storage.findAll(any(Chunk.class))).thenReturn(cursor); + return storage; } @@ -161,8 +167,29 @@ Storage storage = mock(Storage.class); when(storage.findAllFromCategory(HostInfoDAO.hostInfoCategory)).thenReturn(cursor); + when(storage.findAll(any(Chunk.class))).thenReturn(cursor); + + return storage; + } - 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 @@ -173,4 +200,127 @@ 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/MemoryStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -59,6 +59,17 @@ 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()); @@ -78,14 +89,6 @@ @Test public void testGetLatestMemoryStats() { - 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); @@ -129,14 +132,6 @@ @Test public void testGetLatestMemoryStatsTwice() { - 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); @@ -168,6 +163,28 @@ } @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);
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoConnectionTest.java Mon Apr 16 14:23:46 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.dao; - -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.net.UnknownHostException; - -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.dao.Connection.ConnectionListener; -import com.redhat.thermostat.common.dao.Connection.ConnectionStatus; -import com.redhat.thermostat.common.storage.StorageConstants; - -@PrepareForTest(MongoConnection.class) -@RunWith(PowerMockRunner.class) -public class MongoConnectionTest { - - private MongoConnection connection; - private ConnectionListener listener; - - @Before - public void setUp() { - StartupConfiguration conf = mock(StartupConfiguration.class); - when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518"); - connection = new MongoConnection(conf); - listener = mock(ConnectionListener.class); - connection.addListener(listener); - } - - @After - public void tearDown() { - connection = 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 mongo = mock(Mongo.class); - when(mongo.getDB(StorageConstants.THERMOSTAT_DB_NAME)).thenReturn(db); - - PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(mongo); - - - connection.connect(); - - - verify(listener).changed(ConnectionStatus.CONNECTED); - } - - @Test - public void testConnectUnknownHostException() throws Exception { - - PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new UnknownHostException()); - - connection.connect(); - - verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT); - } - - @Test - public void testConnectMongoException() throws Exception { - - PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new MongoException("fluff")); - - connection.connect(); - - verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT); - } -}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -36,39 +36,43 @@ package com.redhat.thermostat.common.dao; -import static org.junit.Assert.*; +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.mongodb.DB; +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 MongoConnection conn; - private ConnectionProvider connProvider; + private Storage storage; + private Connection connection; + private StorageProvider provider; private DAOFactory daoFactory; - private DB db; HostRef hostRef; VmRef vmRef; @Before public void setUp() { - conn = mock(MongoConnection.class); - connProvider = mock(ConnectionProvider.class); - when(connProvider.createConnection()).thenReturn(conn); - db = mock(DB.class); - when(conn.getDB()).thenReturn(db); + 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(connProvider); + daoFactory = new MongoDAOFactory(provider); } @Test public void testGetConnection() { - assertSame(conn, daoFactory.getConnection()); + assertSame(storage, daoFactory.getStorage()); } @Test
--- a/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -59,6 +59,10 @@ 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; @@ -75,9 +79,6 @@ @Test public void testGetNetworkInterfaces() { - 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); @@ -109,4 +110,23 @@ 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/VmClassStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -59,6 +59,10 @@ 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()); @@ -74,10 +78,7 @@ @Test public void testGetLatestClassStatsBasic() { - Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false); - chunk.put(Key.TIMESTAMP, 1234L); - chunk.put(Key.VM_ID, 321); - chunk.put(VmClassStatDAO.loadedClassesKey, 12345L); + Chunk chunk = getChunk(); Cursor cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); @@ -103,18 +104,15 @@ assertEquals(1, vmClassStats.size()); VmClassStat stat = vmClassStats.get(0); - assertEquals(1234L, stat.getTimeStamp()); - assertEquals(12345L, stat.getLoadedClasses()); - assertEquals(321, stat.getVmId()); + assertEquals(TIMESTAMP, (Long) stat.getTimeStamp()); + assertEquals(LOADED_CLASSES, (Long) stat.getLoadedClasses()); + assertEquals(VM_ID, (Integer) stat.getVmId()); } @Test public void testGetLatestClassStatsTwice() { - Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false); - chunk.put(Key.TIMESTAMP, 1234L); - chunk.put(Key.VM_ID, 321); - chunk.put(VmClassStatDAO.loadedClassesKey, 12345L); + Chunk chunk = getChunk(); Cursor cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); @@ -139,4 +137,30 @@ 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/VmCpuStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -48,6 +48,7 @@ import java.util.Collection; import java.util.List; +import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -59,6 +60,22 @@ 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()); @@ -73,12 +90,6 @@ @Test public void testGetLatestCpuStatsBasic() { - Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false); - chunk.put(Key.TIMESTAMP, 1234L); - chunk.put(Key.AGENT_ID, "test-agent-id"); - chunk.put(Key.VM_ID, 321); - chunk.put(VmCpuStatDAO.vmCpuLoadKey, 9.9); - Cursor cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(chunk); @@ -91,7 +102,7 @@ VmRef vmRef = mock(VmRef.class); when(vmRef.getAgent()).thenReturn(hostRef); - when(vmRef.getId()).thenReturn(321); + when(vmRef.getId()).thenReturn(VM_ID); VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage); @@ -103,20 +114,14 @@ assertEquals(1, vmCpuStats.size()); VmCpuStat stat = vmCpuStats.get(0); - assertEquals(1234L, stat.getTimeStamp()); - assertEquals(9.9, stat.getCpuLoad(), 0.001); - assertEquals(321, stat.getVmId()); + assertEquals(TIMESTAMP, (Long) stat.getTimeStamp()); + assertEquals(CPU_LOAD, stat.getCpuLoad(), 0.001); + assertEquals(VM_ID, (Integer) stat.getVmId()); } @Test public void testGetLatestCpuStatsTwice() { - Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false); - chunk.put(Key.AGENT_ID, "test-agent-id"); - chunk.put(Key.TIMESTAMP, 1234L); - chunk.put(Key.VM_ID, 321); - chunk.put(VmCpuStatDAO.vmCpuLoadKey, 9.9); - Cursor cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(chunk); @@ -140,4 +145,20 @@ 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/VmGcStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -60,6 +60,12 @@ 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()); @@ -76,12 +82,6 @@ @Test public void testGetLatestVmGcStatsBasic() { - 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); @@ -123,12 +123,6 @@ @Test public void testGetLatestVmGcStatsTwice() { - 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); @@ -158,4 +152,23 @@ 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/VmInfoDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -41,6 +41,7 @@ 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; @@ -52,6 +53,7 @@ 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; @@ -237,4 +239,50 @@ 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/VmMemoryStatDAOTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -43,7 +43,9 @@ 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; @@ -51,6 +53,8 @@ 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; @@ -164,4 +168,75 @@ 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/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -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 java.net.UnknownHostException; + +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; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@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 testConnectUnknownHostException() throws Exception { + PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new UnknownHostException()); + conn.connect(); + + verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT); + } + + @Test + public void testConnectMongoException() throws Exception { + PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenThrow(new MongoException("fluff")); + conn.connect(); + + verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT); + } +}
--- a/common/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -62,9 +62,12 @@ 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}) +@PrepareForTest({ DBCollection.class, DB.class, Mongo.class, MongoStorage.class, MongoConnection.class }) public class MongoStorageTest { private static final Key<String> key1 = new Key<>("key1", false); @@ -75,17 +78,29 @@ 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 storage; - private DB db; - private DBCollection testCollection, emptyTestCollection; + private MongoStorage makeStorage() throws Exception { + MongoStorage storage = new MongoStorage(conf); + storage.mapCategoryToDBCollection(testCategory, testCollection); + storage.mapCategoryToDBCollection(emptyTestCategory, emptyTestCollection); + return storage; + } @Before - public void setUp() { - storage = new MongoStorage(null); + public void setUp() throws Exception { + conf = mock(StartupConfiguration.class); + when(conf.getDBConnectionString()).thenReturn("mongodb://127.0.0.1:27518"); db = PowerMockito.mock(DB.class); - storage.connect(db); + 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"); @@ -110,39 +125,45 @@ when(testCollection.find()).thenReturn(cursor); when(testCollection.findOne(any(DBObject.class))).thenReturn(value1); when(testCollection.getCount()).thenReturn(2L); - storage.mapCategoryToDBCollection(testCategory, testCollection); emptyTestCollection = PowerMockito.mock(DBCollection.class); when(emptyTestCollection.getCount()).thenReturn(0L); - storage.mapCategoryToDBCollection(emptyTestCategory, emptyTestCollection); when(db.collectionExists(anyString())).thenReturn(false); when(db.createCollection(anyString(), any(DBObject.class))).thenReturn(testCollection); } @After public void tearDown() { - storage = null; + conf = null; + m = null; + db = null; testCollection = null; + emptyTestCollection = null; multiKeyQuery = null; } @Test - public void testCreateConnectionKey() { - MongoStorage mongoStorage = new MongoStorage(null); - mongoStorage.connect(db); + 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 = mongoStorage.createConnectionKey(category); + ConnectionKey connKey = storage.createConnectionKey(category); assertNotNull(connKey); } @Test - public void verifyFindAllReturnsCursor() { + 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() { + 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); @@ -150,22 +171,27 @@ } @Test - public void verifyFindAllCallsDBCollectionFind() { + 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() { + 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() { - + 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); @@ -180,8 +206,9 @@ } @Test - public void verifyFindCallsDBCollectionFindOneWithCorrectQuery() { - + 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); @@ -196,8 +223,9 @@ } @Test - public void verifyFindAllWithMultiKeys() { - + 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); @@ -208,8 +236,9 @@ } @Test - public void verifyFindWithMultiKeys() { - + 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); @@ -220,8 +249,9 @@ } @Test - public void verifyFindReturnsCorrectChunk() { - + 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. @@ -236,8 +266,9 @@ } @Test - public void verifyFindAllReturnsCorrectCursor() { - + 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. @@ -249,32 +280,43 @@ } @Test - public void verifyFindAllFromCategoryCallsDBCollectionFindAll() { + 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() { + 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() { + 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() { + 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() { + 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); }
--- a/common/src/test/java/com/redhat/thermostat/tools/BasicCommandTest.java Mon Apr 16 14:23:46 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/tools/BasicCommandTest.java Mon Apr 16 15:41:08 2012 +0200 @@ -36,9 +36,7 @@ package com.redhat.thermostat.tools; -import static org.junit.Assert.*; - -import java.util.List; +import static org.junit.Assert.assertNotNull; import org.junit.After; import org.junit.Before; @@ -46,7 +44,6 @@ import com.redhat.thermostat.cli.CommandContext; import com.redhat.thermostat.cli.CommandException; -import com.redhat.thermostat.common.config.InvalidConfigurationException; import com.redhat.thermostat.common.config.StartupConfiguration; public class BasicCommandTest {
--- a/distribution/config/agent.properties Mon Apr 16 14:23:46 2012 +0200 +++ b/distribution/config/agent.properties Mon Apr 16 15:41:08 2012 +0200 @@ -3,3 +3,7 @@ # specific backend configurations will be searched under the # $THERMOSTAT_HOME/backends/[backend_name.properties] BACKENDS=system + +# indicates if this agent will save its data to the database on exit +# or rather will purge the db +SAVE_ON_EXIT=false
--- a/tools/src/main/java/com/redhat/thermostat/tools/ThermostatService.java Mon Apr 16 14:23:46 2012 +0200 +++ b/tools/src/main/java/com/redhat/thermostat/tools/ThermostatService.java Mon Apr 16 15:41:08 2012 +0200 @@ -112,6 +112,16 @@ // we are only interested in starting the agent if // we started the database ourselves case START: + + // set a shutdown hook if the db was started by us + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + String[] args = new String[] { "storage", "--stop" }; + Thermostat.main(args); + } + }); + String dbUrl = database.getConfiguration().getDBConnectionString(); String[] args = new String[] { "--dbUrl", dbUrl }; try {