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.xml.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.xml.CamelRedeliveryPolicyFactoryBean; 026import org.apache.camel.spring.xml.SpringErrorHandlerType; 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 SpringErrorHandlerType type = SpringErrorHandlerType.DefaultErrorHandler; 049 050 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) { 051 type = SpringErrorHandlerType.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 SpringErrorHandlerType type = SpringErrorHandlerType.DefaultErrorHandler; 083 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) { 084 type = SpringErrorHandlerType.valueOf(element.getAttribute("type")); 085 } 086 if (type.equals(SpringErrorHandlerType.DefaultErrorHandler) 087 || type.equals(SpringErrorHandlerType.DeadLetterChannel) 088 || type.equals(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.DeadLetterChannel)) { 124 throw new IllegalArgumentException( 125 "Attribute deadLetterUri can only be used if type is " 126 + SpringErrorHandlerType.DeadLetterChannel.name() 127 + ", in error handler with id: " 128 + id); 129 } 130 String deadLetterHandleNewException = element.getAttribute("deadLetterHandleNewException"); 131 if (ObjectHelper.isNotEmpty(deadLetterHandleNewException) && !type.equals(SpringErrorHandlerType.DeadLetterChannel)) { 132 throw new IllegalArgumentException( 133 "Attribute deadLetterHandleNewException can only be used if type is " 134 + SpringErrorHandlerType.DeadLetterChannel.name() 135 + ", in error handler with id: " 136 + id); 137 } 138 String transactionTemplateRef = element.getAttribute("transactionTemplateRef"); 139 if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 140 throw new IllegalArgumentException( 141 "Attribute transactionTemplateRef can only be used if type is " 142 + SpringErrorHandlerType.TransactionErrorHandler.name() 143 + ", in error handler with id: " + id); 144 } 145 String transactionManagerRef = element.getAttribute("transactionManagerRef"); 146 if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 147 throw new IllegalArgumentException( 148 "Attribute transactionManagerRef can only be used if type is " 149 + SpringErrorHandlerType.TransactionErrorHandler.name() 150 + ", in error handler with id: " + id); 151 } 152 String rollbackLoggingLevel = element.getAttribute("rollbackLoggingLevel"); 153 if (ObjectHelper.isNotEmpty(rollbackLoggingLevel) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 154 throw new IllegalArgumentException( 155 "Attribute rollbackLoggingLevel can only be used if type is " 156 + SpringErrorHandlerType.TransactionErrorHandler.name() 157 + ", in error handler with id: " + id); 158 } 159 String useOriginalMessage = element.getAttribute("useOriginalMessage"); 160 if (ObjectHelper.isNotEmpty(useOriginalMessage) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 161 throw new IllegalArgumentException( 162 "Attribute useOriginalMessage is not supported by error handler type: " 163 + type.name() + ", in error handler with id: " + id); 164 } 165 String useOriginalBody = element.getAttribute("useOriginalBody"); 166 if (ObjectHelper.isNotEmpty(useOriginalBody) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 167 throw new IllegalArgumentException( 168 "Attribute useOriginalBody is not supported by error handler type: " 169 + type.name() + ", in error handler with id: " + id); 170 } 171 String onRedeliveryRef = element.getAttribute("onRedeliveryRef"); 172 if (ObjectHelper.isNotEmpty(onRedeliveryRef) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 173 throw new IllegalArgumentException( 174 "Attribute onRedeliveryRef is not supported by error handler type: " 175 + type.name() + ", in error handler with id: " + id); 176 } 177 String onExceptionOccurredRef = element.getAttribute("onExceptionOccurredRef"); 178 if (ObjectHelper.isNotEmpty(onExceptionOccurredRef) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 179 throw new IllegalArgumentException( 180 "Attribute onExceptionOccurredRef is not supported by error handler type: " 181 + type.name() + ", in error handler with id: " + id); 182 } 183 String onPrepareFailureRef = element.getAttribute("onPrepareFailureRef"); 184 if (ObjectHelper.isNotEmpty(onPrepareFailureRef) && (type.equals(SpringErrorHandlerType.TransactionErrorHandler) 185 || type.equals(SpringErrorHandlerType.NoErrorHandler))) { 186 throw new IllegalArgumentException( 187 "Attribute onPrepareFailureRef is not supported by error handler type: " 188 + type.name() + ", in error handler with id: " + id); 189 } 190 String retryWhileRef = element.getAttribute("retryWhileRef"); 191 if (ObjectHelper.isNotEmpty(retryWhileRef) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 192 throw new IllegalArgumentException( 193 "Attribute retryWhileRef is not supported by error handler type: " 194 + type.name() + ", in error handler with id: " + id); 195 } 196 String redeliveryPolicyRef = element.getAttribute("redeliveryPolicyRef"); 197 if (ObjectHelper.isNotEmpty(redeliveryPolicyRef) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 198 throw new IllegalArgumentException( 199 "Attribute redeliveryPolicyRef is not supported by error handler type: " 200 + type.name() + ", in error handler with id: " + id); 201 } 202 String executorServiceRef = element.getAttribute("executorServiceRef"); 203 if (ObjectHelper.isNotEmpty(executorServiceRef) && type.equals(SpringErrorHandlerType.NoErrorHandler)) { 204 throw new IllegalArgumentException( 205 "Attribute executorServiceRef is not supported by error handler type: " 206 + type.name() + ", in error handler with id: " + id); 207 } 208 } 209 210 private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) { 211 NamedNodeMap attributes = element.getAttributes(); 212 for (int x = 0; x < attributes.getLength(); x++) { 213 Attr attribute = (Attr) attributes.item(x); 214 String name = attribute.getLocalName(); 215 if (name.equals(attributeName)) { 216 Assert.state(StringUtils.hasText(propertyName), 217 "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty."); 218 builder.addPropertyReference(propertyName, attribute.getValue()); 219 } 220 } 221 } 222 223 protected static class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser { 224 225 public RedeliveryPolicyDefinitionParser(Class<?> type) { 226 super(type, false); 227 } 228 229 @Override 230 protected boolean shouldGenerateId() { 231 return true; 232 } 233 } 234 235}