001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.spring.handler;
018    
019    import org.w3c.dom.Attr;
020    import org.w3c.dom.Element;
021    import org.w3c.dom.NamedNodeMap;
022    import org.w3c.dom.Node;
023    import org.w3c.dom.NodeList;
024    
025    import org.apache.camel.processor.RedeliveryPolicy;
026    import org.apache.camel.spring.ErrorHandlerType;
027    import org.apache.camel.util.ObjectHelper;
028    
029    import org.springframework.beans.factory.config.BeanDefinition;
030    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
031    import org.springframework.beans.factory.xml.ParserContext;
032    import org.springframework.util.Assert;
033    import org.springframework.util.StringUtils;
034    
035    /**
036     * The DefinitionParser to deal with the ErrorHandler
037     */
038    public class ErrorHandlerDefinitionParser extends BeanDefinitionParser {
039        protected BeanDefinitionParser redeliveryPolicyParser = new RedeliveryPolicyDefinitionParser(RedeliveryPolicy.class);
040        
041        public ErrorHandlerDefinitionParser() {
042            // need to override the default
043            super(null);
044        }
045    
046        protected Class getBeanClass(Element element) {
047            ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;
048    
049            if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
050                type = ErrorHandlerType.valueOf(element.getAttribute("type"));
051            }
052            return type.getTypeAsClass();
053        }
054        
055        protected boolean isEligibleAttribute(String attributeName) {
056            if (attributeName == null || ID_ATTRIBUTE.equals(attributeName)) {
057                return false;
058            }
059            return !attributeName.equals("xmlns") && !attributeName.startsWith("xmlns:")
060                    && !attributeName.equals("type") && !attributeName.equals("onRedeliveryRef")
061                    && !attributeName.equals("transactionTemplateRef") 
062                    && !attributeName.equals("transactionManagerRef");
063        }
064    
065        @Override
066        protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
067            super.doParse(element, parserContext, builder);
068            ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;
069            if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
070                type = ErrorHandlerType.valueOf(element.getAttribute("type"));
071            }
072            if (type.equals(ErrorHandlerType.NoErrorHandler) || type.equals(ErrorHandlerType.LoggingErrorHandler)) {
073                // don't need to parser other stuff
074                return;
075            }
076            if (type.equals(ErrorHandlerType.DefaultErrorHandler) 
077                || type.equals(ErrorHandlerType.DeadLetterChannel) 
078                || type.equals(ErrorHandlerType.TransactionErrorHandler)) {
079                NodeList list = element.getChildNodes();
080                int size = list.getLength();
081                for (int i = 0; i < size; i++) {
082                    Node child = list.item(i);
083                    if (child instanceof Element) {
084                        Element childElement = (Element)child;
085                        String localName = child.getLocalName();
086                        // set the redeliveryPolicy
087                        if (localName.equals("redeliveryPolicy")) {
088                            BeanDefinition redeliveryPolicyDefinition = redeliveryPolicyParser.parse(childElement, parserContext);
089                            builder.addPropertyValue(localName, redeliveryPolicyDefinition);
090                        }
091                    }
092                }
093                // deal with onRedeliveryRef
094                parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder);
095            }
096            if (type.equals(ErrorHandlerType.TransactionErrorHandler)) {
097                // deal with transactionTemplateRef
098                parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder);
099                parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder);
100            }
101        }
102    
103        private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) {
104            NamedNodeMap attributes = element.getAttributes();
105            for (int x = 0; x < attributes.getLength(); x++) {
106                Attr attribute = (Attr) attributes.item(x);
107                String name = attribute.getLocalName();
108                if (name.equals(attributeName)) {
109                    Assert.state(StringUtils.hasText(propertyName),
110                            "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty.");
111                    builder.addPropertyReference(propertyName, attribute.getValue());
112                }
113            }
114        }
115        
116        protected class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser {
117            public RedeliveryPolicyDefinitionParser(Class type) {
118                super(type);
119            }
120    
121            protected boolean shouldGenerateId() {
122                return true;
123            }
124        }
125        
126    }