SGF-398 - Provide early support of Apache Geode (Pivotal GemFire OSS).

Implemented Pivotal GemFire/Apache Geode feature checking during SDG XML namespace parsing and processing.
This commit is contained in:
John Blum
2015-05-04 10:23:37 -07:00
parent abbbfed8fd
commit 9a1210bc84
4 changed files with 80 additions and 38 deletions

View File

@@ -19,9 +19,11 @@ package org.springframework.data.gemfire;
import java.util.concurrent.ConcurrentMap;
import org.springframework.util.ClassUtils;
import org.w3c.dom.Element;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.internal.GemFireVersion;
/**
* The GemfireUtils class is a utility class encapsulating common functionality to access features and capabilities
@@ -32,18 +34,62 @@ import com.gemstone.gemfire.cache.Region;
*/
public abstract class GemfireUtils {
public final static String GEMFIRE_NAME = GemFireVersion.getProductName();
public final static String GEMFIRE_VERSION = CacheFactory.getVersion();
// TODO use a more reliable means of determining implementing class for GemFire features such as Java's SPI support
private static final String ASYNC_EVENT_QUEUE_TYPE_NAME = "com.gemstone.gemfire.cache.AsyncEventQueue";
private static final String CQ_TYPE_NAME = "com.gemstone.gemfire.cache.query.internal.cq.CqServiceFactoryImpl";
private static final String GATEWAY_TYPE_NAME = "com.gemstone.gemfire.internal.cache.wan.GatewaySenderFactoryImpl";
public static boolean isClassAvailable(String fullyQualifiedClassName) {
return ClassUtils.isPresent(fullyQualifiedClassName, GemfireUtils.class.getClassLoader());
}
public static boolean isGemfireFeatureAvailable(Element element) {
boolean featureAvailable = (!isAsyncEventQueue(element) || isAsyncEventQueueAvailable());
featureAvailable &= (!isContinuousQuery(element) || isContinuousQueryAvailable());
featureAvailable &= (!isGateway(element) || isGatewayAvailable());
return featureAvailable;
}
public static boolean isGemfireFeatureUnavailable(Element element) {
return !isGemfireFeatureAvailable(element);
}
private static boolean isAsyncEventQueue(Element element) {
return "async-event-queue".equals(element.getLocalName());
}
private static boolean isAsyncEventQueueAvailable() {
return isClassAvailable(ASYNC_EVENT_QUEUE_TYPE_NAME);
}
private static boolean isContinuousQuery(Element element) {
return "cq-listener-container".equals(element.getLocalName());
}
private static boolean isContinuousQueryAvailable() {
return isClassAvailable(CQ_TYPE_NAME);
}
private static boolean isGateway(Element element) {
String elementLocalName = element.getLocalName();
return ("gateway-receiver".equals(elementLocalName) || "gateway-sender".equals(elementLocalName));
}
private static boolean isGatewayAvailable() {
return isClassAvailable(GATEWAY_TYPE_NAME);
}
public static boolean isGemfireVersionGreaterThanEqual(double expectedVersion) {
double actualVersion = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return actualVersion >= expectedVersion;
return (actualVersion >= expectedVersion);
}
public static boolean isGemfireVersion65OrAbove() {
// expected 'major.minor'
try {
double version = Double.parseDouble(GEMFIRE_VERSION.substring(0, 3));
return version >= 6.5;
return isGemfireVersionGreaterThanEqual(6.5);
}
catch (NumberFormatException e) {
// NOTE based on logic from the PartitionedRegionFactoryBean class...

View File

@@ -16,9 +16,6 @@
package org.springframework.data.gemfire.config;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;
@@ -35,20 +32,9 @@ import org.w3c.dom.Element;
@SuppressWarnings("unused")
class GemfireNamespaceHandler extends NamespaceHandlerSupport {
protected static final List<String> GEMFIRE7_ELEMENTS = Arrays.asList(
"async-event-queue",
"gateway-receiver",
"gateway-sender"
);
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
boolean v7ElementsPresent = GEMFIRE7_ELEMENTS.contains(element.getLocalName());
if (v7ElementsPresent) {
ParsingUtils.throwExceptionIfNotGemfireV7(element.getLocalName(), null, parserContext);
}
ParsingUtils.assertGemFireFeatureAvailable(element, parserContext);
return super.parse(element, parserContext);
}

View File

@@ -365,17 +365,6 @@ abstract class ParsingUtils {
}
}
static void throwExceptionIfNotGemfireV7(String elementName, String attributeName, ParserContext parserContext) {
if (!GemfireUtils.isGemfireVersion7OrAbove()) {
String messagePrefix = (attributeName != null)
? String.format("Attribute '%1$s' of element '%2$s'", attributeName, elementName)
: String.format("Element '%1$s'", elementName);
parserContext.getReaderContext().error(
String.format("%1$s requires GemFire version 7 or later. The current version is %2$s.",
messagePrefix, GemfireUtils.GEMFIRE_VERSION), null);
}
}
static void parseScope(Element element, BeanDefinitionBuilder builder) {
String scopeAttributeValue = element.getAttribute("scope");
@@ -431,4 +420,22 @@ abstract class ParsingUtils {
return (StringUtils.hasText(cacheRef) ? cacheRef : GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME);
}
static void assertGemFireFeatureAvailable(Element element, ParserContext parserContext) {
if (GemfireUtils.isGemfireFeatureUnavailable(element)) {
parserContext.getReaderContext().error(String.format("'%1$s' is not supported in %2$s v%3$s",
element.getLocalName(), GemfireUtils.GEMFIRE_NAME, GemfireUtils.GEMFIRE_VERSION), element);
}
}
static void throwExceptionIfNotGemfireV7(String elementName, String attributeName, ParserContext parserContext) {
if (!GemfireUtils.isGemfireVersion7OrAbove()) {
String messagePrefix = (attributeName != null)
? String.format("Attribute '%1$s' of element '%2$s'", attributeName, elementName)
: String.format("Element '%1$s'", elementName);
parserContext.getReaderContext().error(
String.format("%1$s requires GemFire version 7 or later. The current version is %2$s.",
messagePrefix, GemfireUtils.GEMFIRE_VERSION), null);
}
}
}

View File

@@ -38,12 +38,8 @@ public class GemfireUtilsTest {
protected int getGemFireVersion() {
try {
String gemfireVersion = GemFireVersion.getGemFireVersion();
StringBuilder buffer = new StringBuilder();
buffer.append(GemFireVersion.getMajorVersion(gemfireVersion));
buffer.append(GemFireVersion.getMinorVersion(gemfireVersion));
return Integer.decode(buffer.toString());
return Integer.decode(String.format("%1$d%2$d", GemFireVersion.getMajorVersion(gemfireVersion),
GemFireVersion.getMinorVersion(gemfireVersion)));
}
catch (NumberFormatException ignore) {
return -1;
@@ -51,17 +47,24 @@ public class GemfireUtilsTest {
}
@Test
public void testIsGemfireVersion65OrAbove() {
public void isGemfireVersion65OrAbove() {
int gemfireVersion = getGemFireVersion();
assumeTrue(gemfireVersion > -1);
assertEquals(getGemFireVersion() >= 65, GemfireUtils.isGemfireVersion65OrAbove());
}
@Test
public void testIsGemfireVersion7OrAbove() {
public void isGemfireVersion7OrAbove() {
int gemfireVersion = getGemFireVersion();
assumeTrue(gemfireVersion > -1);
assertEquals(getGemFireVersion() >= 70, GemfireUtils.isGemfireVersion7OrAbove());
}
@Test
public void isGemfireVersion8OrAbove() {
int gemfireVersion = getGemFireVersion();
assumeTrue(gemfireVersion > -1);
assertEquals(getGemFireVersion() >= 80, GemfireUtils.isGemfireVersion7OrAbove());
}
}