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 import org.springframework.beans.factory.config.BeanDefinition;
029 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
030 import org.springframework.beans.factory.xml.ParserContext;
031 import org.springframework.util.Assert;
032 import org.springframework.util.StringUtils;
033
034 /**
035 * The DefinitionParser to deal with the ErrorHandler
036 */
037 public class ErrorHandlerDefinitionParser extends BeanDefinitionParser {
038 protected BeanDefinitionParser redeliveryPolicyParser = new RedeliveryPolicyDefinitionParser(RedeliveryPolicy.class);
039
040 public ErrorHandlerDefinitionParser() {
041 // need to override the default
042 super(null, false);
043 }
044
045 protected Class getBeanClass(Element element) {
046 ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;
047
048 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
049 type = ErrorHandlerType.valueOf(element.getAttribute("type"));
050 }
051 return type.getTypeAsClass();
052 }
053
054 protected boolean isEligibleAttribute(String attributeName) {
055 if (attributeName == null || ID_ATTRIBUTE.equals(attributeName)) {
056 return false;
057 }
058 if (attributeName.equals("xmlns") || attributeName.startsWith("xmlns:")) {
059 return false;
060 }
061 return !attributeName.equals("type")
062 && !attributeName.equals("onRedeliveryRef")
063 && !attributeName.equals("onRetryWhileRef")
064 && !attributeName.equals("redeliveryPolicyRef")
065 && !attributeName.equals("transactionTemplateRef")
066 && !attributeName.equals("transactionManagerRef");
067 }
068
069 @Override
070 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
071 super.doParse(element, parserContext, builder);
072
073 String id = element.getAttribute("id");
074
075 ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;
076 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
077 type = ErrorHandlerType.valueOf(element.getAttribute("type"));
078 }
079 if (type.equals(ErrorHandlerType.DefaultErrorHandler)
080 || type.equals(ErrorHandlerType.DeadLetterChannel)
081 || type.equals(ErrorHandlerType.TransactionErrorHandler)) {
082 NodeList list = element.getChildNodes();
083 int size = list.getLength();
084 for (int i = 0; i < size; i++) {
085 Node child = list.item(i);
086 if (child instanceof Element) {
087 Element childElement = (Element)child;
088 String localName = child.getLocalName();
089 // set the redeliveryPolicy
090 if (localName.equals("redeliveryPolicy")) {
091 // cannot have redeliveryPolicyRef attribute as well, only one is allowed
092 if (ObjectHelper.isNotEmpty(element.getAttribute("redeliveryPolicyRef"))) {
093 throw new IllegalArgumentException("Cannot set both redeliveryPolicyRef and redeliveryPolicy,"
094 + " only one allowed, in error handler with id: " + id);
095 }
096 BeanDefinition redeliveryPolicyDefinition = redeliveryPolicyParser.parse(childElement, parserContext);
097 builder.addPropertyValue(localName, redeliveryPolicyDefinition);
098 }
099 }
100 }
101 parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder);
102 parserRefAttribute(element, "onRetryWhileRef", "onRetryWhile", builder);
103 parserRefAttribute(element, "redeliveryPolicyRef", "redeliveryPolicy", builder);
104 if (type.equals(ErrorHandlerType.TransactionErrorHandler)) {
105 // deal with transactionTemplateRef
106 parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder);
107 parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder);
108 }
109 }
110
111 // validate attributes according to type
112
113 String deadLetterUri = element.getAttribute("deadLetterUri");
114 if (ObjectHelper.isNotEmpty(deadLetterUri) && !type.equals(ErrorHandlerType.DeadLetterChannel)) {
115 throw new IllegalArgumentException("Attribute deadLetterUri can only be used if type is "
116 + ErrorHandlerType.DeadLetterChannel.name() + ", in error handler with id: " + id);
117 }
118 String transactionTemplateRef = element.getAttribute("transactionTemplateRef");
119 if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
120 throw new IllegalArgumentException("Attribute transactionTemplateRef can only be used if type is "
121 + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
122 }
123 String transactionManagerRef = element.getAttribute("transactionManagerRef");
124 if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
125 throw new IllegalArgumentException("Attribute transactionManagerRef can only be used if type is "
126 + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
127 }
128 String useOriginalMessage = element.getAttribute("useOriginalMessage");
129 if (ObjectHelper.isNotEmpty(useOriginalMessage) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
130 throw new IllegalArgumentException("Attribute useOriginalMessage is not supported by error handler type: "
131 + type.name() + ", in error handler with id: " + id);
132 }
133 String onRedeliveryRef = element.getAttribute("onRedeliveryRef");
134 if (ObjectHelper.isNotEmpty(onRedeliveryRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
135 throw new IllegalArgumentException("Attribute onRedeliveryRef is not supported by error handler type: "
136 + type.name() + ", in error handler with id: " + id);
137 }
138 String retryWhileRef = element.getAttribute("retryWhileRef");
139 if (ObjectHelper.isNotEmpty(retryWhileRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
140 throw new IllegalArgumentException("Attribute retryWhileRef is not supported by error handler type: "
141 + type.name() + ", in error handler with id: " + id);
142 }
143 String redeliveryPolicyRef = element.getAttribute("redeliveryPolicyRef");
144 if (ObjectHelper.isNotEmpty(redeliveryPolicyRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
145 throw new IllegalArgumentException("Attribute redeliveryPolicyRef is not supported by error handler type: "
146 + type.name() + ", in error handler with id: " + id);
147 }
148 }
149
150 private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) {
151 NamedNodeMap attributes = element.getAttributes();
152 for (int x = 0; x < attributes.getLength(); x++) {
153 Attr attribute = (Attr) attributes.item(x);
154 String name = attribute.getLocalName();
155 if (name.equals(attributeName)) {
156 Assert.state(StringUtils.hasText(propertyName),
157 "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty.");
158 builder.addPropertyReference(propertyName, attribute.getValue());
159 }
160 }
161 }
162
163 protected class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser {
164
165 public RedeliveryPolicyDefinitionParser(Class type) {
166 super(type, false);
167 }
168
169 protected boolean shouldGenerateId() {
170 return true;
171 }
172 }
173
174 }