001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.transaction.interceptor;
018:
019: import java.io.Serializable;
020:
021: /**
022: * Rule determining whether or not a given exception (and any subclasses) should
023: * cause a rollback. Multiple such rules can be applied to determine whether a
024: * transaction should commit or rollback after an exception has been thrown.
025: *
026: * @author Rod Johnson
027: * @since 09.04.2003
028: * @see NoRollbackRuleAttribute
029: */
030: public class RollbackRuleAttribute implements Serializable {
031:
032: public static final RollbackRuleAttribute ROLLBACK_ON_RUNTIME_EXCEPTIONS = new RollbackRuleAttribute(
033: RuntimeException.class);
034:
035: /**
036: * Could hold exception, resolving class name but would always require FQN.
037: * This way does multiple string comparisons, but how often do we decide
038: * whether to roll back a transaction following an exception?
039: */
040: private final String exceptionName;
041:
042: /**
043: * Preferred way to construct a RollbackRule, matching the exception class and
044: * subclasses. The exception class must be Throwable or a subclass of Throwable.
045: * @param clazz throwable class
046: */
047: public RollbackRuleAttribute(Class clazz) {
048: if (!Throwable.class.isAssignableFrom(clazz)) {
049: throw new IllegalArgumentException(
050: "Cannot construct rollback rule from ["
051: + clazz.getName()
052: + "]: it's not a Throwable");
053: }
054: this .exceptionName = clazz.getName();
055: }
056:
057: /**
058: * Construct a new RollbackRule for the given exception name.
059: * This can be a substring, with no wildcard support at present.
060: * A value of "ServletException" would match
061: * <code>javax.servlet.ServletException</code> and subclasses, for example.
062: * <p><b>NB:</b> Consider carefully how specific the pattern is, and whether
063: * to include package information (which isn't mandatory). For example,
064: * "Exception" will match nearly anything, and will probably hide other rules.
065: * "java.lang.Exception" would be correct if "Exception" was meant to define
066: * a rule for all checked exceptions. With more unusual exception names such
067: * as "BaseBusinessException" there's no need to use a FQN.
068: * @param exceptionName the exception pattern
069: * (can also be a fully qualified class name)
070: */
071: public RollbackRuleAttribute(String exceptionName) {
072: this .exceptionName = exceptionName;
073: }
074:
075: /**
076: * Return the pattern for the exception name.
077: */
078: public String getExceptionName() {
079: return exceptionName;
080: }
081:
082: /**
083: * Return the depth to the superclass matching.
084: * 0 means ex matches exactly. Returns -1 if there's no match.
085: * Otherwise, returns depth. Lowest depth wins.
086: */
087: public int getDepth(Throwable ex) {
088: return getDepth(ex.getClass(), 0);
089: }
090:
091: private int getDepth(Class exceptionClass, int depth) {
092: if (exceptionClass.getName().indexOf(this .exceptionName) != -1) {
093: // Found it!
094: return depth;
095: }
096: // If we've gone as far as we can go and haven't found it...
097: if (exceptionClass.equals(Throwable.class)) {
098: return -1;
099: }
100: return getDepth(exceptionClass.getSuperclass(), depth + 1);
101: }
102:
103: public boolean equals(Object other) {
104: if (this == other) {
105: return true;
106: }
107: if (!(other instanceof RollbackRuleAttribute)) {
108: return false;
109: }
110: RollbackRuleAttribute rhs = (RollbackRuleAttribute) other;
111: return this .exceptionName.equals(rhs.exceptionName);
112: }
113:
114: public int hashCode() {
115: return this .exceptionName.hashCode();
116: }
117:
118: public String toString() {
119: return "RollbackRuleAttribute with pattern ["
120: + this .exceptionName + "]";
121: }
122:
123: }
|