From 54821dcc662c52dac840b0bb4bc485bfc95ef586 Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 2 Feb 2015 13:31:31 -0800 Subject: [PATCH] SGF-289 - Enumeration restrictions (xsd:enumeration) should be avoided in the XML schema. Removed the XSD enumeration restriction on the 'type' attribute of the 'index' element definition inside the SDG XML namespace (XSD) allowing the use of property placeholders to specify the Index types on GemFire Cache Region Indexes. --- .../data/gemfire/CacheFactoryBean.java | 25 ------ .../data/gemfire/IndexTypeConverter.java | 49 ++---------- .../data/gemfire/config/CacheParser.java | 7 ++ ...rRegistrationBeanFactoryPostProcessor.java | 64 +++++++++++++++ .../data/gemfire/config/IndexParser.java | 19 +++-- .../gemfire/config/spring-gemfire-1.6.xsd | 20 ++--- .../data/gemfire/IndexTypeConverterTest.java | 4 +- ...istrationBeanFactoryPostProcessorTest.java | 79 +++++++++++++++++++ .../gemfire/config/IndexNamespaceTest.java | 55 +++++++------ .../data/gemfire/config/index-ns.xml | 13 ++- 10 files changed, 222 insertions(+), 113 deletions(-) create mode 100644 src/main/java/org/springframework/data/gemfire/config/CustomEditorRegistrationBeanFactoryPostProcessor.java create mode 100644 src/test/java/org/springframework/data/gemfire/config/CustomEditorRegistrationBeanFactoryPostProcessorTest.java diff --git a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java index 6e735366..a55d3f3f 100644 --- a/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/CacheFactoryBean.java @@ -33,13 +33,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.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.io.Resource; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.gemfire.client.InterestResultPolicyConverter; -import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy; -import org.springframework.data.gemfire.server.SubscriptionEvictionPolicyConverter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; @@ -50,11 +46,7 @@ import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.DynamicRegionFactory; -import com.gemstone.gemfire.cache.EvictionAction; -import com.gemstone.gemfire.cache.ExpirationAction; import com.gemstone.gemfire.cache.GemFireCache; -import com.gemstone.gemfire.cache.InterestPolicy; -import com.gemstone.gemfire.cache.InterestResultPolicy; import com.gemstone.gemfire.cache.TransactionListener; import com.gemstone.gemfire.cache.TransactionWriter; import com.gemstone.gemfire.cache.util.GatewayConflictResolver; @@ -917,22 +909,6 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, return lazyInitialize; } - /* (non-Javadoc) */ - private void initBeanFactory() { - if (getBeanFactory() instanceof ConfigurableBeanFactory) { - ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) getBeanFactory(); - - beanFactory.registerCustomEditor(EvictionAction.class, EvictionActionConverter.class); - beanFactory.registerCustomEditor(EvictionPolicyType.class, EvictionPolicyConverter.class); - beanFactory.registerCustomEditor(ExpirationAction.class, ExpirationActionConverter.class); - beanFactory.registerCustomEditor(IndexMaintenancePolicyType.class, IndexMaintenancePolicyConverter.class); - beanFactory.registerCustomEditor(IndexType.class, IndexTypeConverter.class); - beanFactory.registerCustomEditor(InterestPolicy.class, InterestPolicyConverter.class); - beanFactory.registerCustomEditor(InterestResultPolicy.class, InterestResultPolicyConverter.class); - beanFactory.registerCustomEditor(SubscriptionEvictionPolicy.class, SubscriptionEvictionPolicyConverter.class); - } - } - /* (non-Javadoc) */ protected void postProcessPropertiesBeforeInitialization(Properties gemfireProperties) { if (GemfireUtils.isGemfireVersion8OrAbove()) { @@ -949,7 +925,6 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware, */ @Override public void afterPropertiesSet() throws Exception { - initBeanFactory(); postProcessPropertiesBeforeInitialization(getProperties()); if (!isLazyInitialize()) { diff --git a/src/main/java/org/springframework/data/gemfire/IndexTypeConverter.java b/src/main/java/org/springframework/data/gemfire/IndexTypeConverter.java index aa7ed872..256d4d3f 100644 --- a/src/main/java/org/springframework/data/gemfire/IndexTypeConverter.java +++ b/src/main/java/org/springframework/data/gemfire/IndexTypeConverter.java @@ -16,10 +16,7 @@ package org.springframework.data.gemfire; -import java.beans.PropertyEditorSupport; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.util.Assert; +import org.springframework.data.gemfire.support.AbstractPropertyEditorConverterSupport; import org.springframework.util.StringUtils; /** @@ -27,57 +24,27 @@ import org.springframework.util.StringUtils; * that converts a given String value into a proper IndexType. * * @author John Blum - * @see java.beans.PropertyEditorSupport - * @see org.springframework.core.convert.converter.Converter * @see org.springframework.data.gemfire.IndexType + * @see org.springframework.data.gemfire.support.AbstractPropertyEditorConverterSupport * @since 1.5.2 */ @SuppressWarnings("unused") -public class IndexTypeConverter extends PropertyEditorSupport implements Converter { +public class IndexTypeConverter extends AbstractPropertyEditorConverterSupport { /** - * Asserts that the given String value was successfully converted into a IndexType. + * Converts the given String value into an appropriate IndexType. * - * @param value the String value to convert into an appropriate IndexType. - * @param indexType the converted IndexType. - * @return the IndexType is non-null. - * @throws java.lang.IllegalArgumentException if the IndexType argument was null, indicating that - * the given String value could not be converted into an appropriate IndexType. - * @see org.springframework.data.gemfire.IndexType - */ - private IndexType assertConverted(final String value, final IndexType indexType) { - Assert.notNull(indexType, String.format("Failed to convert String (%1$s) into an IndexType!", value)); - return indexType; - } - - /** - * Converts the given String value into an appropriate IndexType - * - * @param value the String to convert into a corresponding IndexType enumerated value. - * @return an IndexType converted from the given String value. + * @param value the String to convert into an appropriate IndexType enumerated value. + * @return an IndexType converted from the given String. * @throws java.lang.IllegalArgumentException if the given String could not be converted into * an appropriate IndexType enumerated value. - * @see #assertConverted(String, IndexType) + * @see #assertConverted(String, Object, Class) * @see org.springframework.data.gemfire.IndexType#valueOfIgnoreCase(String) * @see org.springframework.util.StringUtils#trimWhitespace(String) */ @Override public IndexType convert(final String value) { - return assertConverted(value, IndexType.valueOfIgnoreCase(StringUtils.trimWhitespace(value))); - } - - /** - * Sets the value of this PropertyEditor as a IndexType enumerated value converted from the given String text. - * - * @param text the String to convert into a corresponding IndexType enumerated value. - * @throws java.lang.IllegalArgumentException if the given String could not be converted into - * an appropriate IndexType enumerated value. - * @see #convert(String) - * @see #setValue(Object) - */ - @Override - public void setAsText(final String text) throws IllegalArgumentException { - setValue(convert(text)); + return assertConverted(value, IndexType.valueOfIgnoreCase(StringUtils.trimWhitespace(value)), IndexType.class); } } diff --git a/src/main/java/org/springframework/data/gemfire/config/CacheParser.java b/src/main/java/org/springframework/data/gemfire/config/CacheParser.java index 87c82a02..5a364d61 100644 --- a/src/main/java/org/springframework/data/gemfire/config/CacheParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/CacheParser.java @@ -54,6 +54,8 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, builder); + registerCustomGemFireBeanFactoryPostProcessors(parserContext); + ParsingUtils.setPropertyValue(element, builder, "cache-xml-location", "cacheXml"); ParsingUtils.setPropertyReference(element, builder, "properties-ref", "properties"); ParsingUtils.setPropertyValue(element, builder, "lazy-init","lazyInitialize"); @@ -111,6 +113,11 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser { parseJndiBindings(element, builder); } + private void registerCustomGemFireBeanFactoryPostProcessors(final ParserContext parserContext) { + BeanDefinitionReaderUtils.registerWithGeneratedName(BeanDefinitionBuilder.genericBeanDefinition( + CustomEditorRegistrationBeanFactoryPostProcessor.class).getBeanDefinition(), parserContext.getRegistry()); + } + private void parsePdxDiskStore(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { ParsingUtils.setPropertyValue(element, builder, "pdx-disk-store", "pdxDiskStoreName"); diff --git a/src/main/java/org/springframework/data/gemfire/config/CustomEditorRegistrationBeanFactoryPostProcessor.java b/src/main/java/org/springframework/data/gemfire/config/CustomEditorRegistrationBeanFactoryPostProcessor.java new file mode 100644 index 00000000..ec364ace --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/CustomEditorRegistrationBeanFactoryPostProcessor.java @@ -0,0 +1,64 @@ +/* + * 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.config; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.data.gemfire.EvictionActionConverter; +import org.springframework.data.gemfire.EvictionPolicyConverter; +import org.springframework.data.gemfire.EvictionPolicyType; +import org.springframework.data.gemfire.ExpirationActionConverter; +import org.springframework.data.gemfire.IndexMaintenancePolicyConverter; +import org.springframework.data.gemfire.IndexMaintenancePolicyType; +import org.springframework.data.gemfire.IndexType; +import org.springframework.data.gemfire.IndexTypeConverter; +import org.springframework.data.gemfire.InterestPolicyConverter; +import org.springframework.data.gemfire.client.InterestResultPolicyConverter; +import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy; +import org.springframework.data.gemfire.server.SubscriptionEvictionPolicyConverter; + +import com.gemstone.gemfire.cache.EvictionAction; +import com.gemstone.gemfire.cache.ExpirationAction; +import com.gemstone.gemfire.cache.InterestPolicy; +import com.gemstone.gemfire.cache.InterestResultPolicy; + +/** + * The CustomEditorRegistrationBeanFactoryPostProcessor class is a Spring BeanFactoryPostProcessor used to register + * custom GemFire JavaBeans PropertyEditors and Spring Converters that are used to perform type conversions between + * String-based configuration meta-data and actual GemFire or SDG defined enumerated types. + * + * @author John Blum + * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor + * @since 1.6.0 + */ +@SuppressWarnings("unused") +public class CustomEditorRegistrationBeanFactoryPostProcessor implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException { + beanFactory.registerCustomEditor(EvictionAction.class, EvictionActionConverter.class); + beanFactory.registerCustomEditor(EvictionPolicyType.class, EvictionPolicyConverter.class); + beanFactory.registerCustomEditor(ExpirationAction.class, ExpirationActionConverter.class); + beanFactory.registerCustomEditor(IndexMaintenancePolicyType.class, IndexMaintenancePolicyConverter.class); + beanFactory.registerCustomEditor(IndexType.class, IndexTypeConverter.class); + beanFactory.registerCustomEditor(InterestPolicy.class, InterestPolicyConverter.class); + beanFactory.registerCustomEditor(InterestResultPolicy.class, InterestResultPolicyConverter.class); + beanFactory.registerCustomEditor(SubscriptionEvictionPolicy.class, SubscriptionEvictionPolicyConverter.class); + } + +} diff --git a/src/main/java/org/springframework/data/gemfire/config/IndexParser.java b/src/main/java/org/springframework/data/gemfire/config/IndexParser.java index 77b36b4e..33e05afe 100644 --- a/src/main/java/org/springframework/data/gemfire/config/IndexParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/IndexParser.java @@ -23,9 +23,14 @@ import org.springframework.data.gemfire.IndexFactoryBean; import org.w3c.dom.Element; /** - * Parser for <index;gt; definitions. + * Namespace parser for <index;gt; bean definitions. * * @author Costin Leau + * @author John Blum + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder + * @see org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser + * @see org.springframework.data.gemfire.IndexFactoryBean + * @since 1.1.0 */ class IndexParser extends AbstractSimpleBeanDefinitionParser { @@ -33,17 +38,15 @@ class IndexParser extends AbstractSimpleBeanDefinitionParser { return IndexFactoryBean.class; } + @Override + protected boolean isEligibleAttribute(String attributeName) { + return (!"cache-ref".equals(attributeName) && super.isEligibleAttribute(attributeName)); + } + @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { ParsingUtils.setPropertyReference(element, builder, "cache-ref", "cache"); super.doParse(element, parserContext, builder); } - @Override - protected boolean isEligibleAttribute(String attributeName) { - if ("cache-ref".equals(attributeName)) { - return false; - } - return super.isEligibleAttribute(attributeName); - } } diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd index e526d9dd..7f1c7ac6 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-1.6.xsd @@ -2321,14 +2321,12 @@ The name of the index bean definition. If property 'name' is not set, it will be ]]> - - - - - - - - + + + + @@ -2346,16 +2344,14 @@ Corresponds to the regionPath parameter in createIndex methods. - + - + + + HASH + + + + @@ -20,8 +28,9 @@ - + - +