From a8bedeee388825ae946aec4ae9193afe65f1a9bc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 18 Oct 2010 11:35:31 -0700 Subject: [PATCH] Allow namespace attributes to be expressions and placeholder values --- .../config/xml/IntegrationNamespaceUtils.java | 212 +++++++----------- 1 file changed, 82 insertions(+), 130 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java index e3b8c4b7d1..c3b04ad3bd 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java @@ -1,17 +1,14 @@ /* * Copyright 2002-2010 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. + * + * 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.integration.config.xml; @@ -20,6 +17,7 @@ import java.util.List; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; @@ -47,73 +45,53 @@ public abstract class IntegrationNamespaceUtils { static final String ORDER = "order"; /** - * Configures the provided bean definition builder with a property value - * corresponding to the attribute whose name is provided if that attribute - * is defined in the given element. + * Configures the provided bean definition builder with a property value corresponding to the attribute whose name + * is provided if that attribute is defined in the given element. * - * @param builder - * the bean definition builder to be configured - * @param element - * the XML element where the attribute should be defined - * @param attributeName - * the name of the attribute whose value will be used to populate - * the property - * @param propertyName - * the name of the property to be populated + * @param builder the bean definition builder to be configured + * @param element the XML element where the attribute should be defined + * @param attributeName the name of the attribute whose value will be used to populate the property + * @param propertyName the name of the property to be populated */ - public static void setValueIfAttributeDefined( - BeanDefinitionBuilder builder, Element element, - String attributeName, String propertyName) { + public static void setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element, String attributeName, + String propertyName) { String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { - builder.addPropertyValue(propertyName, attributeValue); + builder.addPropertyValue(propertyName, new TypedStringValue(attributeValue)); } } /** - * Configures the provided bean definition builder with a property value - * corresponding to the attribute whose name is provided if that attribute - * is defined in the given element. + * Configures the provided bean definition builder with a property value corresponding to the attribute whose name + * is provided if that attribute is defined in the given element. * *

- * The property name will be the camel-case equivalent of the lower case - * hyphen separated attribute (e.g. the "foo-bar" attribute would match the - * "fooBar" property). + * The property name will be the camel-case equivalent of the lower case hyphen separated attribute (e.g. the + * "foo-bar" attribute would match the "fooBar" property). * * @see Conventions#attributeNameToPropertyName(String) * - * @param builder - * the bean definition builder to be configured - * @param element - * - the XML element where the attribute should be defined - * @param attributeName - * - the name of the attribute whose value will be set on the - * property + * @param builder the bean definition builder to be configured + * @param element - the XML element where the attribute should be defined + * @param attributeName - the name of the attribute whose value will be set on the property */ - public static void setValueIfAttributeDefined( - BeanDefinitionBuilder builder, Element element, String attributeName) { - setValueIfAttributeDefined(builder, element, attributeName, Conventions - .attributeNameToPropertyName(attributeName)); + public static void setValueIfAttributeDefined(BeanDefinitionBuilder builder, Element element, String attributeName) { + setValueIfAttributeDefined(builder, element, attributeName, + Conventions.attributeNameToPropertyName(attributeName)); } /** - * Configures the provided bean definition builder with a property reference - * to a bean. The bean reference is identified by the value from the - * attribute whose name is provided if that attribute is defined in the - * given element. + * Configures the provided bean definition builder with a property reference to a bean. The bean reference is + * identified by the value from the attribute whose name is provided if that attribute is defined in the given + * element. * - * @param builder - * the bean definition builder to be configured - * @param element - * the XML element where the attribute should be defined - * @param attributeName - * the name of the attribute whose value will be used as a bean - * reference to populate the property - * @param propertyName - * the name of the property to be populated + * @param builder the bean definition builder to be configured + * @param element the XML element where the attribute should be defined + * @param attributeName the name of the attribute whose value will be used as a bean reference to populate the + * property + * @param propertyName the name of the property to be populated */ - public static void setReferenceIfAttributeDefined( - BeanDefinitionBuilder builder, Element element, + public static void setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element, String attributeName, String propertyName) { String attributeValue = element.getAttribute(attributeName); if (StringUtils.hasText(attributeValue)) { @@ -122,38 +100,32 @@ public abstract class IntegrationNamespaceUtils { } /** - * Configures the provided bean definition builder with a property reference - * to a bean. The bean reference is identified by the value from the - * attribute whose name is provided if that attribute is defined in the - * given element. + * Configures the provided bean definition builder with a property reference to a bean. The bean reference is + * identified by the value from the attribute whose name is provided if that attribute is defined in the given + * element. * *

- * The property name will be the camel-case equivalent of the lower case - * hyphen separated attribute (e.g. the "foo-bar" attribute would match the - * "fooBar" property). + * The property name will be the camel-case equivalent of the lower case hyphen separated attribute (e.g. the + * "foo-bar" attribute would match the "fooBar" property). * * @see Conventions#attributeNameToPropertyName(String) * - * @param builder - * the bean definition builder to be configured - * @param element - * - the XML element where the attribute should be defined - * @param attributeName - * - the name of the attribute whose value will be used as a bean - * reference to populate the property + * @param builder the bean definition builder to be configured + * @param element - the XML element where the attribute should be defined + * @param attributeName - the name of the attribute whose value will be used as a bean reference to populate the + * property * * @see Conventions#attributeNameToPropertyName(String) */ - public static void setReferenceIfAttributeDefined( - BeanDefinitionBuilder builder, Element element, String attributeName) { + public static void setReferenceIfAttributeDefined(BeanDefinitionBuilder builder, Element element, + String attributeName) { setReferenceIfAttributeDefined(builder, element, attributeName, Conventions.attributeNameToPropertyName(attributeName)); } /** - * Provides a user friendly description of an element based on its node name - * and, if available, its "id" attribute value. This is useful for creating - * error messages from within bean definition parsers. + * Provides a user friendly description of an element based on its node name and, if available, its "id" attribute + * value. This is useful for creating error messages from within bean definition parsers. */ public static String createElementDescription(Element element) { String elementId = "'" + element.getNodeName() + "'"; @@ -165,70 +137,51 @@ public abstract class IntegrationNamespaceUtils { } /** - * Parse a "poller" element to provide a reference for the target - * BeanDefinitionBuilder. If the poller element does not contain a "ref" - * attribute, this will create and register a PollerMetadata instance and - * then add it as a property reference of the target builder. + * Parse a "poller" element to provide a reference for the target BeanDefinitionBuilder. If the poller element does + * not contain a "ref" attribute, this will create and register a PollerMetadata instance and then add it as a + * property reference of the target builder. * - * @param pollerElement - * the "poller" element to parse - * @param targetBuilder - * the builder that expects the "trigger" property - * @param parserContext - * the parserContext for the target builder + * @param pollerElement the "poller" element to parse + * @param targetBuilder the builder that expects the "trigger" property + * @param parserContext the parserContext for the target builder */ - public static void configurePollerMetadata(Element pollerElement, - BeanDefinitionBuilder targetBuilder, ParserContext parserContext) { + public static void configurePollerMetadata(Element pollerElement, BeanDefinitionBuilder targetBuilder, + ParserContext parserContext) { if (pollerElement.hasAttribute("ref")) { if (pollerElement.getAttributes().getLength() != 1) { - parserContext - .getReaderContext() - .error( - "A 'poller' element that provides a 'ref' must have no other attributes.", - pollerElement); + parserContext.getReaderContext().error( + "A 'poller' element that provides a 'ref' must have no other attributes.", pollerElement); } if (pollerElement.getChildNodes().getLength() != 0) { - parserContext - .getReaderContext() - .error( - "A 'poller' element that provides a 'ref' must have no child elements.", - pollerElement); - } - targetBuilder.addPropertyReference("pollerMetadata", pollerElement - .getAttribute("ref")); - } else { - BeanDefinition beanDefinition = parserContext.getDelegate() - .parseCustomElement(pollerElement, - targetBuilder.getBeanDefinition()); - if (beanDefinition == null) { parserContext.getReaderContext().error( - "BeanDefinition must not be null", pollerElement); + "A 'poller' element that provides a 'ref' must have no child elements.", pollerElement); + } + targetBuilder.addPropertyReference("pollerMetadata", pollerElement.getAttribute("ref")); + } else { + BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(pollerElement, + targetBuilder.getBeanDefinition()); + if (beanDefinition == null) { + parserContext.getReaderContext().error("BeanDefinition must not be null", pollerElement); } targetBuilder.addPropertyValue("pollerMetadata", beanDefinition); } } /** - * Get a text value from a named attribute if it exists, otherwise check for - * a nested element of the same name. If both are specified it is an error, - * but if neither is specified, just returns null. + * Get a text value from a named attribute if it exists, otherwise check for a nested element of the same name. If + * both are specified it is an error, but if neither is specified, just returns null. * - * @param element - * a DOM node - * @param name - * the name of the property (attribute or child element) - * @param parserContext - * the current context + * @param element a DOM node + * @param name the name of the property (attribute or child element) + * @param parserContext the current context * @return the text from the attribite or element or null */ - public static String getTextFromAttributeOrNestedElement(Element element, - String name, ParserContext parserContext) { + public static String getTextFromAttributeOrNestedElement(Element element, String name, ParserContext parserContext) { String attr = element.getAttribute(name); Element childElement = DomUtils.getChildElementByTagName(element, name); if (StringUtils.hasText(attr) && childElement != null) { parserContext.getReaderContext().error( - "Either an attribute or a child element can be specified for " - + name + " but not both", element); + "Either an attribute or a child element can be specified for " + name + " but not both", element); return null; } if (!StringUtils.hasText(attr) && childElement == null) { @@ -237,8 +190,7 @@ public abstract class IntegrationNamespaceUtils { return StringUtils.hasText(attr) ? attr : childElement.getTextContent(); } - public static BeanComponentDefinition parseInnerHandlerDefinition( - Element element, ParserContext parserContext) { + public static BeanComponentDefinition parseInnerHandlerDefinition(Element element, ParserContext parserContext) { // parses out inner bean definition for concrete implementation if // defined List childElements = DomUtils.getChildElementsByTagName(element, "bean"); @@ -254,11 +206,11 @@ public abstract class IntegrationNamespaceUtils { } String ref = element.getAttribute(REF_ATTRIBUTE); - Assert.isTrue(!(StringUtils.hasText(ref) && innerComponentDefinition != null), "Ambiguous definition. Inner bean " + (innerComponentDefinition == null - ? innerComponentDefinition - : innerComponentDefinition.getBeanDefinition().getBeanClassName()) - + " declaration and \"ref\" " + ref - + " are not allowed together."); + Assert.isTrue(!(StringUtils.hasText(ref) && innerComponentDefinition != null), + "Ambiguous definition. Inner bean " + + (innerComponentDefinition == null ? innerComponentDefinition : innerComponentDefinition + .getBeanDefinition().getBeanClassName()) + " declaration and \"ref\" " + ref + + " are not allowed together."); return innerComponentDefinition; } }