1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.transaction.interceptor;
  17. import java.util.ArrayList;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import java.util.TreeSet;
  21. import org.apache.commons.logging.Log;
  22. import org.apache.commons.logging.LogFactory;
  23. /**
  24. * TransactionAttribute implementation that works out whether a
  25. * given exception should cause transaction rollback by applying
  26. * a number of rollback rules, both positive and negative.
  27. * If no rules are relevant to the exception, it behaves
  28. * like DefaultTransactionAttribute (rolling back on
  29. * runtime exceptions).
  30. * <br>
  31. * The TransactionAttributeEditor property editor creates objects
  32. * of this class.
  33. * @since 09-Apr-2003
  34. * @version $Id: RuleBasedTransactionAttribute.java,v 1.3 2004/03/18 02:46:05 trisberg Exp $
  35. * @author Rod Johnson
  36. */
  37. public class RuleBasedTransactionAttribute extends DefaultTransactionAttribute {
  38. protected final Log logger = LogFactory.getLog(getClass());
  39. private List rollbackRules;
  40. public RuleBasedTransactionAttribute() {
  41. this.rollbackRules = new ArrayList();
  42. }
  43. public RuleBasedTransactionAttribute(int propagationBehavior, List rollbackRules) {
  44. super(propagationBehavior);
  45. this.rollbackRules = rollbackRules;
  46. }
  47. public void setRollbackRules(List rollbackRules) {
  48. this.rollbackRules = rollbackRules;
  49. }
  50. public List getRollbackRules() {
  51. return rollbackRules;
  52. }
  53. /**
  54. * Winning rule is the shallowest rule (that is, the closest
  55. * in the inheritance hierarchy to the exception). If no rule applies (-1),
  56. * return false.
  57. * @see org.springframework.transaction.interceptor.TransactionAttribute#rollbackOn(java.lang.Throwable)
  58. */
  59. public boolean rollbackOn(Throwable t) {
  60. logger.debug("Applying rules to determine whether transaction should rollback on " + t);
  61. RollbackRuleAttribute winner = null;
  62. int deepest = Integer.MAX_VALUE;
  63. if (this.rollbackRules != null) {
  64. for (Iterator it = this.rollbackRules.iterator(); it.hasNext();) {
  65. RollbackRuleAttribute rule = (RollbackRuleAttribute) it.next();
  66. int depth = rule.getDepth(t);
  67. if (depth >= 0 && depth < deepest) {
  68. deepest = depth;
  69. winner = rule;
  70. }
  71. }
  72. }
  73. logger.debug("Winning rollback rule is: " + winner);
  74. // User superclass behaviour (rollback on unchecked)
  75. // if no rule matches
  76. if (winner == null) {
  77. logger.debug("No relevant rollback rule found: applying superclass default");
  78. return super.rollbackOn(t);
  79. }
  80. return !(winner instanceof NoRollbackRuleAttribute);
  81. }
  82. public String toString() {
  83. StringBuffer result = getDefinitionDescription();
  84. TreeSet rules = new TreeSet();
  85. for (Iterator it = rollbackRules.iterator(); it.hasNext();) {
  86. RollbackRuleAttribute rule = (RollbackRuleAttribute) it.next();
  87. String sign = (rule instanceof NoRollbackRuleAttribute) ? COMMIT_RULE_PREFIX : ROLLBACK_RULE_PREFIX;
  88. rules.add(sign + rule.getExceptionName());
  89. }
  90. for (Iterator it = rules.iterator(); it.hasNext();) {
  91. result.append(',');
  92. result.append(it.next());
  93. }
  94. return result.toString();
  95. }
  96. }