1 16 17 package org.springframework.transaction.config; 18 19 import java.util.LinkedList ; 20 import java.util.List ; 21 22 import org.w3c.dom.Element ; 23 24 import org.springframework.beans.factory.config.TypedStringValue; 25 import org.springframework.beans.factory.support.BeanDefinitionBuilder; 26 import org.springframework.beans.factory.support.ManagedMap; 27 import org.springframework.beans.factory.support.RootBeanDefinition; 28 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; 29 import org.springframework.beans.factory.xml.ParserContext; 30 import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; 31 import org.springframework.transaction.interceptor.NoRollbackRuleAttribute; 32 import org.springframework.transaction.interceptor.RollbackRuleAttribute; 33 import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; 34 import org.springframework.transaction.interceptor.TransactionInterceptor; 35 import org.springframework.util.StringUtils; 36 import org.springframework.util.xml.DomUtils; 37 38 47 class TxAdviceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { 48 49 private static final String ATTRIBUTES = "attributes"; 50 51 private static final String TIMEOUT = "timeout"; 52 53 private static final String READ_ONLY = "read-only"; 54 55 private static final String NAME_MAP = "nameMap"; 56 57 private static final String PROPAGATION = "propagation"; 58 59 private static final String ISOLATION = "isolation"; 60 61 private static final String ROLLBACK_FOR = "rollback-for"; 62 63 private static final String NO_ROLLBACK_FOR = "no-rollback-for"; 64 65 66 protected Class getBeanClass(Element element) { 67 return TransactionInterceptor.class; 68 } 69 70 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { 71 builder.addPropertyReference(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY, 73 element.getAttribute(TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE)); 74 75 List txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES); 76 if (txAttributes.size() > 1) { 77 parserContext.getReaderContext().error( 78 "Element <attributes> is allowed at most once inside element <advice>", element); 79 } 80 else if (txAttributes.size() == 1) { 81 Element attributeSourceElement = (Element ) txAttributes.get(0); 83 RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext); 84 builder.addPropertyValue(TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE, attributeSourceDefinition); 85 } 86 else { 87 Class sourceClass = TxNamespaceUtils.getAnnotationTransactionAttributeSourceClass(); 89 builder.addPropertyValue(TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE, new RootBeanDefinition(sourceClass)); 90 } 91 } 92 93 private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) { 94 List methods = DomUtils.getChildElementsByTagName(attrEle, "method"); 95 ManagedMap transactionAttributeMap = new ManagedMap(methods.size()); 96 transactionAttributeMap.setSource(parserContext.extractSource(attrEle)); 97 98 for (int i = 0; i < methods.size(); i++) { 99 Element methodEle = (Element ) methods.get(i); 100 101 String name = methodEle.getAttribute("name"); 102 TypedStringValue nameHolder = new TypedStringValue(name); 103 nameHolder.setSource(parserContext.extractSource(methodEle)); 104 105 RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute(); 106 String propagation = methodEle.getAttribute(PROPAGATION); 107 String isolation = methodEle.getAttribute(ISOLATION); 108 String timeout = methodEle.getAttribute(TIMEOUT); 109 String readOnly = methodEle.getAttribute(READ_ONLY); 110 if (StringUtils.hasText(propagation)) { 111 attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation); 112 } 113 if (StringUtils.hasText(isolation)) { 114 attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation); 115 } 116 if (StringUtils.hasText(timeout)) { 117 try { 118 attribute.setTimeout(Integer.parseInt(timeout)); 119 } 120 catch (NumberFormatException ex) { 121 parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle); 122 } 123 } 124 if (StringUtils.hasText(readOnly)) { 125 attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY)).booleanValue()); 126 } 127 128 List rollbackRules = new LinkedList (); 129 if (methodEle.hasAttribute(ROLLBACK_FOR)) { 130 String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR); 131 addRollbackRuleAttributesTo(rollbackRules,rollbackForValue); 132 } 133 if (methodEle.hasAttribute(NO_ROLLBACK_FOR)) { 134 String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR); 135 addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue); 136 } 137 attribute.setRollbackRules(rollbackRules); 138 139 transactionAttributeMap.put(nameHolder, attribute); 140 } 141 142 RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class); 143 attributeSourceDefinition.setSource(parserContext.extractSource(attrEle)); 144 attributeSourceDefinition.getPropertyValues().addPropertyValue(NAME_MAP, transactionAttributeMap); 145 return attributeSourceDefinition; 146 } 147 148 private void addRollbackRuleAttributesTo(List rollbackRules, String rollbackForValue) { 149 String [] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(rollbackForValue); 150 for (int i = 0; i < exceptionTypeNames.length; i++) { 151 rollbackRules.add(new RollbackRuleAttribute(StringUtils.trimWhitespace(exceptionTypeNames[i]))); 152 } 153 } 154 155 private void addNoRollbackRuleAttributesTo(List rollbackRules, String noRollbackForValue) { 156 String [] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(noRollbackForValue); 157 for (int i = 0; i < exceptionTypeNames.length; i++) { 158 rollbackRules.add(new NoRollbackRuleAttribute(StringUtils.trimWhitespace(exceptionTypeNames[i]))); 159 } 160 } 161 162 } 163 | Popular Tags |