/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.communication.configuration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.naming.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.configuration.ConfigurationSegment;
import de.rcenvironment.core.utils.common.StringUtils;
/**
* Class providing the configuration of the communication bundle. Additionally it defines the default configuration.
*
* @author Frank Kautz
* @author Doreen Seider
* @author Tobias Menden
* @author Robert Mischke
*/
public class CommunicationConfiguration {
/**
* The interval between connection health/liveliness checks.
*/
public static final int CONNECTION_HEALTH_CHECK_INTERVAL_MSEC = 20 * 1000;
/**
* Defines the maximum random delay ("jitter") that is waited before each individual connection health check. This randomness serves to
* avoid all connections being checked at once, and always in the same order. The interval for the random delay is [0;
* CONNECTION_HEALTH_CHECK_MAX_JITTER_MSEC]. The maximum value should be smaller than (CONNECTION_HEALTH_CHECK_INTERVAL_MSEC -
* CONNECTION_HEALTH_CHECK_TIMEOUT_MSEC) to avoid overlapping checks for the same connection.
*
*/
public static final int CONNECTION_HEALTH_CHECK_MAX_JITTER_MSEC = 7 * 1000;
/**
* The maximum response time for an individual connection health check.
*/
public static final int CONNECTION_HEALTH_CHECK_TIMEOUT_MSEC = 10 * 1000;
/**
* The number of consecutive health check failures before a connection is considered "broken".
*/
public static final int CONNECTION_HEALTH_CHECK_FAILURE_LIMIT = 3;
/**
* Default request/response timeout on the sender side.
*/
public static final int DEFAULT_REQUEST_TIMEOUT_MSEC = 40000;
/**
* Default timeout for waiting for the response while forwarding.
*/
public static final int DEFAULT_FORWARDING_TIMEOUT_MSEC = 35000;
private static final int MAX_VALID_PORT = 65535;
private static final String COMMA = ",";
private List<String> providedContactPoints = new ArrayList<String>();
private List<String> remoteContactPoints = new ArrayList<String>();
private int requestTimeoutMsec = DEFAULT_REQUEST_TIMEOUT_MSEC;
private int forwardingTimeoutMsec = DEFAULT_FORWARDING_TIMEOUT_MSEC;
private final Log log = LogFactory.getLog(getClass());
/**
* Default constructor for bean mapping and tests.
*/
public CommunicationConfiguration() {}
public CommunicationConfiguration(ConfigurationSegment configuration) {
requestTimeoutMsec = configuration.getLong("requestTimeoutMsec", (long) DEFAULT_REQUEST_TIMEOUT_MSEC).intValue();
forwardingTimeoutMsec = configuration.getLong("forwardingTimeoutMsec", (long) DEFAULT_FORWARDING_TIMEOUT_MSEC).intValue();
Map<String, ConfigurationSegment> connectionElements = configuration.listElements("connections");
if (connectionElements != null) {
for (Entry<String, ConfigurationSegment> entry : connectionElements.entrySet()) {
ConfigurationSegment configPart = entry.getValue();
String connection;
try {
connection = parseConnectionEntry(configPart);
remoteContactPoints.add(connection);
} catch (ConfigurationException e) {
// TODO >6.0.0: change to throw exception to outside?
log.error("Error in network connection entry \"" + entry.getKey() + "\": " + e.getMessage());
}
}
}
Map<String, ConfigurationSegment> serverPortElements = configuration.listElements("serverPorts");
if (serverPortElements != null) {
for (Entry<String, ConfigurationSegment> entry : serverPortElements.entrySet()) {
ConfigurationSegment configPart = entry.getValue();
String serverPort;
try {
serverPort = parseServerPortEntry(configPart);
providedContactPoints.add(serverPort);
} catch (ConfigurationException e) {
// TODO >6.0.0: change to throw exception to outside?
log.error("Error in server port entry " + entry.getKey() + ": " + e.getMessage());
}
}
}
}
private String parseConnectionEntry(ConfigurationSegment connectionPart) throws ConfigurationException {
// TODO mapping to old string approach to reduce code changes; improve later
String host = connectionPart.getString("host");
if (host == null) {
throw new ConfigurationException("Missing required parameter \"host\"");
}
final Long portString = connectionPart.getLong("port");
if (portString == null) {
throw new ConfigurationException("Missing required parameter \"port\"");
}
int port = portString.intValue();
StringBuilder options = new StringBuilder();
Long autoRetryInitialDelay = connectionPart.getLong("autoRetryInitialDelay");
if (autoRetryInitialDelay != null) {
options.append("autoRetryInitialDelay=");
options.append(autoRetryInitialDelay);
options.append(COMMA);
}
Long autoRetryMaximumDelay = connectionPart.getLong("autoRetryMaximumDelay");
if (autoRetryMaximumDelay != null) {
options.append("autoRetryMaximumDelay=");
options.append(autoRetryMaximumDelay);
options.append(COMMA);
}
Double autoRetryDelayMultiplier = connectionPart.getDouble("autoRetryDelayMultiplier");
if (autoRetryDelayMultiplier != null) {
options.append("autoRetryDelayMultiplier=");
options.append(autoRetryDelayMultiplier);
options.append(COMMA);
}
boolean connectOnStartup = connectionPart.getBoolean("connectOnStartup", true);
options.append("connectOnStartup=");
options.append(Boolean.toString(connectOnStartup));
options.append(COMMA);
if (options.length() != 0) {
options.setLength(options.length() - 1);
}
String connection = StringUtils.format("activemq-tcp:%s:%d(%s)", host, port, options.toString());
return connection;
}
private String parseServerPortEntry(ConfigurationSegment connectionPart) throws ConfigurationException {
// TODO mapping to old string approach to reduce code changes; improve later
String ip = connectionPart.getString("ip");
if (ip == null || ip.trim().isEmpty()) {
throw new ConfigurationException("Missing or invalid \"ip\" parameter");
}
Long port = connectionPart.getLong("port");
if (port == null || port < 1 || port > MAX_VALID_PORT) {
throw new ConfigurationException("Missing or invalid \"port\" parameter");
}
return StringUtils.format("activemq-tcp:%s:%d", ip, port.intValue());
}
public List<String> getProvidedContactPoints() {
return providedContactPoints;
}
public void setProvidedContactPoints(List<String> providedContactPoints) {
this.providedContactPoints = providedContactPoints;
}
public List<String> getRemoteContactPoints() {
return remoteContactPoints;
}
public void setRemoteContactPoints(List<String> remoteContactPoints) {
this.remoteContactPoints = remoteContactPoints;
}
public int getRequestTimeoutMsec() {
return requestTimeoutMsec;
}
public void setRequestTimeoutMsec(int requestTimeoutMsec) {
this.requestTimeoutMsec = requestTimeoutMsec;
}
public int getForwardingTimeoutMsec() {
return forwardingTimeoutMsec;
}
public void setForwardingTimeoutMsec(int forwardingTimeoutMsec) {
this.forwardingTimeoutMsec = forwardingTimeoutMsec;
}
}