package ch.marcsladek.jrtnp.server;
import java.io.IOException;
import java.net.Socket;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import ch.marcsladek.jrtnp.connection.Connection;
import ch.marcsladek.jrtnp.connection.ConnectionFactory;
public class ClientManager {
protected final ConcurrentHashMap<String, Connection> clientMap;
protected final ConnectionFactory factory;
/**
* @param connectionFactoryClass
* class of the factory used to create objects of own Connection
* implementation
* @throws ReflectiveOperationException
* when unable to use reflection on given class
*/
protected ClientManager(Class<? extends ConnectionFactory> connectionFactoryClass)
throws ReflectiveOperationException {
clientMap = new ConcurrentHashMap<String, Connection>();
factory = connectionFactoryClass.getConstructor().newInstance();
}
/**
* Returns and starts a new Connection for the given Socket and adds it to the
* pool
*
* @param socket
* for establishing the connection to
* @return the new Conenction
* @throws IOException
* when unable to listen to socket
*/
public Connection newClient(Socket socket) {
try {
Connection newClient = factory.newInstance(socket);
if (clientMap.putIfAbsent(newClient.getIdentifier(), newClient) == null) {
newClient.start();
return newClient;
} else {
System.err.println("Connection '" + newClient + "' already exists");
return null;
}
} catch (IOException e) {
System.err.println("Connecting to '" + socket + "' failed: " + e.getMessage());
return null;
}
}
/**
* Removes the given Connection from the pool
*
* @param identifier
* specifies Connection
* @return whether was successful or not
*/
public boolean removeClient(String identifier) {
Connection client = clientMap.remove(identifier);
boolean success = false;
if (client != null) {
try {
client.shutdown();
success = true;
} catch (IOException e) {
}
}
return success;
}
/**
* Sends the Object to the Connection given connection
*
* @param identifier
* specifies Connection
* @param obj
* Object being sent
* @return whether was successful or not
* @throws IOException
* when unable to access socket
*/
public final boolean send(String identifier, Object obj) throws IOException {
Connection client = clientMap.get(identifier);
if (client != null) {
return client.send(obj);
} else {
return false;
}
}
/**
* @return a list of connected Clients
*/
public final Collection<String> list() {
return clientMap.keySet();
}
/**
* shuts down the connections to all clients
*/
public final void shutdown() {
for (Connection client : clientMap.values()) {
try {
client.shutdown();
} catch (IOException e) {
}
}
}
@Override
public String toString() {
return "ClientManager [connectionFactory=" + factory.getClass().getName()
+ ", clientMap=" + clientMap + "]";
}
}