SGF-433 - Fix improper resolution of Spring property placeholders in 'locators' and 'servers' attributes on the '<gfe:pool>' element(s) in Spring XML config.
This commit is contained in:
@@ -28,7 +28,9 @@ import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.util.DistributedSystemUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -36,7 +38,6 @@ import com.gemstone.gemfire.cache.client.Pool;
|
||||
import com.gemstone.gemfire.cache.client.PoolFactory;
|
||||
import com.gemstone.gemfire.cache.client.PoolManager;
|
||||
import com.gemstone.gemfire.distributed.DistributedSystem;
|
||||
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
|
||||
|
||||
/**
|
||||
* FactoryBean for easy declaration and configuration of a GemFire Pool. If a new Pool is created,
|
||||
@@ -47,13 +48,26 @@ import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.BeanFactoryAware
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpointList
|
||||
* @see com.gemstone.gemfire.cache.client.Pool
|
||||
* @see com.gemstone.gemfire.cache.client.PoolFactory
|
||||
* @see com.gemstone.gemfire.cache.client.PoolManager
|
||||
* @see com.gemstone.gemfire.distributed.DistributedSystem
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, DisposableBean, BeanNameAware,
|
||||
BeanFactoryAware {
|
||||
public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, DisposableBean,
|
||||
BeanNameAware, BeanFactoryAware {
|
||||
|
||||
protected static final int DEFAULT_LOCATOR_PORT = DistributedSystemUtils.DEFAULT_LOCATOR_PORT;
|
||||
protected static final int DEFAULT_SERVER_PORT = DistributedSystemUtils.DEFAULT_CACHE_SERVER_PORT;
|
||||
|
||||
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
|
||||
|
||||
@@ -62,8 +76,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Collection<InetSocketAddress> locators;
|
||||
private Collection<InetSocketAddress> servers;
|
||||
private ConnectionEndpointList locators = new ConnectionEndpointList();
|
||||
private ConnectionEndpointList servers = new ConnectionEndpointList();
|
||||
|
||||
private Pool pool;
|
||||
|
||||
@@ -128,7 +142,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
log.debug(String.format("No Pool with name '%1$s' was found. Creating a new Pool...", name));
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(locators) && CollectionUtils.isEmpty(servers)) {
|
||||
if (locators.isEmpty() && servers.isEmpty()) {
|
||||
throw new IllegalArgumentException("at least one GemFire Locator or Server is required");
|
||||
}
|
||||
|
||||
@@ -155,12 +169,12 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
poolFactory.setSubscriptionRedundancy(subscriptionRedundancy);
|
||||
poolFactory.setThreadLocalConnections(threadLocalConnections);
|
||||
|
||||
for (InetSocketAddress connection : CollectionUtils.nullSafeCollection(locators)) {
|
||||
poolFactory.addLocator(connection.getHostName(), connection.getPort());
|
||||
for (ConnectionEndpoint locator : locators) {
|
||||
poolFactory.addLocator(locator.getHost(), locator.getPort());
|
||||
}
|
||||
|
||||
for (InetSocketAddress connection : CollectionUtils.nullSafeCollection(servers)) {
|
||||
poolFactory.addServer(connection.getHostName(), connection.getPort());
|
||||
for (ConnectionEndpoint server : servers) {
|
||||
poolFactory.addServer(server.getHost(), server.getPort());
|
||||
}
|
||||
|
||||
// eagerly initialize the GemFire DistributedSystem (if needed)
|
||||
@@ -177,7 +191,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
|
||||
/* (non-Javadoc) */
|
||||
void resolveDistributedSystem() {
|
||||
if (InternalDistributedSystem.getAnyInstance() == null) {
|
||||
if (DistributedSystemUtils.getDistributedSystem() == null) {
|
||||
doDistributedSystemConnect(resolveGemfireProperties());
|
||||
}
|
||||
}
|
||||
@@ -257,8 +271,17 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
this.keepAlive = keepAlive;
|
||||
}
|
||||
|
||||
public void setLocators(Collection<InetSocketAddress> locators) {
|
||||
this.locators = locators;
|
||||
@Deprecated
|
||||
public void setLocators(Iterable<InetSocketAddress> locators) {
|
||||
setLocatorEndpoints(ConnectionEndpointList.from(locators));
|
||||
}
|
||||
|
||||
public void setLocatorEndpoints(Iterable<ConnectionEndpoint> endpoints) {
|
||||
this.locators.add(endpoints);
|
||||
}
|
||||
|
||||
public void setLocatorEndpointList(ConnectionEndpointList endpointList) {
|
||||
setLocatorEndpoints(endpointList);
|
||||
}
|
||||
|
||||
public void setLoadConditioningInterval(int loadConditioningInterval) {
|
||||
@@ -297,8 +320,17 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
|
||||
this.serverGroup = serverGroup;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setServers(Collection<InetSocketAddress> servers) {
|
||||
this.servers = servers;
|
||||
setServerEndpoints(ConnectionEndpointList.from(servers));
|
||||
}
|
||||
|
||||
public void setServerEndpoints(Iterable<ConnectionEndpoint> endpoints) {
|
||||
this.servers.add(endpoints);
|
||||
}
|
||||
|
||||
public void setServerEndpointList(ConnectionEndpointList endpointList) {
|
||||
setServerEndpoints(endpointList);
|
||||
}
|
||||
|
||||
public void setSocketBufferSize(int socketBufferSize) {
|
||||
|
||||
@@ -16,24 +16,26 @@
|
||||
|
||||
package org.springframework.data.gemfire.config;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpointList;
|
||||
import org.springframework.data.gemfire.util.DistributedSystemUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.gemstone.gemfire.cache.server.CacheServer;
|
||||
import com.gemstone.gemfire.internal.DistributionLocator;
|
||||
|
||||
/**
|
||||
* Parser for GFE <pool;gt; bean definitions.
|
||||
*
|
||||
@@ -41,10 +43,12 @@ import com.gemstone.gemfire.internal.DistributionLocator;
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
*/
|
||||
class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
class PoolParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
protected static final int DEFAULT_LOCATOR_PORT = DistributionLocator.DEFAULT_LOCATOR_PORT;
|
||||
protected static final int DEFAULT_SERVER_PORT = CacheServer.DEFAULT_PORT;
|
||||
protected static final int DEFAULT_LOCATOR_PORT = DistributedSystemUtils.DEFAULT_LOCATOR_PORT;
|
||||
protected static final int DEFAULT_SERVER_PORT = DistributedSystemUtils.DEFAULT_CACHE_SERVER_PORT;
|
||||
|
||||
protected static final Pattern PROPERTY_PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{.+\\}");
|
||||
|
||||
protected static final String DEFAULT_HOST = "localhost";
|
||||
protected static final String HOST_ATTRIBUTE_NAME = "host";
|
||||
@@ -58,53 +62,95 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return PoolFactoryBean.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
ParsingUtils.setPropertyValue(element, builder, "free-connection-timeout");
|
||||
ParsingUtils.setPropertyValue(element, builder, "idle-timeout");
|
||||
ParsingUtils.setPropertyValue(element, builder, "load-conditioning-interval");
|
||||
ParsingUtils.setPropertyValue(element, builder, "keep-alive");
|
||||
ParsingUtils.setPropertyValue(element, builder, "max-connections");
|
||||
ParsingUtils.setPropertyValue(element, builder, "min-connections");
|
||||
ParsingUtils.setPropertyValue(element, builder, "multi-user-authentication");
|
||||
ParsingUtils.setPropertyValue(element, builder, "ping-interval");
|
||||
ParsingUtils.setPropertyValue(element, builder, "pr-single-hop-enabled");
|
||||
ParsingUtils.setPropertyValue(element, builder, "read-timeout");
|
||||
ParsingUtils.setPropertyValue(element, builder, "retry-attempts");
|
||||
ParsingUtils.setPropertyValue(element, builder, "server-group");
|
||||
ParsingUtils.setPropertyValue(element, builder, "socket-buffer-size");
|
||||
ParsingUtils.setPropertyValue(element, builder, "statistic-interval");
|
||||
ParsingUtils.setPropertyValue(element, builder, "subscription-ack-interval");
|
||||
ParsingUtils.setPropertyValue(element, builder, "subscription-enabled");
|
||||
ParsingUtils.setPropertyValue(element, builder, "subscription-message-tracking-timeout");
|
||||
ParsingUtils.setPropertyValue(element, builder, "subscription-redundancy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "thread-local-connections");
|
||||
|
||||
ManagedList<BeanDefinition> locators = new ManagedList<BeanDefinition>(subElements.size());
|
||||
ManagedList<BeanDefinition> servers = new ManagedList<BeanDefinition>(subElements.size());
|
||||
List<Element> childElements = DomUtils.getChildElements(element);
|
||||
|
||||
// parse nested locator/server elements
|
||||
for (Element subElement : subElements) {
|
||||
String name = subElement.getLocalName();
|
||||
ManagedList<BeanDefinition> locators = new ManagedList<BeanDefinition>(childElements.size());
|
||||
ManagedList<BeanDefinition> servers = new ManagedList<BeanDefinition>(childElements.size());
|
||||
|
||||
if (LOCATOR_ELEMENT_NAME.equals(name)) {
|
||||
locators.add(parseLocator(subElement));
|
||||
for (Element childElement : childElements) {
|
||||
String childElementName = childElement.getLocalName();
|
||||
|
||||
if (LOCATOR_ELEMENT_NAME.equals(childElementName)) {
|
||||
locators.add(parseLocator(childElement));
|
||||
}
|
||||
if (SERVER_ELEMENT_NAME.equals(name)) {
|
||||
servers.add(parseServer(subElement));
|
||||
|
||||
if (SERVER_ELEMENT_NAME.equals(childElementName)) {
|
||||
servers.add(parseServer(childElement));
|
||||
}
|
||||
}
|
||||
|
||||
locators.addAll(parseLocators(element));
|
||||
servers.addAll(parseServers(element));
|
||||
locators.addAll(parseLocators(element, builder));
|
||||
servers.addAll(parseServers(element, builder));
|
||||
|
||||
// NOTE if neither Locators or Servers were specified, then setup a default connection to a Locator
|
||||
// running on localhost listening on the default Locator port (10334) for convenience
|
||||
if (locators.isEmpty() && servers.isEmpty()) {
|
||||
// NOTE if neither Locators nor Servers were specified, then setup a default connection to a Locator
|
||||
// listening on the default Locator port (10334), running on localhost
|
||||
if (childElements.isEmpty() && !hasAttributes(element, LOCATORS_ATTRIBUTE_NAME, SERVERS_ATTRIBUTE_NAME)) {
|
||||
locators.add(buildConnection(DEFAULT_HOST, String.valueOf(DEFAULT_LOCATOR_PORT), false));
|
||||
}
|
||||
|
||||
if (!locators.isEmpty()) {
|
||||
builder.addPropertyValue("locators", locators);
|
||||
builder.addPropertyValue("locatorEndpoints", locators);
|
||||
}
|
||||
|
||||
if (!servers.isEmpty()) {
|
||||
builder.addPropertyValue("servers", servers);
|
||||
builder.addPropertyValue("serverEndpoints", servers);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
boolean hasAttributes(Element element, String... attributeNames) {
|
||||
for (String attributeName : attributeNames) {
|
||||
if (element.hasAttribute(attributeName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BeanDefinition buildConnections(String propertyPlaceholder, boolean server) {
|
||||
BeanDefinitionBuilder connectionEndpointListBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
ConnectionEndpointList.class);
|
||||
|
||||
connectionEndpointListBuilder.setFactoryMethod("parse");
|
||||
connectionEndpointListBuilder.addConstructorArgValue(defaultPort(null, server));
|
||||
connectionEndpointListBuilder.addConstructorArgValue(propertyPlaceholder);
|
||||
|
||||
return connectionEndpointListBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
BeanDefinition buildConnection(String host, String port, boolean server) {
|
||||
BeanDefinitionBuilder inetSocketAddressBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
InetSocketAddress.class);
|
||||
BeanDefinitionBuilder connectionEndpointBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
ConnectionEndpoint.class);
|
||||
|
||||
inetSocketAddressBuilder.addConstructorArgValue(defaultHost(host));
|
||||
inetSocketAddressBuilder.addConstructorArgValue(defaultPort(port, server));
|
||||
connectionEndpointBuilder.addConstructorArgValue(defaultHost(host));
|
||||
connectionEndpointBuilder.addConstructorArgValue(defaultPort(port, server));
|
||||
|
||||
return inetSocketAddressBuilder.getBeanDefinition();
|
||||
return connectionEndpointBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -119,13 +165,15 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
ManagedList<BeanDefinition> parseConnections(String hostPortCommaDelimitedList, boolean server) {
|
||||
ManagedList<BeanDefinition> connections = new ManagedList<BeanDefinition>();
|
||||
List<BeanDefinition> parseConnections(String hostPortCommaDelimitedList, boolean server) {
|
||||
List<BeanDefinition> connections = Collections.emptyList();
|
||||
|
||||
if (StringUtils.hasText(hostPortCommaDelimitedList)) {
|
||||
String[] hostPorts = hostPortCommaDelimitedList.split(",");
|
||||
String[] hostsPorts = hostPortCommaDelimitedList.split(",");
|
||||
|
||||
for (String hostPort : hostPorts) {
|
||||
connections = new ArrayList<BeanDefinition>(hostsPorts.length);
|
||||
|
||||
for (String hostPort : hostsPorts) {
|
||||
connections.add(parseConnection(hostPort, server));
|
||||
}
|
||||
}
|
||||
@@ -135,17 +183,14 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
BeanDefinition parseConnection(String hostPort, boolean server) {
|
||||
String host = hostPort.trim();
|
||||
String port = defaultPort(null, server);
|
||||
String host;
|
||||
|
||||
int portIndex = hostPort.indexOf('[');
|
||||
int portIndex = host.indexOf('[');
|
||||
|
||||
if (portIndex > -1) {
|
||||
host = hostPort.substring(0, portIndex).trim();
|
||||
port = parseDigits(hostPort.substring(portIndex)).trim();
|
||||
}
|
||||
else {
|
||||
host = hostPort.trim();
|
||||
port = parseDigits(host.substring(portIndex)).trim();
|
||||
host = host.substring(0, portIndex).trim();
|
||||
}
|
||||
|
||||
return buildConnection(host, port, server);
|
||||
@@ -155,9 +200,9 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
String parseDigits(String value) {
|
||||
StringBuilder digits = new StringBuilder();
|
||||
|
||||
for (char chr : value.toCharArray()) {
|
||||
if (Character.isDigit(chr)) {
|
||||
digits.append(chr);
|
||||
for (char character : value.toCharArray()) {
|
||||
if (Character.isDigit(character)) {
|
||||
digits.append(character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,21 +210,52 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
BeanDefinition parseLocator(Element element) {
|
||||
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME), element.getAttribute(PORT_ATTRIBUTE_NAME), false);
|
||||
boolean isPropertyPlaceholder(String value) {
|
||||
return PROPERTY_PLACEHOLDER_PATTERN.matcher(value).matches();
|
||||
}
|
||||
|
||||
ManagedList<BeanDefinition> parseLocators(Element element) {
|
||||
return parseConnections(element.getAttribute(LOCATORS_ATTRIBUTE_NAME), false);
|
||||
/* (non-Javadoc) */
|
||||
BeanDefinition parseLocator(Element element) {
|
||||
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME),
|
||||
element.getAttribute(PORT_ATTRIBUTE_NAME), false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
List<BeanDefinition> parseLocators(Element element, BeanDefinitionBuilder builder) {
|
||||
List<BeanDefinition> beanDefinitions = Collections.emptyList();
|
||||
|
||||
String locatorsAttributeValue = element.getAttribute(LOCATORS_ATTRIBUTE_NAME);
|
||||
|
||||
if (isPropertyPlaceholder(locatorsAttributeValue)) {
|
||||
builder.addPropertyValue("locatorEndpointList", buildConnections(locatorsAttributeValue, false));
|
||||
}
|
||||
else {
|
||||
beanDefinitions = parseConnections(locatorsAttributeValue, false);
|
||||
}
|
||||
|
||||
return beanDefinitions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
BeanDefinition parseServer(Element element) {
|
||||
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME), element.getAttribute(PORT_ATTRIBUTE_NAME), false);
|
||||
return buildConnection(element.getAttribute(HOST_ATTRIBUTE_NAME),
|
||||
element.getAttribute(PORT_ATTRIBUTE_NAME), true);
|
||||
}
|
||||
|
||||
ManagedList<BeanDefinition> parseServers(Element element) {
|
||||
return parseConnections(element.getAttribute(SERVERS_ATTRIBUTE_NAME), true);
|
||||
/* (non-Javadoc) */
|
||||
List<BeanDefinition> parseServers(Element element, BeanDefinitionBuilder builder) {
|
||||
List<BeanDefinition> beanDefinitions = Collections.emptyList();
|
||||
|
||||
String serversAttributeValue = element.getAttribute(SERVERS_ATTRIBUTE_NAME);
|
||||
|
||||
if (isPropertyPlaceholder(serversAttributeValue)) {
|
||||
builder.addPropertyValue("serverEndpointList", buildConnections(serversAttributeValue, true));
|
||||
}
|
||||
else {
|
||||
beanDefinitions = parseConnections(serversAttributeValue, true);
|
||||
}
|
||||
|
||||
return beanDefinitions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The ConnectionEndpoint class models a GemFire connection endpoint in the format of hostname[portnumber],
|
||||
* where hostname is the network name or IP address of the host.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Cloneable
|
||||
* @see java.lang.Comparable
|
||||
* @since 1.6.3
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ConnectionEndpoint implements Cloneable, Comparable<ConnectionEndpoint> {
|
||||
|
||||
protected static final int DEFAULT_PORT = 0; // ephemeral port
|
||||
|
||||
protected static final String DEFAULT_HOST = "localhost";
|
||||
|
||||
private final int port;
|
||||
private final String host;
|
||||
|
||||
/**
|
||||
* Converts the InetSocketAddress into a ConnectionEndpoint.
|
||||
*
|
||||
* @param socketAddress the InetSocketAddress used to construct and initialize the ConnectionEndpoint.
|
||||
* @return a ConnectionEndpoint representing the InetSocketAddress.
|
||||
* @see java.net.InetSocketAddress
|
||||
*/
|
||||
public static ConnectionEndpoint from(InetSocketAddress socketAddress) {
|
||||
return new ConnectionEndpoint(socketAddress.getHostString(), socketAddress.getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the host and port String value into a valid ConnectionEndpoint.
|
||||
*
|
||||
* @param hostPort a String value containing the host and port formatted as 'host[port]'.
|
||||
* @return a valid ConnectionEndpoint initialized with the host and port, or with DEFAULT_PORT
|
||||
* if port was unspecified.
|
||||
* @see #parse(String, int)
|
||||
* @see #DEFAULT_PORT
|
||||
*/
|
||||
public static ConnectionEndpoint parse(String hostPort) {
|
||||
return parse(hostPort, DEFAULT_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the host and port value into a valid ConnectionEndpoint.
|
||||
*
|
||||
* @param hostPort a String value containing the host and port formatted as 'host[port]'.
|
||||
* @param defaultPort an Integer value indicating the default port to use if the port is unspecified
|
||||
* in the host and port String value.
|
||||
* @return a valid ConnectionEndpoint initialized with the host and port, or with the default port
|
||||
* if port was unspecified.
|
||||
* @see #ConnectionEndpoint(String, int)
|
||||
*/
|
||||
public static ConnectionEndpoint parse(String hostPort, int defaultPort) {
|
||||
Assert.hasText(hostPort, "'hostPort' must be specified");
|
||||
|
||||
String host = StringUtils.trimAllWhitespace(hostPort);
|
||||
|
||||
int port = defaultPort;
|
||||
int portIndex = hostPort.indexOf("[");
|
||||
|
||||
if (portIndex > -1) {
|
||||
port = parsePort(parseDigits(host.substring(portIndex)), defaultPort);
|
||||
host = host.substring(0, portIndex).trim();
|
||||
}
|
||||
|
||||
return new ConnectionEndpoint(host, port);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
static String parseDigits(String value) {
|
||||
StringBuilder digits = new StringBuilder();
|
||||
|
||||
if (StringUtils.hasText(value)) {
|
||||
for (char character : value.toCharArray()) {
|
||||
if (Character.isDigit(character)) {
|
||||
digits.append(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return digits.toString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
static int parsePort(String port, int defaultPort) {
|
||||
try {
|
||||
return Integer.parseInt(port);
|
||||
}
|
||||
catch (NumberFormatException ignore) {
|
||||
return defaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ConnectionEndpoint initialized with the specific host and port.
|
||||
*
|
||||
* @param host the hostname or IP address of the ConnectionEndpoint. If the host is unspecified,
|
||||
* then ConnectionEndpoint.DEFAULT_HOST will be used.
|
||||
* @param port the (service) port number in this ConnectionEndpoint.
|
||||
* @throws IllegalArgumentException if the port number is less than 0.
|
||||
* @see ConnectionEndpoint#DEFAULT_HOST
|
||||
*/
|
||||
public ConnectionEndpoint(String host, int port) {
|
||||
Assert.isTrue(port >= 0 && port <= 65535, String.format("port number (%1$d) must be between 0 and 65535", port));
|
||||
|
||||
this.host = (StringUtils.hasText(host) ? host : DEFAULT_HOST);
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host in this ConnectionEndpoint.
|
||||
*
|
||||
* @return a String value indicating the hostname or IP address in this ConnectionEndpoint.
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port number in this ConnectionEndpoint.
|
||||
*
|
||||
* @return an Integer value indicating the (service) port number in this ConnectionEndpoint.
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
return new ConnectionEndpoint(this.getHost(), this.getPort());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public int compareTo(ConnectionEndpoint connectionEndpoint) {
|
||||
int compareValue = getHost().compareTo(connectionEndpoint.getHost());
|
||||
return (compareValue != 0 ? compareValue : getPort() - connectionEndpoint.getPort());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof ConnectionEndpoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConnectionEndpoint that = (ConnectionEndpoint) obj;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(this.getHost(), that.getHost())
|
||||
&& ObjectUtils.nullSafeEquals(this.getPort(), that.getPort());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashValue = 17;
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getHost());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getPort());
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%1$s[%2$d]", getHost(), getPort());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* The ConnectionEndpointList class is an Iterable collection of ConnectionEndpoint objects.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Iterable
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @since 1.6.3
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ConnectionEndpointList implements Iterable<ConnectionEndpoint> {
|
||||
|
||||
private final List<ConnectionEndpoint> connectionEndpoints;
|
||||
|
||||
/**
|
||||
* Converts the array of InetSocketAddresses into an instance of ConnectionEndpointList.
|
||||
*
|
||||
* @param socketAddresses the array of InetSocketAddresses used to initialize an instance of ConnectionEndpointList.
|
||||
* @return a ConnectionEndpointList representing the array of InetSocketAddresses.
|
||||
* @see java.net.InetSocketAddress
|
||||
* @see #from(Iterable)
|
||||
*/
|
||||
public static ConnectionEndpointList from(InetSocketAddress... socketAddresses) {
|
||||
return from(Arrays.asList(socketAddresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Iterable collection of InetSocketAddresses into an instance of ConnectionEndpointList.
|
||||
*
|
||||
* @param socketAddresses in Iterable collection of InetSocketAddresses used to initialize an instance
|
||||
* of ConnectionEndpointList.
|
||||
* @return a ConnectionEndpointList representing the array of InetSocketAddresses.
|
||||
* @see java.net.InetSocketAddress
|
||||
*/
|
||||
public static ConnectionEndpointList from(Iterable<InetSocketAddress> socketAddresses) {
|
||||
List<ConnectionEndpoint> connectionEndpoints = new ArrayList<ConnectionEndpoint>();
|
||||
|
||||
for (InetSocketAddress socketAddress : CollectionUtils.nullSafeIterable(socketAddresses)) {
|
||||
connectionEndpoints.add(ConnectionEndpoint.from(socketAddress));
|
||||
}
|
||||
|
||||
return new ConnectionEndpointList(connectionEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the array of hosts and ports in the format 'host[port]' to convert into an instance
|
||||
* of ConnectionEndpointList.
|
||||
*
|
||||
* @param defaultPort the default port number to use if port is not specified in a host and port value.
|
||||
* @param hostsPorts the array of hosts and ports to parse.
|
||||
* @return a ConnectionEndpointList representing the hosts and ports in the array.
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint#parse(String, int)
|
||||
*/
|
||||
public static ConnectionEndpointList parse(int defaultPort, String... hostsPorts) {
|
||||
List<ConnectionEndpoint> connectionEndpoints = new ArrayList<ConnectionEndpoint>(hostsPorts.length);
|
||||
|
||||
for (String hostPort : ArrayUtils.nullSafeArray(hostsPorts)) {
|
||||
connectionEndpoints.add(ConnectionEndpoint.parse(hostPort, defaultPort));
|
||||
}
|
||||
|
||||
return new ConnectionEndpointList(connectionEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty, uninitialized instance of the ConnectionEndpointList collection.
|
||||
*/
|
||||
public ConnectionEndpointList() {
|
||||
this(Collections.<ConnectionEndpoint>emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of ConnectionEndpointList initialized with the the array of ConnectionEndpoints.
|
||||
*
|
||||
* @param connectionEndpoints is an array containing ConnectionEndpoints to add to this collection.
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see #ConnectionEndpointList(Iterable)
|
||||
*/
|
||||
public ConnectionEndpointList(ConnectionEndpoint... connectionEndpoints) {
|
||||
this(Arrays.asList(connectionEndpoints));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of ConnectionEndpointList initialized with the Iterable collection of ConnectionEndpoints.
|
||||
*
|
||||
* @param connectionEndpoints the Iterable object containing ConnectionEndpoints to add to this collection.
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
public ConnectionEndpointList(Iterable<ConnectionEndpoint> connectionEndpoints) {
|
||||
this.connectionEndpoints = new ArrayList<ConnectionEndpoint>();
|
||||
add(connectionEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the array of ConnectionEndpoints to this list.
|
||||
*
|
||||
* @param connectionEndpoints the array of ConnectionEndpoints to add to this list.
|
||||
* @return this ConnectionEndpointList to support the Builder pattern style of chaining.
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see #add(Iterable)
|
||||
*/
|
||||
public final ConnectionEndpointList add(ConnectionEndpoint... connectionEndpoints) {
|
||||
Collections.addAll(this.connectionEndpoints, connectionEndpoints);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Iterable collection of ConnectionEndpoints to this list.
|
||||
*
|
||||
* @param connectionEndpoints the Iterable collection of ConnectionEndpoints to add to this list.
|
||||
* @return this ConnectionEndpointList to support the Builder pattern style of chaining.
|
||||
* @see org.springframework.data.gemfire.support.ConnectionEndpoint
|
||||
* @see #add(ConnectionEndpoint...)
|
||||
*/
|
||||
public final ConnectionEndpointList add(Iterable<ConnectionEndpoint> connectionEndpoints) {
|
||||
for (ConnectionEndpoint connectionEndpoint : CollectionUtils.nullSafeIterable(connectionEndpoints)) {
|
||||
this.connectionEndpoints.add(connectionEndpoint);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all ConnectionEndpoints in this list with the specified hostname.
|
||||
*
|
||||
* @param host a String indicating the hostname to use in the match.
|
||||
* @return a ConnectionEndpointList (sub-List) containing all the ConnectionEndpoints matching the given hostname.
|
||||
* @see #findBy(int)
|
||||
*/
|
||||
public ConnectionEndpointList findBy(String host) {
|
||||
List<ConnectionEndpoint> connectionEndpoints = new ArrayList<ConnectionEndpoint>(size());
|
||||
|
||||
for (ConnectionEndpoint connectionEndpoint : this) {
|
||||
if (connectionEndpoint.getHost().equals(host)) {
|
||||
connectionEndpoints.add(connectionEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
return new ConnectionEndpointList(connectionEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all ConnectionEndpoints in this list with the specified port number.
|
||||
*
|
||||
* @param port an Integer value indicating the port number to use in the match.
|
||||
* @return a ConnectionEndpointList (sub-List) containing all the ConnectionEndpoints matching the given port number.
|
||||
* @see #findBy(String)
|
||||
*/
|
||||
public ConnectionEndpointList findBy(int port) {
|
||||
List<ConnectionEndpoint> connectionEndpoints = new ArrayList<ConnectionEndpoint>(size());
|
||||
|
||||
for (ConnectionEndpoint connectionEndpoint : this) {
|
||||
if (connectionEndpoint.getPort() == port) {
|
||||
connectionEndpoints.add(connectionEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
return new ConnectionEndpointList(connectionEndpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this collection contains any ConnectionEndpoints.
|
||||
*
|
||||
* @return a boolean value indicating whether this collection contains any ConnectionEndpoints.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return connectionEndpoints.isEmpty();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public Iterator<ConnectionEndpoint> iterator() {
|
||||
return Collections.unmodifiableList(connectionEndpoints).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of ConnectionEndpoints contained in this collection.
|
||||
*
|
||||
* @return an integer value indicating the number of ConnectionEndpoints contained in this collection.
|
||||
*/
|
||||
public int size() {
|
||||
return connectionEndpoints.size();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public String toString() {
|
||||
return connectionEndpoints.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -78,6 +78,19 @@ public abstract class ArrayUtils {
|
||||
return (array != null ? array.length : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe, empty array operation returning the given Object array if not null or an empty Object array
|
||||
* if the array argument is null.
|
||||
*
|
||||
* @param <T> the element Class type of the array.
|
||||
* @param array the Object array on which a null check is performed.
|
||||
* @return the given Object array if not null, otherwise return an empty Object array.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] nullSafeArray(T[] array) {
|
||||
return (array != null ? array : (T[]) new Object[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from the given array at position (index). The element is removed at the specified position
|
||||
* and all remaining elements are shifted to the left.
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.springframework.data.gemfire.util;
|
||||
|
||||
import com.gemstone.gemfire.cache.server.CacheServer;
|
||||
import com.gemstone.gemfire.distributed.DistributedSystem;
|
||||
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
|
||||
import com.gemstone.gemfire.internal.DistributionLocator;
|
||||
|
||||
/**
|
||||
* DistributedSystemUtils is an abstract utility class for working with the GemFire DistributedSystem.
|
||||
@@ -28,6 +30,9 @@ import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
|
||||
*/
|
||||
public abstract class DistributedSystemUtils {
|
||||
|
||||
public static final int DEFAULT_CACHE_SERVER_PORT = CacheServer.DEFAULT_PORT;
|
||||
public static final int DEFAULT_LOCATOR_PORT = DistributionLocator.DEFAULT_LOCATOR_PORT;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends DistributedSystem> T getDistributedSystem() {
|
||||
return (T) InternalDistributedSystem.getAnyInstance();
|
||||
|
||||
Reference in New Issue
Block a user