package ibis.ipl.support;
import ibis.ipl.IbisConfigurationException;
import ibis.ipl.IbisProperties;
import ibis.ipl.server.ServerProperties;
import ibis.smartsockets.SmartSocketsProperties;
import ibis.smartsockets.direct.DirectSocketAddress;
import ibis.smartsockets.virtual.InitializationException;
import ibis.smartsockets.virtual.VirtualSocketAddress;
import ibis.smartsockets.virtual.VirtualSocketFactory;
import ibis.util.TypedProperties;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Convenience class to create a VirtualSocketFactory, and get the address of
* the server.
*/
public class Client {
private static final Logger logger = LoggerFactory.getLogger(Client.class);
private static DirectSocketAddress createServerAddress(String serverString,
int defaultPort) throws IbisConfigurationException {
if (serverString == null) {
throw new IbisConfigurationException("serverString undefined");
}
// maybe it is a DirectSocketAddress?
try {
return DirectSocketAddress.getByAddress(serverString);
} catch (Throwable e) {
// IGNORE
}
Throwable throwable = null;
// or only a host address
try {
return DirectSocketAddress.getByAddress(serverString, defaultPort);
} catch (Throwable e) {
throwable = e;
// IGNORE
}
throw new IbisConfigurationException(
"could not create server address from given string: "
+ serverString, throwable);
}
private static Map<String, Client> clients = new HashMap<String, Client>();
/**
* Returns a named client. Creates one if needed.
*
* @param name
* name of the client
* @param properties
* properties used when client is created
* @param port
* local port to bound client to used when client is created (0
* for any free port)
* @return the client with the specified name
* @throws IbisConfigurationException
* if the client cannot be created due to invalid settings
* @throws IOException
* if the client cannot be created due to a SmartSockets error
*/
public static synchronized Client getOrCreateClient(String name,
Properties properties, int port) throws IbisConfigurationException,
IOException {
Client result = clients.get(name);
if (result == null) {
result = new Client(properties, port);
clients.put(name, result);
}
return result;
}
private final DirectSocketAddress serverMachine;
private final VirtualSocketFactory factory;
private Client(Properties properties, int port)
throws IbisConfigurationException, IOException {
TypedProperties typedProperties = ServerProperties
.getHardcodedProperties();
typedProperties.addProperties(properties);
String serverAddressString = typedProperties
.getProperty(IbisProperties.SERVER_ADDRESS);
if (serverAddressString == null || serverAddressString.equals("")) {
serverMachine = null;
} else {
serverMachine = createServerAddress(serverAddressString,
typedProperties.getIntProperty(ServerProperties.PORT,
ServerProperties.DEFAULT_PORT));
}
String hubs = typedProperties.getProperty(IbisProperties.HUB_ADDRESSES);
// did the server also start a hub?
boolean serverIsHub = typedProperties
.getBooleanProperty(IbisProperties.SERVER_IS_HUB);
if (serverMachine != null && serverIsHub) {
// add server to hub addresses
if (hubs == null || hubs.equals("")) {
hubs = serverMachine.toString();
} else {
hubs = hubs + "," + serverMachine.toString();
}
}
Properties smartProperties = new Properties();
if (port > 0) {
smartProperties.put(SmartSocketsProperties.PORT_RANGE, Integer
.toString(port));
}
if (hubs != null) {
smartProperties.put(SmartSocketsProperties.HUB_ADDRESSES, hubs);
}
try {
factory = VirtualSocketFactory.createSocketFactory(smartProperties,
true);
} catch (InitializationException e) {
throw new IOException(e.getMessage());
}
logger.debug("client factory running on " + factory.getLocalHost());
}
public VirtualSocketFactory getFactory() {
return factory;
}
/**
* Get the address of a service running on a given port.
*
* @param port
* the port the service is running on
* @throws IbisConfigurationException
* if the server address is unknown.
*/
public VirtualSocketAddress getServiceAddress(int port)
throws IbisConfigurationException {
if (serverMachine == null) {
throw new IbisConfigurationException(
"cannot get address of server, server address property \""
+ IbisProperties.SERVER_ADDRESS + "\" undefined");
}
return new VirtualSocketAddress(serverMachine, port, serverMachine,
null);
}
}