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 org.springframework.aop.framework.AopConfigException;
  18. /**
  19. * Rule determining whether or not a given exception (and any subclasses) should
  20. * cause a rollback. Multiple such rules can be applied to determine whether a
  21. * transaction should commit or rollback after an exception has been thrown.
  22. * @since 09-Apr-2003
  23. * @version $Id: RollbackRuleAttribute.java,v 1.6 2004/03/18 02:46:05 trisberg Exp $
  24. * @author Rod Johnson
  25. * @see NoRollbackRuleAttribute
  26. */
  27. public class RollbackRuleAttribute {
  28. public static final RollbackRuleAttribute ROLLBACK_ON_RUNTIME_EXCEPTIONS = new RollbackRuleAttribute("java.lang.RuntimeException");
  29. /**
  30. * Could hold exception, resolving classname but would always require FQN.
  31. * This way does multiple string comparisons, but how often do we decide
  32. * whether to roll back a transaction following an exception?
  33. */
  34. private final String exceptionName;
  35. /**
  36. * Preferred way to construct a RollbackRule, matching
  37. * the exception class and subclasses. The exception class must be
  38. * Throwable or a subclass of Throwable.
  39. * @param clazz throwable class
  40. */
  41. public RollbackRuleAttribute(Class clazz) {
  42. if (!Throwable.class.isAssignableFrom(clazz))
  43. throw new AopConfigException("Cannot construct rollback rule from " + clazz + "; " +
  44. "it's not a Throwable");
  45. this.exceptionName = clazz.getName();
  46. }
  47. /**
  48. * Construct a new RollbackRule for the given exception name.
  49. * This can be a substring, with no wildcard support at present.
  50. * A value of "ServletException" would match ServletException and
  51. * subclasses, for example.
  52. * <p><b>NB: </b>Consider carefully how specific the pattern is, and whether
  53. * to include package information (which isn't mandatory). For example,
  54. * "Exception" will match nearly anything, and will probably hide other rules.
  55. * "java.lang.Exception" would be correct if "Exception" was meant to define
  56. * a rule for all checked exceptions. With more unusual Exception
  57. * names such as "BaseBusinessException" there's no need to use a FQN.
  58. * @param exceptionName the exception pattern
  59. */
  60. public RollbackRuleAttribute(String exceptionName) {
  61. this.exceptionName = exceptionName;
  62. }
  63. /**
  64. * Return the pattern for the exception name.
  65. */
  66. public String getExceptionName() {
  67. return exceptionName;
  68. }
  69. /**
  70. * Return the depth to the superclass matching.
  71. * 0 means t matches. Return -1 if there's no match.
  72. * Otherwise, return depth. Lowest depth wins.
  73. */
  74. public int getDepth(Throwable t) {
  75. return getDepth(t.getClass(), 0);
  76. }
  77. private int getDepth(Class exceptionClass, int depth) {
  78. if (exceptionClass.getName().indexOf(this.exceptionName) != -1) {
  79. // Found it!
  80. return depth;
  81. }
  82. // If we've gone as far as we can go and haven't found it...
  83. if (exceptionClass.equals(Throwable.class)) {
  84. return -1;
  85. }
  86. return getDepth(exceptionClass.getSuperclass(), depth + 1);
  87. }
  88. public String toString() {
  89. return "RollbackRule with pattern '" + this.exceptionName + "'";
  90. }
  91. }