This commit is contained in:
Costin Leau
2011-03-29 16:23:54 +03:00
parent 4c43122c33
commit 69f05b9f26
8 changed files with 95 additions and 13 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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");

View File

@@ -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:
* <pre>

View File

@@ -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

View File

@@ -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

View File

@@ -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"));

View File

@@ -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"));
}
}