From 9a1210bc84f1fe8f433a42ca01308592e3d09f6a Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 4 May 2015 10:23:37 -0700 Subject: [PATCH] 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. --- .../data/gemfire/GemfireUtils.java | 54 +++++++++++++++++-- .../config/GemfireNamespaceHandler.java | 16 +----- .../data/gemfire/config/ParsingUtils.java | 29 ++++++---- .../data/gemfire/GemfireUtilsTest.java | 19 ++++--- 4 files changed, 80 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/GemfireUtils.java b/src/main/java/org/springframework/data/gemfire/GemfireUtils.java index 28988444..39b818c8 100644 --- a/src/main/java/org/springframework/data/gemfire/GemfireUtils.java +++ b/src/main/java/org/springframework/data/gemfire/GemfireUtils.java @@ -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... diff --git a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java index 12ef2c0e..9625c937 100644 --- a/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java +++ b/src/main/java/org/springframework/data/gemfire/config/GemfireNamespaceHandler.java @@ -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 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); } diff --git a/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java b/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java index 002f77a0..989302fa 100644 --- a/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java +++ b/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java @@ -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); + } + } + } diff --git a/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java b/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java index 8a775146..44682718 100644 --- a/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java +++ b/src/test/java/org/springframework/data/gemfire/GemfireUtilsTest.java @@ -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()); + } + }