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.spring.CamelRedeliveryPolicyFactoryBean;
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(CamelRedeliveryPolicyFactoryBean.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 parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder);
106 parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder);
107 }
108 }
109
110 // validate attributes according to type
111
112 String deadLetterUri = element.getAttribute("deadLetterUri");
113 if (ObjectHelper.isNotEmpty(deadLetterUri) && !type.equals(ErrorHandlerType.DeadLetterChannel)) {
114 throw new IllegalArgumentException("Attribute deadLetterUri can only be used if type is "
115 + ErrorHandlerType.DeadLetterChannel.name() + ", in error handler with id: " + id);
116 }
117 String transactionTemplateRef = element.getAttribute("transactionTemplateRef");
118 if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
119 throw new IllegalArgumentException("Attribute transactionTemplateRef can only be used if type is "
120 + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
121 }
122 String transactionManagerRef = element.getAttribute("transactionManagerRef");
123 if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
124 throw new IllegalArgumentException("Attribute transactionManagerRef can only be used if type is "
125 + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
126 }
127 String rollbackLoggingLevel = element.getAttribute("rollbackLoggingLevel");
128 if (ObjectHelper.isNotEmpty(rollbackLoggingLevel) && (!type.equals(ErrorHandlerType.TransactionErrorHandler))) {
129 throw new IllegalArgumentException("Attribute rollbackLoggingLevel can only be used if type is "
130 + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
131 }
132 String useOriginalMessage = element.getAttribute("useOriginalMessage");
133 if (ObjectHelper.isNotEmpty(useOriginalMessage) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
134 throw new IllegalArgumentException("Attribute useOriginalMessage is not supported by error handler type: "
135 + type.name() + ", in error handler with id: " + id);
136 }
137 String onRedeliveryRef = element.getAttribute("onRedeliveryRef");
138 if (ObjectHelper.isNotEmpty(onRedeliveryRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
139 throw new IllegalArgumentException("Attribute onRedeliveryRef is not supported by error handler type: "
140 + type.name() + ", in error handler with id: " + id);
141 }
142 String retryWhileRef = element.getAttribute("retryWhileRef");
143 if (ObjectHelper.isNotEmpty(retryWhileRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
144 throw new IllegalArgumentException("Attribute retryWhileRef is not supported by error handler type: "
145 + type.name() + ", in error handler with id: " + id);
146 }
147 String redeliveryPolicyRef = element.getAttribute("redeliveryPolicyRef");
148 if (ObjectHelper.isNotEmpty(redeliveryPolicyRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
149 throw new IllegalArgumentException("Attribute redeliveryPolicyRef is not supported by error handler type: "
150 + type.name() + ", in error handler with id: " + id);
151 }
152 String executorServiceRef = element.getAttribute("executorServiceRef");
153 if (ObjectHelper.isNotEmpty(executorServiceRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
154 throw new IllegalArgumentException("Attribute executorServiceRef is not supported by error handler type: "
155 + type.name() + ", in error handler with id: " + id);
156 }
157 String logName = element.getAttribute("logName");
158 if (ObjectHelper.isNotEmpty(logName) && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
159 throw new IllegalArgumentException("Attribute logName is not supported by error handler type: "
160 + type.name() + ", in error handler with id: " + id);
161 }
162 String level = element.getAttribute("level");
163 if (ObjectHelper.isNotEmpty(level) && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
164 throw new IllegalArgumentException("Attribute level is not supported by error handler type: "
165 + type.name() + ", in error handler with id: " + id);
166 }
167 }
168
169 private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) {
170 NamedNodeMap attributes = element.getAttributes();
171 for (int x = 0; x < attributes.getLength(); x++) {
172 Attr attribute = (Attr) attributes.item(x);
173 String name = attribute.getLocalName();
174 if (name.equals(attributeName)) {
175 Assert.state(StringUtils.hasText(propertyName),
176 "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty.");
177 builder.addPropertyReference(propertyName, attribute.getValue());
178 }
179 }
180 }
181
182 protected class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser {
183
184 public RedeliveryPolicyDefinitionParser(Class<?> type) {
185 super(type, false);
186 }
187
188 protected boolean shouldGenerateId() {
189 return true;
190 }
191 }
192
193 }