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 return !attributeName.equals("type") 065 && !attributeName.equals("onRedeliveryRef") 066 && !attributeName.equals("onRetryWhileRef") 067 && !attributeName.equals("onPrepareFailureRef") 068 && !attributeName.equals("onExceptionOccurredRef") 069 && !attributeName.equals("redeliveryPolicyRef") 070 && !attributeName.equals("transactionTemplateRef") 071 && !attributeName.equals("transactionManagerRef"); 072 } 073 074 @Override 075 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { 076 super.doParse(element, parserContext, builder); 077 078 String id = element.getAttribute("id"); 079 080 SpringErrorHandlerType type = SpringErrorHandlerType.DefaultErrorHandler; 081 if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) { 082 type = SpringErrorHandlerType.valueOf(element.getAttribute("type")); 083 } 084 if (type.equals(SpringErrorHandlerType.DefaultErrorHandler) 085 || type.equals(SpringErrorHandlerType.DeadLetterChannel) 086 || type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 087 NodeList list = element.getChildNodes(); 088 int size = list.getLength(); 089 for (int i = 0; i < size; i++) { 090 Node child = list.item(i); 091 if (child instanceof Element) { 092 Element childElement = (Element) child; 093 String localName = child.getLocalName(); 094 // set the redeliveryPolicy 095 if (localName.equals("redeliveryPolicy")) { 096 // cannot have redeliveryPolicyRef attribute as well, only one is allowed 097 if (ObjectHelper.isNotEmpty(element.getAttribute("redeliveryPolicyRef"))) { 098 throw new IllegalArgumentException( 099 "Cannot set both redeliveryPolicyRef and redeliveryPolicy," 100 + " only one allowed, in error handler with id: " + id); 101 } 102 BeanDefinition redeliveryPolicyDefinition = redeliveryPolicyParser.parse(childElement, parserContext); 103 builder.addPropertyValue(localName, redeliveryPolicyDefinition); 104 } 105 } 106 } 107 parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder); 108 parserRefAttribute(element, "onRetryWhileRef", "onRetryWhile", builder); 109 parserRefAttribute(element, "onPrepareFailureRef", "onPrepareFailure", builder); 110 parserRefAttribute(element, "onExceptionOccurredRef", "onExceptionOccurred", builder); 111 parserRefAttribute(element, "redeliveryPolicyRef", "redeliveryPolicy", builder); 112 if (type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 113 parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder); 114 parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder); 115 } 116 } 117 118 // validate attributes according to type 119 120 String deadLetterUri = element.getAttribute("deadLetterUri"); 121 if (ObjectHelper.isNotEmpty(deadLetterUri) && !type.equals(SpringErrorHandlerType.DeadLetterChannel)) { 122 throw new IllegalArgumentException( 123 "Attribute deadLetterUri can only be used if type is " 124 + SpringErrorHandlerType.DeadLetterChannel.name() 125 + ", in error handler with id: " 126 + id); 127 } 128 String deadLetterHandleNewException = element.getAttribute("deadLetterHandleNewException"); 129 if (ObjectHelper.isNotEmpty(deadLetterHandleNewException) && !type.equals(SpringErrorHandlerType.DeadLetterChannel)) { 130 throw new IllegalArgumentException( 131 "Attribute deadLetterHandleNewException can only be used if type is " 132 + SpringErrorHandlerType.DeadLetterChannel.name() 133 + ", in error handler with id: " 134 + id); 135 } 136 String transactionTemplateRef = element.getAttribute("transactionTemplateRef"); 137 if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 138 throw new IllegalArgumentException( 139 "Attribute transactionTemplateRef can only be used if type is " 140 + SpringErrorHandlerType.TransactionErrorHandler.name() 141 + ", in error handler with id: " + id); 142 } 143 String transactionManagerRef = element.getAttribute("transactionManagerRef"); 144 if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 145 throw new IllegalArgumentException( 146 "Attribute transactionManagerRef can only be used if type is " 147 + SpringErrorHandlerType.TransactionErrorHandler.name() 148 + ", in error handler with id: " + id); 149 } 150 String rollbackLoggingLevel = element.getAttribute("rollbackLoggingLevel"); 151 if (ObjectHelper.isNotEmpty(rollbackLoggingLevel) && !type.equals(SpringErrorHandlerType.TransactionErrorHandler)) { 152 throw new IllegalArgumentException( 153 "Attribute rollbackLoggingLevel can only be used if type is " 154 + SpringErrorHandlerType.TransactionErrorHandler.name() 155 + ", in error handler with id: " + id); 156 } 157 String useOriginalMessage = element.getAttribute("useOriginalMessage"); 158 if (ObjectHelper.isNotEmpty(useOriginalMessage) && type.equals(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.TransactionErrorHandler) 183 || type.equals(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.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(SpringErrorHandlerType.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 static 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}