/* * Copyright 2002-2014 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.integration.config.xml; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandler; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.IntegrationRegistrar; import org.springframework.util.StringUtils; /** * Base class for NamespaceHandlers that registers a BeanFactoryPostProcessor * for configuring default bean definitions. * * @author Mark Fisher * @author Oleg Zhurakousky * @author Gary Russell * @author Artem Bilan */ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHandler { protected final Log logger = LogFactory.getLog(this.getClass()); private static final String VERSION = "5.0"; private final NamespaceHandlerDelegate delegate = new NamespaceHandlerDelegate(); @Override public final BeanDefinition parse(Element element, ParserContext parserContext) { this.verifySchemaVersion(element, parserContext); IntegrationRegistrar integrationRegistrar = new IntegrationRegistrar(); integrationRegistrar.setBeanClassLoader(parserContext.getReaderContext().getBeanClassLoader()); integrationRegistrar.registerBeanDefinitions(null, parserContext.getRegistry()); return this.delegate.parse(element, parserContext); } @Override public final BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext) { return this.delegate.decorate(source, definition, parserContext); } protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator decorator) { this.delegate.doRegisterBeanDefinitionDecorator(elementName, decorator); } protected final void registerBeanDefinitionDecoratorForAttribute(String attributeName, BeanDefinitionDecorator decorator) { this.delegate.doRegisterBeanDefinitionDecoratorForAttribute(attributeName, decorator); } protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { this.delegate.doRegisterBeanDefinitionParser(elementName, parser); } private void verifySchemaVersion(Element element, ParserContext parserContext) { if (!(matchesVersion(element) && matchesVersion(element.getOwnerDocument().getDocumentElement()))) { parserContext.getReaderContext().error( "You cannot use prior versions of Spring Integration schemas with Spring Integration " + VERSION + ". Please upgrade your schema declarations or use versionless aliases (e.g. spring-integration.xsd).", element); } } private static boolean matchesVersion(Element element) { String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); return !StringUtils.hasText(schemaLocation) // no namespace on this element || schemaLocation.matches("(?m).*spring-integration-[a-z-]*" + VERSION + ".xsd.*") // correct version || schemaLocation.matches("(?m).*spring-integration[a-z-]*.xsd.*") // version-less schema || !schemaLocation.matches("(?m).*spring-integration.*"); // no spring-integration schemas } private class NamespaceHandlerDelegate extends NamespaceHandlerSupport { NamespaceHandlerDelegate() { super(); } @Override public void init() { AbstractIntegrationNamespaceHandler.this.init(); } private void doRegisterBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator decorator) { super.registerBeanDefinitionDecorator(elementName, decorator); } private void doRegisterBeanDefinitionDecoratorForAttribute(String attributeName, BeanDefinitionDecorator decorator) { super.registerBeanDefinitionDecoratorForAttribute(attributeName, decorator); } private void doRegisterBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { super.registerBeanDefinitionParser(elementName, parser); } } }