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 */ 017package org.apache.camel.spring.handler; 018 019import org.w3c.dom.Attr; 020import org.w3c.dom.Element; 021import org.w3c.dom.NamedNodeMap; 022import org.w3c.dom.Node; 023import org.w3c.dom.NodeList; 024 025import org.apache.camel.spring.CamelRedeliveryPolicyFactoryBean; 026import org.apache.camel.spring.ErrorHandlerType; 027import org.apache.camel.util.ObjectHelper; 028import org.springframework.beans.factory.config.BeanDefinition; 029import org.springframework.beans.factory.support.BeanDefinitionBuilder; 030import org.springframework.beans.factory.xml.ParserContext; 031import org.springframework.util.Assert; 032import org.springframework.util.StringUtils; 033 034/** 035 * The DefinitionParser to deal with the ErrorHandler 036 */ 037public class ErrorHandlerDefinitionParser extends BeanDefinitionParser { 038 protected BeanDefinitionParser redeliveryPolicyParser 039 = new RedeliveryPolicyDefinitionParser(CamelRedeliveryPolicyFactoryBean.class); 040 041 public ErrorHandlerDefinitionParser() { 042 // need to override the default 043 super(null, false); 044 } 045 046 @Override 047 protected Class<?> getBeanClass(Element element) { 048 ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler; 049 050 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) { 051 type = ErrorHandlerType.valueOf(element.getAttribute("type")); 052 } 053 return type.getTypeAsClass(); 054 } 055 056 @Override 057 protected boolean isEligibleAttribute(String attributeName) { 058 if (attributeName == null || ID_ATTRIBUTE.equals(attributeName)) { 059 return false; 060 } 061 if (attributeName.equals("xmlns") || attributeName.startsWith("xmlns:")) { 062 return false; 063 } 064 // CHECKSTYLE:OFF 065 return !attributeName.equals("type") 066 && !attributeName.equals("onRedeliveryRef") 067 && !attributeName.equals("onRetryWhileRef") 068 && !attributeName.equals("onPrepareFailureRef") 069 && !attributeName.equals("onExceptionOccurredRef") 070 && !attributeName.equals("redeliveryPolicyRef") 071 && !attributeName.equals("transactionTemplateRef") 072 && !attributeName.equals("transactionManagerRef"); 073 // CHECKSTYLE:ON 074 } 075 076 @Override 077 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { 078 super.doParse(element, parserContext, builder); 079 080 String id = element.getAttribute("id"); 081 082 ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler; 083 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) { 084 type = ErrorHandlerType.valueOf(element.getAttribute("type")); 085 } 086 if (type.equals(ErrorHandlerType.DefaultErrorHandler) 087 || type.equals(ErrorHandlerType.DeadLetterChannel) 088 || type.equals(ErrorHandlerType.TransactionErrorHandler)) { 089 NodeList list = element.getChildNodes(); 090 int size = list.getLength(); 091 for (int i = 0; i < size; i++) { 092 Node child = list.item(i); 093 if (child instanceof Element) { 094 Element childElement = (Element) child; 095 String localName = child.getLocalName(); 096 // set the redeliveryPolicy 097 if (localName.equals("redeliveryPolicy")) { 098 // cannot have redeliveryPolicyRef attribute as well, only one is allowed 099 if (ObjectHelper.isNotEmpty(element.getAttribute("redeliveryPolicyRef"))) { 100 throw new IllegalArgumentException( 101 "Cannot set both redeliveryPolicyRef and redeliveryPolicy," 102 + " only one allowed, in error handler with id: " + id); 103 } 104 BeanDefinition redeliveryPolicyDefinition = redeliveryPolicyParser.parse(childElement, parserContext); 105 builder.addPropertyValue(localName, redeliveryPolicyDefinition); 106 } 107 } 108 } 109 parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder); 110 parserRefAttribute(element, "onRetryWhileRef", "onRetryWhile", builder); 111 parserRefAttribute(element, "onPrepareFailureRef", "onPrepareFailure", builder); 112 parserRefAttribute(element, "onExceptionOccurredRef", "onExceptionOccurred", builder); 113 parserRefAttribute(element, "redeliveryPolicyRef", "redeliveryPolicy", builder); 114 if (type.equals(ErrorHandlerType.TransactionErrorHandler)) { 115 parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder); 116 parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder); 117 } 118 } 119 120 // validate attributes according to type 121 122 String deadLetterUri = element.getAttribute("deadLetterUri"); 123 if (ObjectHelper.isNotEmpty(deadLetterUri) && !type.equals(ErrorHandlerType.DeadLetterChannel)) { 124 throw new IllegalArgumentException( 125 "Attribute deadLetterUri can only be used if type is " 126 + ErrorHandlerType.DeadLetterChannel.name() + ", in error handler with id: " 127 + id); 128 } 129 String deadLetterHandleNewException = element.getAttribute("deadLetterHandleNewException"); 130 if (ObjectHelper.isNotEmpty(deadLetterHandleNewException) && !type.equals(ErrorHandlerType.DeadLetterChannel)) { 131 throw new IllegalArgumentException( 132 "Attribute deadLetterHandleNewException can only be used if type is " 133 + ErrorHandlerType.DeadLetterChannel.name() + ", in error handler with id: " 134 + id); 135 } 136 String transactionTemplateRef = element.getAttribute("transactionTemplateRef"); 137 if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) { 138 throw new IllegalArgumentException( 139 "Attribute transactionTemplateRef can only be used if type is " 140 + ErrorHandlerType.TransactionErrorHandler.name() 141 + ", in error handler with id: " + id); 142 } 143 String transactionManagerRef = element.getAttribute("transactionManagerRef"); 144 if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) { 145 throw new IllegalArgumentException( 146 "Attribute transactionManagerRef can only be used if type is " 147 + ErrorHandlerType.TransactionErrorHandler.name() 148 + ", in error handler with id: " + id); 149 } 150 String rollbackLoggingLevel = element.getAttribute("rollbackLoggingLevel"); 151 if (ObjectHelper.isNotEmpty(rollbackLoggingLevel) && (!type.equals(ErrorHandlerType.TransactionErrorHandler))) { 152 throw new IllegalArgumentException( 153 "Attribute rollbackLoggingLevel can only be used if type is " 154 + ErrorHandlerType.TransactionErrorHandler.name() 155 + ", in error handler with id: " + id); 156 } 157 String useOriginalMessage = element.getAttribute("useOriginalMessage"); 158 if (ObjectHelper.isNotEmpty(useOriginalMessage) && type.equals(ErrorHandlerType.NoErrorHandler)) { 159 throw new IllegalArgumentException( 160 "Attribute useOriginalMessage is not supported by error handler type: " 161 + type.name() + ", in error handler with id: " + id); 162 } 163 String useOriginalBody = element.getAttribute("useOriginalBody"); 164 if (ObjectHelper.isNotEmpty(useOriginalBody) && type.equals(ErrorHandlerType.NoErrorHandler)) { 165 throw new IllegalArgumentException( 166 "Attribute useOriginalBody is not supported by error handler type: " 167 + type.name() + ", in error handler with id: " + id); 168 } 169 String onRedeliveryRef = element.getAttribute("onRedeliveryRef"); 170 if (ObjectHelper.isNotEmpty(onRedeliveryRef) && type.equals(ErrorHandlerType.NoErrorHandler)) { 171 throw new IllegalArgumentException( 172 "Attribute onRedeliveryRef is not supported by error handler type: " 173 + type.name() + ", in error handler with id: " + id); 174 } 175 String onExceptionOccurredRef = element.getAttribute("onExceptionOccurredRef"); 176 if (ObjectHelper.isNotEmpty(onExceptionOccurredRef) && type.equals(ErrorHandlerType.NoErrorHandler)) { 177 throw new IllegalArgumentException( 178 "Attribute onExceptionOccurredRef is not supported by error handler type: " 179 + type.name() + ", in error handler with id: " + id); 180 } 181 String onPrepareFailureRef = element.getAttribute("onPrepareFailureRef"); 182 if (ObjectHelper.isNotEmpty(onPrepareFailureRef) && (type.equals(ErrorHandlerType.TransactionErrorHandler) 183 || type.equals(ErrorHandlerType.NoErrorHandler))) { 184 throw new IllegalArgumentException( 185 "Attribute onPrepareFailureRef is not supported by error handler type: " 186 + type.name() + ", in error handler with id: " + id); 187 } 188 String retryWhileRef = element.getAttribute("retryWhileRef"); 189 if (ObjectHelper.isNotEmpty(retryWhileRef) && type.equals(ErrorHandlerType.NoErrorHandler)) { 190 throw new IllegalArgumentException( 191 "Attribute retryWhileRef is not supported by error handler type: " 192 + type.name() + ", in error handler with id: " + id); 193 } 194 String redeliveryPolicyRef = element.getAttribute("redeliveryPolicyRef"); 195 if (ObjectHelper.isNotEmpty(redeliveryPolicyRef) && type.equals(ErrorHandlerType.NoErrorHandler)) { 196 throw new IllegalArgumentException( 197 "Attribute redeliveryPolicyRef is not supported by error handler type: " 198 + type.name() + ", in error handler with id: " + id); 199 } 200 String executorServiceRef = element.getAttribute("executorServiceRef"); 201 if (ObjectHelper.isNotEmpty(executorServiceRef) && type.equals(ErrorHandlerType.NoErrorHandler)) { 202 throw new IllegalArgumentException( 203 "Attribute executorServiceRef is not supported by error handler type: " 204 + type.name() + ", in error handler with id: " + id); 205 } 206 } 207 208 private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) { 209 NamedNodeMap attributes = element.getAttributes(); 210 for (int x = 0; x < attributes.getLength(); x++) { 211 Attr attribute = (Attr) attributes.item(x); 212 String name = attribute.getLocalName(); 213 if (name.equals(attributeName)) { 214 Assert.state(StringUtils.hasText(propertyName), 215 "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty."); 216 builder.addPropertyReference(propertyName, attribute.getValue()); 217 } 218 } 219 } 220 221 protected class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser { 222 223 public RedeliveryPolicyDefinitionParser(Class<?> type) { 224 super(type, false); 225 } 226 227 @Override 228 protected boolean shouldGenerateId() { 229 return true; 230 } 231 } 232 233}