SGF-390 - Improve unit test coverage for the PoolFactoryBean class.

This commit is contained in:
John Blum
2015-04-01 14:25:00 -07:00
parent 06d1df02ce
commit d44464dee5
12 changed files with 610 additions and 131 deletions

View File

@@ -19,8 +19,6 @@ package org.springframework.data.gemfire;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -38,6 +36,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -487,7 +486,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
/* (non-Javadoc) */
private void registerTransactionListeners(Cache cache) {
for (TransactionListener transactionListener : nullSafeCollection(transactionListeners)) {
for (TransactionListener transactionListener : CollectionUtils.nullSafeCollection(transactionListeners)) {
cache.getCacheTransactionManager().addListener(transactionListener);
}
}
@@ -501,7 +500,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
/* (non-Javadoc) */
private void registerJndiDataSources() {
for (JndiDataSource jndiDataSource : nullSafeCollection(jndiDataSources)) {
for (JndiDataSource jndiDataSource : CollectionUtils.nullSafeCollection(jndiDataSources)) {
String typeAttributeValue = jndiDataSource.getAttributes().get("type");
JndiDataSourceType jndiDataSourceType = JndiDataSourceType.valueOfIgnoreCase(typeAttributeValue);
@@ -514,10 +513,6 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
}
}
protected <T> Collection<T> nullSafeCollection(final Collection<T> collection) {
return (collection != null ? collection : Collections.<T>emptyList());
}
@Override
public void destroy() throws Exception {
if (close) {

View File

@@ -23,6 +23,7 @@ import java.util.Properties;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -180,11 +181,11 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
clientCacheFactory.setPoolSubscriptionRedundancy(pool.getSubscriptionRedundancy());
clientCacheFactory.setPoolThreadLocalConnections(pool.getThreadLocalConnections());
for (InetSocketAddress socketAddress : nullSafeCollection(pool.getLocators())) {
for (InetSocketAddress socketAddress : CollectionUtils.nullSafeCollection(pool.getLocators())) {
clientCacheFactory.addPoolLocator(socketAddress.getHostName(), socketAddress.getPort());
}
for (InetSocketAddress socketAddress : nullSafeCollection(pool.getServers())) {
for (InetSocketAddress socketAddress : CollectionUtils.nullSafeCollection(pool.getServers())) {
clientCacheFactory.addPoolServer(socketAddress.getHostName(), socketAddress.getPort());
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.data.gemfire.client;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -29,8 +28,8 @@ 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.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.client.Pool;
@@ -59,7 +58,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
// indicates whether the Pool has been created internally (by this FactoryBean) or not
private volatile boolean internalPool = true;
private volatile boolean springBasedPool = true;
private BeanFactory beanFactory;
@@ -109,7 +108,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(name)) {
Assert.hasText(beanName, "The Pool name is required!");
Assert.hasText(beanName, "Pool 'name' is required");
name = beanName;
}
@@ -121,7 +120,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
log.debug(String.format("A Pool with name '%1$s' already exists; using existing Pool.", name));
}
internalPool = false;
springBasedPool = false;
pool = existingPool;
}
else {
@@ -130,12 +129,12 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
}
if (CollectionUtils.isEmpty(locators) && CollectionUtils.isEmpty(servers)) {
throw new IllegalArgumentException("At least one locator or server is required!");
throw new IllegalArgumentException("at least one GemFire Locator or Server is required");
}
internalPool = true;
springBasedPool = true;
PoolFactory poolFactory = PoolManager.createFactory();
PoolFactory poolFactory = createPoolFactory();
poolFactory.setFreeConnectionTimeout(freeConnectionTimeout);
poolFactory.setIdleTimeout(idleTimeout);
@@ -156,33 +155,41 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
poolFactory.setSubscriptionRedundancy(subscriptionRedundancy);
poolFactory.setThreadLocalConnections(threadLocalConnections);
for (InetSocketAddress connection : nullSafeCollection(locators)) {
for (InetSocketAddress connection : CollectionUtils.nullSafeCollection(locators)) {
poolFactory.addLocator(connection.getHostName(), connection.getPort());
}
for (InetSocketAddress connection : nullSafeCollection(servers)) {
for (InetSocketAddress connection : CollectionUtils.nullSafeCollection(servers)) {
poolFactory.addServer(connection.getHostName(), connection.getPort());
}
// eagerly initialize ClientCache (if needed)
if (InternalDistributedSystem.getAnyInstance() == null) {
doDistributedSystemConnect(resolveGemfireProperties());
}
// eagerly initialize the GemFire DistributedSystem (if needed)
resolveDistributedSystem();
pool = poolFactory.create(name);
}
}
public void destroy() throws Exception {
if (internalPool && pool != null) {
if (!pool.isDestroyed()) {
pool.releaseThreadLocalConnection();
pool.destroy(keepAlive);
/* (non-Javadoc) */
protected PoolFactory createPoolFactory() {
return PoolManager.createFactory();
}
if (log.isDebugEnabled()) {
log.debug(String.format("Destroyed Pool '%1$s'.", name));
}
}
/* (non-Javadoc) */
void resolveDistributedSystem() {
if (InternalDistributedSystem.getAnyInstance() == null) {
doDistributedSystemConnect(resolveGemfireProperties());
}
}
/* (non-Javadoc) */
Properties resolveGemfireProperties() {
try {
ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
return clientCacheFactoryBean.getProperties();
}
catch (Exception ignore) {
return null;
}
}
@@ -195,26 +202,22 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
* @see com.gemstone.gemfire.distributed.DistributedSystem#connect(java.util.Properties)
*/
@SuppressWarnings("deprecation")
static void doDistributedSystemConnect(Properties properties) {
void doDistributedSystemConnect(Properties properties) {
Properties gemfireProperties = (properties != null ? (Properties) properties.clone() : new Properties());
gemfireProperties.setProperty("locators", "");
gemfireProperties.setProperty("mcast-port", "0");
DistributedSystem.connect(gemfireProperties);
}
/* (non-Javadoc) */
private <T> Collection<T> nullSafeCollection(final Collection<T> list) {
return (list != null ? list : Collections.<T>emptyList());
}
public void destroy() throws Exception {
if (springBasedPool && pool != null && !pool.isDestroyed()) {
pool.releaseThreadLocalConnection();
pool.destroy(keepAlive);
pool = null;
/* (non-Javadoc) */
private Properties resolveGemfireProperties() {
try {
ClientCacheFactoryBean clientCacheFactoryBean = beanFactory.getBean(ClientCacheFactoryBean.class);
return clientCacheFactoryBean.getProperties();
}
catch (Exception ignore) {
return null;
if (log.isDebugEnabled()) {
log.debug(String.format("Destroyed Pool '%1$s'.", name));
}
}
}

View File

@@ -10,79 +10,99 @@
* 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.util;
import java.lang.reflect.Array;
/**
* @author David Turanski
* The ArrayUtils class is a utility class for working with Object arrays.
*
* @author David Turanski
* @author John Blum
* @see java.lang.reflect.Array
*/
public abstract class ArrayUtils {
/**
* Insert an element into an array. The element is inserted at the
* given position, all elements afterwards are moved to the right.
*
* @param originalArray array to insert into
* @param pos position at which to insert the element
* @param element element to add
* @return the new array
*/
public static Object[] insert(Object[] originalArray, int pos, Object element) {
Object[] newArray = (Object[]) java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length + 1);
/**
* Insert an element into the given array at position (index). The element is inserted at the given position
* and all elements afterwards are moved to the right.
*
* @param originalArray the array in which to insert the element.
* @param position an integer index (position) at which to insert the element in the array.
* @param element the element to insert into the array.
* @return a new array with the element inserted at position.
* @see java.lang.System#arraycopy(Object, int, Object, int, int)
* @see java.lang.reflect.Array#newInstance(Class, int)
*/
public static Object[] insert(Object[] originalArray, int position, Object element) {
Object[] newArray = (Object[]) Array.newInstance(originalArray.getClass().getComponentType(),
originalArray.length + 1);
// copy everything before the given position
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // does not copy originalArray[pos], where we insert
}
// insert
newArray[pos] = element;
// copy all elements before the given position (here, position refers to the length, or number of elements
// to be copied, excluding the element at originalArray[position]
if (position > 0) {
System.arraycopy(originalArray, 0, newArray, 0, position);
}
// copy remaining elements
if (pos < originalArray.length) {
System.arraycopy(originalArray, pos, // originalArray[pos] first element copied
newArray, pos + 1, // newArray[pos + 1] first destination
originalArray.length - pos); // number of elements left
}
// insert
newArray[position] = element;
return newArray;
}
// copy remaining elements from originalArray, starting at position, to new array
if (position < originalArray.length) {
System.arraycopy(originalArray, position, newArray, position + 1, originalArray.length - position);
}
/**
* Remove element from an array. The element is removed at the
* specified position, and all remaining elements are moved to the left.
*
* @param originalArray array to remove from
* @param pos position to remove
* @return the new array
*/
public static Object[] remove(Object[] originalArray, int pos) {
Object[] newArray = (Object[])java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length - 1);
return newArray;
}
/**
* Determines whether the given array is empty or not.
*
* @param array the array to evaluate for emptiness.
* @return a boolean value indicating whether the given array is empty.
* @see #length(Object...)
*/
public static boolean isEmpty(Object... array) {
return (length(array) == 0);
}
// Copy everything before
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // originalArray[pos - 1] is last element copied
}
/**
* Null-safe operation to determine an array's length.
*
* @param array the array to determine it's length.
* @return the length of the given array or 0 if the array reference is null.
*/
public static int length(Object... array) {
return (array != null ? array.length : 0);
}
// Copy everything after
if (pos < originalArray.length - 1) {
System.arraycopy(originalArray, pos + 1, // originalArray[pos + 1] is first element copied
newArray, pos, // first position to copy into
originalArray.length - 1 - pos);
}
/**
* 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.
*
* @param originalArray the array from which to remove the element.
* @param position the integer index (position) indicating the element to remove from the array.
* @return a new array with the element at position in the originalArray removed.
* @see java.lang.System#arraycopy(Object, int, Object, int, int)
* @see java.lang.reflect.Array#newInstance(Class, int)
*/
public static Object[] remove(Object[] originalArray, int position) {
Object[] newArray = (Object[]) Array.newInstance(originalArray.getClass().getComponentType(),
originalArray.length - 1);
return newArray;
}
// copy all elements before position (here, position refers to the length, or number of elements to be copied
if (position > 0) {
System.arraycopy(originalArray, 0, newArray, 0, position);
}
// copy remaining elements after position from the originalArray
if (position < originalArray.length - 1) {
System.arraycopy(originalArray, position + 1, newArray, position, originalArray.length - 1 - position);
}
return newArray;
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.util;
import java.util.Collection;
import java.util.Collections;
/**
* The CollectionUtils class is a utility class for working with Java Collections Framework and classes.
*
* @author John Blum
* @see java.util.Collection
* @see java.util.Collections
* @see org.springframework.util.CollectionUtils
* @since 1.7.0
*/
@SuppressWarnings("unused")
public abstract class CollectionUtils extends org.springframework.util.CollectionUtils {
/**
* A null-safe operation returning the original Collection is non-null or an empty Collection
* (implemented with List) if null.
*
* @param <T> the element class type of the Collection.
* @param collection the Collection to evaluate for being null.
* @return the given Collection if not null, otherwise return an empty Collection (List).
* @see java.util.Collections#emptyList()
*/
public static <T> Collection<T> nullSafeCollection(final Collection<T> collection) {
return (collection != null ? collection : Collections.<T>emptyList());
}
}