Mercurial > hg > release > thermostat-0.13
changeset 218:6fb6e9890e67
Make agent and client connect in same way.
reviewed-by: neugens
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-April/000758.html
line wrap: on
line diff
--- a/agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java Wed Apr 11 19:42:15 2012 +0200 +++ b/agent/src/main/java/com/redhat/thermostat/agent/AgentApplication.java Thu Apr 12 10:37:36 2012 -0400 @@ -51,13 +51,18 @@ 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.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.Storage; +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; @@ -96,21 +101,43 @@ } 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; + Storage storage = daoFactory.getStorage(); try { backendRegistry = new BackendRegistry(configuration, storage); } catch (BackendLoadException ble) {
--- a/client/src/main/java/com/redhat/thermostat/client/Main.java Wed Apr 11 19:42:15 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/Main.java Thu Apr 12 10:37:36 2012 -0400 @@ -56,13 +56,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 { @@ -82,7 +82,7 @@ StartupConfiguration config = new ConnectionConfiguration(); - ConnectionProvider connProv = new MongoConnectionProvider(config); + StorageProvider connProv = new MongoStorageProvider(config); DAOFactory daoFactory = new MongoDAOFactory(connProv); ApplicationContext.getInstance().setDAOFactory(daoFactory); TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
--- a/client/src/main/java/com/redhat/thermostat/client/ui/ConnectionSelectionDialog.java Wed Apr 11 19:42:15 2012 +0200 +++ b/client/src/main/java/com/redhat/thermostat/client/ui/ConnectionSelectionDialog.java Thu Apr 12 10:37:36 2012 -0400 @@ -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/common/src/main/java/com/redhat/thermostat/common/dao/Connection.java Wed Apr 11 19:42:15 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 Wed Apr 11 19:42:15 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/DAOFactory.java Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Thu Apr 12 10:37:36 2012 -0400 @@ -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/MongoConnection.java Wed Apr 11 19:42:15 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 Wed Apr 11 19:42:15 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 Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java Thu Apr 12 10:37:36 2012 -0400 @@ -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"); + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/Connection.java Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,133 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.storage; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public abstract class Connection { + + public enum ConnectionType { + LOCAL(false), + REMOTE(true), + CLUSTER(true), + ; + + boolean isDisplayable = false; + boolean needsUrl = false; + + private ConnectionType(boolean needsUrl) { + this.needsUrl = needsUrl; + } + + private ConnectionType(boolean isDisplayable, boolean needsUrl) { + this.isDisplayable = isDisplayable; + } + + public boolean isDisplayable() { + return isDisplayable; + } + + public boolean needsUrl() { + return needsUrl; + } + } + + public enum ConnectionStatus { + CONNECTED, + CONNECTING, + FAILED_TO_CONNECT, + DISCONNECTED, + } + + public interface ConnectionListener { + public void changed(ConnectionStatus newStatus); + } + + protected boolean connected = false; + + private ConnectionType type; + private String url; + + private List<Connection.ConnectionListener> listeners = new CopyOnWriteArrayList<>(); + + public void setType(ConnectionType type) { + this.type = type; + } + + public ConnectionType getType() { + return type; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUrl() { + return url; + } + + @Override + public String toString() { + if (url == null) { + return type.toString(); + } + return type.toString() + " to " + url; + } + + public abstract void connect(); + + public abstract void disconnect(); + + public boolean isConnected() { + return connected; + } + + public void addListener(ConnectionListener listener) { + this.listeners.add(listener); + } + + public void removeListener(ConnectionListener listener) { + this.listeners.remove(listener); + } + + protected void fireChanged(ConnectionStatus status) { + for (ConnectionListener listener: listeners) { + listener.changed(status); + } + } +}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/ConnectionFailedException.java Wed Apr 11 19:42:15 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 Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,105 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.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 Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Thu Apr 12 10:37:36 2012 -0400 @@ -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()); } @@ -346,4 +321,34 @@ } 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 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 Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,54 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.storage; + +import com.redhat.thermostat.common.config.StartupConfiguration; + +public class MongoStorageProvider implements StorageProvider { + + private StartupConfiguration configuration; + + public MongoStorageProvider(StartupConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public Storage createStorage() { + return new MongoStorage(configuration); + } + +}
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Storage.java Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/Storage.java Thu Apr 12 10:37:36 2012 -0400 @@ -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,6 +51,8 @@ category.setConnectionKey(connKey); } + public abstract Connection getConnection(); + public abstract ConnectionKey createConnectionKey(Category category); public abstract void putChunk(Chunk chunk); @@ -86,4 +70,15 @@ 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(); + + /** + * @return {@code null} if the value is invalid or missing + */ + public abstract String getBackendConfig(String backendName, String configurationKey); + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/common/storage/StorageProvider.java Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,42 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.storage; + +public interface StorageProvider { + + Storage createStorage(); +}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/ConnectionTest.java Wed Apr 11 19:42:15 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/MongoConnectionTest.java Wed Apr 11 19:42:15 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 Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Thu Apr 12 10:37:36 2012 -0400 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/test/java/com/redhat/thermostat/common/storage/ConnectionTest.java Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.storage; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.storage.Connection; +import com.redhat.thermostat.common.storage.Connection.ConnectionStatus; + +public class ConnectionTest { + + private Connection connection; + + private Connection.ConnectionListener listener1; + private Connection.ConnectionListener listener2; + + @Before + public void setUp() { + + connection = new Connection() { + + @Override + public void disconnect() { + // TODO Auto-generated method stub + + } + + @Override + public void connect() { + // TODO Auto-generated method stub + + } + }; + listener1 = mock(Connection.ConnectionListener.class); + listener2 = mock(Connection.ConnectionListener.class); + connection.addListener(listener1); + connection.addListener(listener2); + } + + @After + public void tearDown() { + connection = null; + listener1 = null; + listener2 = null; + } + + @Test + public void testListenersConnecting() throws Exception { + verifyListenersStatus(ConnectionStatus.CONNECTING); + } + + @Test + public void testListenersConnected() throws Exception { + verifyListenersStatus(ConnectionStatus.CONNECTED); + } + + @Test + public void testListenersFailedToConnect() throws Exception { + verifyListenersStatus(ConnectionStatus.FAILED_TO_CONNECT); + } + + @Test + public void testListenersDisconnected() throws Exception { + verifyListenersStatus(ConnectionStatus.DISCONNECTED); + } + + private void verifyListenersStatus(ConnectionStatus status) { + connection.fireChanged(status); + verify(listener1).changed(status); + verify(listener2).changed(status); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/test/java/com/redhat/thermostat/common/storage/MongoConnectionTest.java Thu Apr 12 10:37:36 2012 -0400 @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.common.storage; + +import 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 Wed Apr 11 19:42:15 2012 +0200 +++ b/common/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Thu Apr 12 10:37:36 2012 -0400 @@ -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); }