Ticket #269: Add ConnectionService, get rid of ProviderService.

This commit is contained in:
Michael Jumper
2013-02-28 00:24:28 -08:00
parent b67a074c4b
commit bc41becdf3
5 changed files with 154 additions and 110 deletions

View File

@@ -50,8 +50,8 @@ import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey;
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
import net.sourceforge.guacamole.net.auth.mysql.service.ProviderService;
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration; import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
import org.mybatis.guice.transactional.Transactional; import org.mybatis.guice.transactional.Transactional;
@@ -75,10 +75,10 @@ public class ConnectionDirectory implements Directory<String, Connection>{
private PermissionCheckService permissionCheckService; private PermissionCheckService permissionCheckService;
/** /**
* Service for creating and retrieving objects. * Service managing connections.
*/ */
@Inject @Inject
private ProviderService providerService; private ConnectionService connectionService;
/** /**
* Service for manipulating connections in the database. * Service for manipulating connections in the database.
@@ -111,7 +111,7 @@ public class ConnectionDirectory implements Directory<String, Connection>{
@Override @Override
public Connection get(String identifier) throws GuacamoleException { public Connection get(String identifier) throws GuacamoleException {
permissionCheckService.verifyConnectionReadAccess(this.user_id, identifier); permissionCheckService.verifyConnectionReadAccess(this.user_id, identifier);
return providerService.getExistingMySQLConnection(identifier); return connectionService.retrieveConnection(identifier);
} }
@Transactional @Transactional
@@ -236,7 +236,9 @@ public class ConnectionDirectory implements Directory<String, Connection>{
// Verify permission to delete // Verify permission to delete
permissionCheckService.verifyConnectionDeleteAccess(this.user_id, identifier); permissionCheckService.verifyConnectionDeleteAccess(this.user_id, identifier);
MySQLConnection mySQLConnection = providerService.getExistingMySQLConnection(identifier); // Get connection
MySQLConnection mySQLConnection =
connectionService.retrieveConnection(identifier);
// Delete all configuration values // Delete all configuration values
ConnectionParameterExample connectionParameterExample = new ConnectionParameterExample(); ConnectionParameterExample connectionParameterExample = new ConnectionParameterExample();

View File

@@ -55,9 +55,9 @@ import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties; import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService; import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService;
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService; import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
import net.sourceforge.guacamole.net.auth.mysql.service.ProviderService;
import net.sourceforge.guacamole.net.auth.mysql.service.SaltService; import net.sourceforge.guacamole.net.auth.mysql.service.SaltService;
import net.sourceforge.guacamole.net.auth.mysql.service.SecureRandomSaltService; import net.sourceforge.guacamole.net.auth.mysql.service.SecureRandomSaltService;
import net.sourceforge.guacamole.net.auth.mysql.service.Sha256PasswordEncryptionService; import net.sourceforge.guacamole.net.auth.mysql.service.Sha256PasswordEncryptionService;
@@ -164,7 +164,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
bind(SaltService.class).to(SecureRandomSaltService.class); bind(SaltService.class).to(SecureRandomSaltService.class);
bind(PasswordEncryptionService.class).to(Sha256PasswordEncryptionService.class); bind(PasswordEncryptionService.class).to(Sha256PasswordEncryptionService.class);
bind(PermissionCheckService.class); bind(PermissionCheckService.class);
bind(ProviderService.class); bind(ConnectionService.class);
bind(UserService.class); bind(UserService.class);
bind(ActiveConnectionSet.class).toInstance(activeConnectionSet); bind(ActiveConnectionSet.class).toInstance(activeConnectionSet);

View File

@@ -1,3 +1,6 @@
package net.sourceforge.guacamole.net.auth.mysql;
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@@ -33,7 +36,6 @@
* the terms of any one of the MPL, the GPL or the LGPL. * the terms of any one of the MPL, the GPL or the LGPL.
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
package net.sourceforge.guacamole.net.auth.mysql;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,14 +43,10 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSocket; import net.sourceforge.guacamole.net.GuacamoleSocket;
import net.sourceforge.guacamole.net.InetGuacamoleSocket;
import net.sourceforge.guacamole.net.auth.AbstractConnection; import net.sourceforge.guacamole.net.auth.AbstractConnection;
import net.sourceforge.guacamole.net.auth.Connection; import net.sourceforge.guacamole.net.auth.Connection;
import net.sourceforge.guacamole.net.auth.ConnectionRecord; import net.sourceforge.guacamole.net.auth.ConnectionRecord;
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties; import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
import net.sourceforge.guacamole.net.auth.mysql.service.ProviderService;
import net.sourceforge.guacamole.properties.GuacamoleProperties;
import net.sourceforge.guacamole.protocol.ConfiguredGuacamoleSocket;
import net.sourceforge.guacamole.protocol.GuacamoleClientInformation; import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration; import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
@@ -69,10 +67,10 @@ public class MySQLConnection extends AbstractConnection {
private List<ConnectionRecord> history = new ArrayList<ConnectionRecord>(); private List<ConnectionRecord> history = new ArrayList<ConnectionRecord>();
/** /**
* Service for creating and retrieving objects. * Service for managing connections.
*/ */
@Inject @Inject
private ProviderService providerService; private ConnectionService connectionService;
/** /**
* Set of all currently active connections. * Set of all currently active connections.
@@ -135,29 +133,7 @@ public class MySQLConnection extends AbstractConnection {
@Override @Override
public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException { public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
return connectionService.connect(this, info);
// If the current connection is active, and multiple simultaneous connections are not allowed.
if(GuacamoleProperties.getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false)
&& activeConnectionSet.contains(getConnectionID()))
throw new GuacamoleException("Cannot connect. This connection is in use.");
// Get guacd connection information
String host = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_HOSTNAME);
int port = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_PORT);
// Get socket
GuacamoleSocket socket = providerService.getMySQLGuacamoleSocket(
new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(host, port),
getConfiguration()
),
getConnectionID()
);
// Mark this connection as active
activeConnectionSet.add(getConnectionID());
return socket;
} }
@Override @Override

View File

@@ -43,7 +43,7 @@ import net.sourceforge.guacamole.net.auth.Connection;
import net.sourceforge.guacamole.net.auth.ConnectionRecord; import net.sourceforge.guacamole.net.auth.ConnectionRecord;
import net.sourceforge.guacamole.net.auth.User; import net.sourceforge.guacamole.net.auth.User;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory;
import net.sourceforge.guacamole.net.auth.mysql.service.ProviderService; import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
import net.sourceforge.guacamole.net.auth.mysql.service.UserService; import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
/** /**
@@ -65,10 +65,10 @@ public class MySQLConnectionRecord implements ConnectionRecord {
private UserService userService; private UserService userService;
/** /**
* Service for creating and retrieving objects. * Service for accessing connections.
*/ */
@Inject @Inject
private ProviderService providerService; private ConnectionService connectionService;
/** /**
* Initialize this MySQLConnectionRecord with the database record it * Initialize this MySQLConnectionRecord with the database record it
@@ -100,7 +100,7 @@ public class MySQLConnectionRecord implements ConnectionRecord {
@Override @Override
public Connection getConnection() { public Connection getConnection() {
return providerService.getExistingMySQLConnection(connectionHistory.getConnection_id()); return connectionService.retrieveConnection(connectionHistory.getConnection_id());
} }
@Override @Override

View File

@@ -1,3 +1,6 @@
package net.sourceforge.guacamole.net.auth.mysql.service;
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@@ -33,7 +36,6 @@
* the terms of any one of the MPL, the GPL or the LGPL. * the terms of any one of the MPL, the GPL or the LGPL.
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
package net.sourceforge.guacamole.net.auth.mysql.service;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -41,84 +43,135 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.auth.Connection; import net.sourceforge.guacamole.net.GuacamoleSocket;
import net.sourceforge.guacamole.net.InetGuacamoleSocket;
import net.sourceforge.guacamole.net.auth.mysql.ActiveConnectionSet;
import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection; import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection;
import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionRecord; import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionRecord;
import net.sourceforge.guacamole.net.auth.mysql.MySQLGuacamoleSocket; import net.sourceforge.guacamole.net.auth.mysql.MySQLGuacamoleSocket;
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
import net.sourceforge.guacamole.net.auth.mysql.model.Connection;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionExample; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionExample;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistoryExample; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistoryExample;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter;
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample; import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample;
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
import net.sourceforge.guacamole.properties.GuacamoleProperties;
import net.sourceforge.guacamole.protocol.ConfiguredGuacamoleSocket; import net.sourceforge.guacamole.protocol.ConfiguredGuacamoleSocket;
import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration; import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
/** /**
* Provides convenient provider methods for MySQL specific implementations. * Service which provides convenience methods for creating, retrieving, and
* @author James Muehlner * manipulating connections.
*
* @author Michael Jumper, James Muehlner
*/ */
public class ProviderService { public class ConnectionService {
/**
* DAO for accessing connections.
*/
@Inject @Inject
private ConnectionMapper connectionDAO; private ConnectionMapper connectionDAO;
/**
* DAO for accessing connection parameters.
*/
@Inject @Inject
private ConnectionParameterMapper connectionParameterDAO; private ConnectionParameterMapper connectionParameterDAO;
/**
* DAO for accessing connection history.
*/
@Inject @Inject
private ConnectionHistoryMapper connectionHistoryDAO; private ConnectionHistoryMapper connectionHistoryDAO;
/**
* Provider which creates MySQLConnections.
*/
@Inject @Inject
private Provider<MySQLConnection> mySQLConnectionProvider; private Provider<MySQLConnection> mySQLConnectionProvider;
/**
* Provider which creates MySQLConnectionRecords.
*/
@Inject @Inject
private Provider<MySQLConnectionRecord> mySQLConnectionRecordProvider; private Provider<MySQLConnectionRecord> mySQLConnectionRecordProvider;
/**
* Provider which creates MySQLGuacamoleSockets.
*/
@Inject @Inject
private Provider<MySQLGuacamoleSocket> mySQLGuacamoleSocketProvider; private Provider<MySQLGuacamoleSocket> mySQLGuacamoleSocketProvider;
/** /**
* Get the connection based on the connection name of the provided object. * Set of all currently active connections.
* @param connection
* @return the new Connection object.
* @throws GuacamoleException
*/ */
public MySQLConnection getExistingMySQLConnection(Connection connection) throws GuacamoleException { @Inject
return getExistingMySQLConnection(connection.getIdentifier()); private ActiveConnectionSet activeConnectionSet;
}
/** /**
* Get the connection based on the connection name of the provided object. * Retrieves the connection having the given name from the database.
* @param name *
* @return the new Connection object. * @param name The name of the connection to return.
* @throws GuacamoleException * @return The connection having the given name, or null if no such
* connection could be found.
*/ */
public MySQLConnection getExistingMySQLConnection(String name) throws GuacamoleException { public MySQLConnection retrieveConnection(String name) {
// Query connection by ID // Query connection by connection identifier (name)
ConnectionExample example = new ConnectionExample(); ConnectionExample example = new ConnectionExample();
example.createCriteria().andConnection_nameEqualTo(name); example.createCriteria().andConnection_nameEqualTo(name);
List<net.sourceforge.guacamole.net.auth.mysql.model.Connection> connections = List<Connection> connections =
connectionDAO.selectByExample(example); connectionDAO.selectByExample(example);
// If no connection found, return null // If no connection found, return null
if(connections.isEmpty()) if(connections.isEmpty())
return null; return null;
// Assert only one connection found
assert connections.size() == 1 : "Multiple connections with same name.";
// Otherwise, return found connection // Otherwise, return found connection
return getExistingMySQLConnection(connections.get(0)); return toMySQLConnection(connections.get(0));
} }
/** /**
* Get an existing MySQLConnection from a connection database record. * Retrieves the connection having the given ID from the database.
* @param connection *
* @return the existing MySQLConnection object. * @param id The ID of the connection to retrieve.
* @return The connection having the given ID, or null if no such
* connection was found.
*/ */
public MySQLConnection getExistingMySQLConnection(net.sourceforge.guacamole.net.auth.mysql.model.Connection connection) { public MySQLConnection retrieveConnection(int id) {
// Query connection by ID
Connection connection = connectionDAO.selectByPrimaryKey(id);
// If no connection found, return null
if(connection == null)
return null;
// Otherwise, return found connection
return toMySQLConnection(connection);
}
/**
* Convert the given database-retrieved Connection into a MySQLConnection.
* The parameters of the given connection will be read and added to the
* MySQLConnection in the process.
*
* @param connection The connection to convert.
* @return A new MySQLConnection containing all data associated with the
* specified connection.
*/
private MySQLConnection toMySQLConnection(Connection connection) {
// Build configuration // Build configuration
GuacamoleConfiguration config = new GuacamoleConfiguration(); GuacamoleConfiguration config = new GuacamoleConfiguration();
@@ -151,64 +204,77 @@ public class ProviderService {
} }
/** /**
* Get an existing MySQLConnection from a connection ID. * Retrieves the history of the connection having the given ID.
* @param id *
* @return the existing MySQLConnection object if found, null if not. * @param connectionID The ID of the connection to retrieve the history of.
* @return A list of MySQLConnectionRecord documenting the history of this
* connection.
*/ */
public MySQLConnection getExistingMySQLConnection(Integer id) { public List<MySQLConnectionRecord> retrieveHistory(int connectionID) {
// Query connection by ID // Retrieve history records relating to given connection ID
net.sourceforge.guacamole.net.auth.mysql.model.Connection connection =
connectionDAO.selectByPrimaryKey(id);
// If no connection found, return null
if(connection == null)
return null;
// Otherwise, return found connection
return getExistingMySQLConnection(connection);
}
/**
* Gets a list of existing MySQLConnectionRecord from the database. These represent
* the history records of the connection.
* @param connectionID
* @return the list of MySQLConnectionRecord related to this connectionID.
*/
public List<MySQLConnectionRecord> getExistingMySQLConnectionRecords(Integer connectionID) {
ConnectionHistoryExample example = new ConnectionHistoryExample(); ConnectionHistoryExample example = new ConnectionHistoryExample();
example.createCriteria().andConnection_idEqualTo(connectionID); example.createCriteria().andConnection_idEqualTo(connectionID);
// we want to return the newest records first
// We want to return the newest records first
example.setOrderByClause("start_date DESC"); example.setOrderByClause("start_date DESC");
// Retrieve all connection history entries
List<ConnectionHistory> connectionHistories = connectionHistoryDAO.selectByExample(example); List<ConnectionHistory> connectionHistories = connectionHistoryDAO.selectByExample(example);
// Convert history entries to connection records
List<MySQLConnectionRecord> connectionRecords = new ArrayList<MySQLConnectionRecord>(); List<MySQLConnectionRecord> connectionRecords = new ArrayList<MySQLConnectionRecord>();
for(ConnectionHistory history : connectionHistories) { for(ConnectionHistory history : connectionHistories) {
connectionRecords.add(getExistingMySQLConnectionRecord(history));
// Create connection record from history
MySQLConnectionRecord record = mySQLConnectionRecordProvider.get();
record.init(history);
connectionRecords.add(record);
} }
return connectionRecords; return connectionRecords;
} }
/** /**
* Create a MySQLConnectionRecord object around a single ConnectionHistory database record. * Create a MySQLGuacamoleSocket using the provided connection.
* @param history *
* @return the new MySQLConnectionRecord object. * @param connection The connection to use when connecting the socket.
* @param info The information to use when performing the connection
* handshake.
* @return The connected socket.
* @throws GuacamoleException If an error occurs while connecting the
* socket.
*/ */
public MySQLConnectionRecord getExistingMySQLConnectionRecord(ConnectionHistory history) { public MySQLGuacamoleSocket connect(MySQLConnection connection,
MySQLConnectionRecord record = mySQLConnectionRecordProvider.get(); GuacamoleClientInformation info)
record.init(history); throws GuacamoleException {
return record;
// If the given connection is active, and multiple simultaneous
// connections are not allowed, disallow connection
if(GuacamoleProperties.getProperty(
MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false)
&& activeConnectionSet.contains(connection.getConnectionID()))
throw new GuacamoleException("Cannot connect. This connection is in use.");
// Get guacd connection information
String host = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_HOSTNAME);
int port = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_PORT);
// Get socket
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(host, port),
connection.getConfiguration(), info
);
// Mark this connection as active
activeConnectionSet.add(connection.getConnectionID());
// Return new MySQLGuacamoleSocket
MySQLGuacamoleSocket mySQLGuacamoleSocket = mySQLGuacamoleSocketProvider.get();
mySQLGuacamoleSocket.init(socket, connection.getConnectionID());
return mySQLGuacamoleSocket;
} }
/**
* Create a MySQLGuacamoleSocket using the provided ConfiguredGuacamoleSocket and connection ID.
* @param socket
* @param connectionID
* @return
*/
public MySQLGuacamoleSocket getMySQLGuacamoleSocket(ConfiguredGuacamoleSocket socket, int connectionID) {
MySQLGuacamoleSocket mySQLGuacamoleSocket = mySQLGuacamoleSocketProvider.get();
mySQLGuacamoleSocket.init(socket, connectionID);
return mySQLGuacamoleSocket;
}
} }