From 69f05b9f2618cf14a034a6da6716962bdeef86f6 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 29 Mar 2011 16:23:54 +0300 Subject: [PATCH] SGF-40 --- .../AliasReplacingBeanDefinitionParser.java | 49 +++++++++++++++++++ .../gemfire/config/ClientRegionParser.java | 5 +- .../gemfire/config/LookupRegionParser.java | 5 +- .../data/gemfire/config/ParsingUtils.java | 32 ++++++++++++ .../config/PartitionedRegionParser.java | 5 +- .../config/ReplicatedRegionParser.java | 5 +- .../config/ClientRegionNamespaceTest.java | 5 ++ .../config/ReplicatedRegionNamespaceTest.java | 2 +- 8 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java diff --git a/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java b/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java new file mode 100644 index 00000000..1184a87c --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/AliasReplacingBeanDefinitionParser.java @@ -0,0 +1,49 @@ +/* + * Copyright 2011 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.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Extension class dealing with the attribute clash (name) that triggers the region name to + * be considered a bean alias. Overrides the automatic alias detection and replaces it with its own + * using meta attributes (since the parsing method is final). + * + * @author Costin Leau + */ +abstract class AliasReplacingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected final void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + ParsingUtils.addBeanAliasAsMetadata(element, builder); + + doParseInternal(element, parserContext, builder); + } + + @Override + protected void registerBeanDefinition(BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { + // add the aliases from the metadata + super.registerBeanDefinition(ParsingUtils.replaceBeanAliasAsMetadata(definition), registry); + } + + protected abstract void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder); +} \ No newline at end of file diff --git a/src/main/java/org/springframework/data/gemfire/config/ClientRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/ClientRegionParser.java index 29425cc9..c6b31ef8 100644 --- a/src/main/java/org/springframework/data/gemfire/config/ClientRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/ClientRegionParser.java @@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentMap; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.gemfire.RegionAttributesFactoryBean; import org.springframework.data.gemfire.client.ClientRegionFactoryBean; @@ -43,14 +42,14 @@ import com.gemstone.gemfire.cache.Scope; * * @author Costin Leau */ -class ClientRegionParser extends AbstractSingleBeanDefinitionParser { +class ClientRegionParser extends AliasReplacingBeanDefinitionParser { protected Class getBeanClass(Element element) { return ClientRegionFactoryBean.class; } @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, builder); // set scope diff --git a/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java index 3a091239..d58b8606 100644 --- a/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java @@ -17,7 +17,6 @@ package org.springframework.data.gemfire.config; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.gemfire.RegionLookupFactoryBean; import org.springframework.util.StringUtils; @@ -28,14 +27,14 @@ import org.w3c.dom.Element; * * @author Costin Leau */ -class LookupRegionParser extends AbstractSingleBeanDefinitionParser { +class LookupRegionParser extends AliasReplacingBeanDefinitionParser { protected Class getBeanClass(Element element) { return RegionLookupFactoryBean.class; } @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, builder); ParsingUtils.setPropertyValue(element, builder, "name", "name"); 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 c694068c..e7b2fcd9 100644 --- a/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java +++ b/src/main/java/org/springframework/data/gemfire/config/ParsingUtils.java @@ -18,9 +18,14 @@ package org.springframework.data.gemfire.config; import java.util.List; +import org.springframework.beans.BeanMetadataAttribute; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -35,6 +40,8 @@ import com.gemstone.gemfire.cache.DiskWriteAttributesFactory; */ abstract class ParsingUtils { + private static final String ALIASES_KEY = ParsingUtils.class.getName() + ":aliases"; + static void setPropertyValue(Element element, BeanDefinitionBuilder builder, String attrName, String propertyName) { String attr = element.getAttribute(attrName); if (StringUtils.hasText(attr)) { @@ -49,6 +56,31 @@ abstract class ParsingUtils { } } + /** + * Utility for parsing bean aliases. Normally parsed by AbstractBeanDefinitionParser however due to the attribute clash + * (bean uses 'name' for aliases while region use it to indicate their name), the parser needs to handle this differently by + * storing them as metadata which gets deleted just before registration. + * + * @param element + * @param builder + */ + static void addBeanAliasAsMetadata(Element element, BeanDefinitionBuilder builder) { + String[] aliases = new String[0]; + String name = element.getAttributeNS(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI, AbstractBeanDefinitionParser.NAME_ATTRIBUTE); + + if (StringUtils.hasLength(name)) { + aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); + } + BeanMetadataAttribute attr = new BeanMetadataAttribute(ALIASES_KEY, aliases); + attr.setSource(element); + builder.getRawBeanDefinition().addMetadataAttribute(attr); + } + + static BeanDefinitionHolder replaceBeanAliasAsMetadata(BeanDefinitionHolder holder) { + BeanDefinition beanDefinition = holder.getBeanDefinition(); + return new BeanDefinitionHolder(beanDefinition, holder.getBeanName(), (String[]) beanDefinition.removeAttribute(ALIASES_KEY)); + } + /** * Utility method handling parsing of nested definition of the type: *
diff --git a/src/main/java/org/springframework/data/gemfire/config/PartitionedRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/PartitionedRegionParser.java
index c7c1e43c..39567fc5 100644
--- a/src/main/java/org/springframework/data/gemfire/config/PartitionedRegionParser.java
+++ b/src/main/java/org/springframework/data/gemfire/config/PartitionedRegionParser.java
@@ -20,7 +20,6 @@ import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.data.gemfire.PartitionAttributesFactoryBean;
 import org.springframework.data.gemfire.RegionAttributesFactoryBean;
@@ -40,14 +39,14 @@ import com.gemstone.gemfire.cache.Region;
  * 
  * @author Costin Leau
  */
-class PartitionedRegionParser extends AbstractSingleBeanDefinitionParser {
+class PartitionedRegionParser extends AliasReplacingBeanDefinitionParser {
 
 	protected Class getBeanClass(Element element) {
 		return RegionFactoryBean.class;
 	}
 
 	@Override
-	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+	protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
 		super.doParse(element, builder);
 
 		// set the data policy
diff --git a/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java
index 023ecd48..8caea003 100644
--- a/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java
+++ b/src/main/java/org/springframework/data/gemfire/config/ReplicatedRegionParser.java
@@ -19,7 +19,6 @@ package org.springframework.data.gemfire.config;
 import java.util.List;
 
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.data.gemfire.RegionAttributesFactoryBean;
 import org.springframework.data.gemfire.RegionFactoryBean;
@@ -35,14 +34,14 @@ import com.gemstone.gemfire.cache.Scope;
  * 
  * @author Costin Leau
  */
-class ReplicatedRegionParser extends AbstractSingleBeanDefinitionParser {
+class ReplicatedRegionParser extends AliasReplacingBeanDefinitionParser {
 
 	protected Class getBeanClass(Element element) {
 		return RegionFactoryBean.class;
 	}
 
 	@Override
-	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+	protected void doParseInternal(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
 		super.doParse(element, builder);
 
 		// set the data policy
diff --git a/src/test/java/org/springframework/data/gemfire/config/ClientRegionNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/ClientRegionNamespaceTest.java
index 9cf69c1e..307c3fd6 100644
--- a/src/test/java/org/springframework/data/gemfire/config/ClientRegionNamespaceTest.java
+++ b/src/test/java/org/springframework/data/gemfire/config/ClientRegionNamespaceTest.java
@@ -61,6 +61,11 @@ public class ClientRegionNamespaceTest {
 		assertTrue(context.containsBean("simple"));
 	}
 
+	@Test
+	public void testBeanNames() throws Exception {
+		assertTrue(ObjectUtils.isEmpty(context.getAliases("publisher")));
+	}
+
 	@Test
 	public void testPublishingClient() throws Exception {
 		assertTrue(context.containsBean("empty"));
diff --git a/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java
index 464c48b9..c8aa6794 100644
--- a/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java
+++ b/src/test/java/org/springframework/data/gemfire/config/ReplicatedRegionNamespaceTest.java
@@ -85,6 +85,6 @@ public class ReplicatedRegionNamespaceTest {
 		assertTrue(context.containsBean("lookup"));
 		RegionLookupFactoryBean lfb = context.getBean("&lookup", RegionLookupFactoryBean.class);
 		assertEquals("existing", TestUtils.readField("name", lfb));
-		assertEquals(context.getBean("existing"), context.getBean("lookup"));
+		assertEquals(existing, context.getBean("lookup"));
 	}
 }
\ No newline at end of file