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.support;
018:
019: import java.io.Serializable;
020:
021: import org.springframework.core.Constants;
022: import org.springframework.transaction.TransactionDefinition;
023:
024: /**
025: * Default implementation of the TransactionDefinition interface,
026: * offering bean-style configuration and sensible default values
027: * (PROPAGATION_REQUIRED, ISOLATION_DEFAULT, TIMEOUT_DEFAULT, readOnly=false).
028: *
029: * <p>Base class for both TransactionTemplate and DefaultTransactionAttribute.
030: *
031: * @author Juergen Hoeller
032: * @since 08.05.2003
033: * @see org.springframework.transaction.support.TransactionTemplate
034: * @see org.springframework.transaction.interceptor.DefaultTransactionAttribute
035: */
036: public class DefaultTransactionDefinition implements
037: TransactionDefinition, Serializable {
038:
039: /** Prefix for the propagation constants defined in TransactionDefinition */
040: public static final String PREFIX_PROPAGATION = "PROPAGATION_";
041:
042: /** Prefix for the isolation constants defined in TransactionDefinition */
043: public static final String PREFIX_ISOLATION = "ISOLATION_";
044:
045: /** Prefix for transaction timeout values in description strings */
046: public static final String PREFIX_TIMEOUT = "timeout_";
047:
048: /** Marker for read-only transactions in description strings */
049: public static final String READ_ONLY_MARKER = "readOnly";
050:
051: /** Constants instance for TransactionDefinition */
052: private static final Constants constants = new Constants(
053: TransactionDefinition.class);
054:
055: private int propagationBehavior = PROPAGATION_REQUIRED;
056:
057: private int isolationLevel = ISOLATION_DEFAULT;
058:
059: private int timeout = TIMEOUT_DEFAULT;
060:
061: private boolean readOnly = false;
062:
063: private String name;
064:
065: /**
066: * Create a new DefaultTransactionDefinition, with default settings.
067: * Can be modified through bean property setters.
068: * @see #setPropagationBehavior
069: * @see #setIsolationLevel
070: * @see #setTimeout
071: * @see #setReadOnly
072: * @see #setName
073: */
074: public DefaultTransactionDefinition() {
075: }
076:
077: /**
078: * Copy constructor. Definition can be modified through bean property setters.
079: * @see #setPropagationBehavior
080: * @see #setIsolationLevel
081: * @see #setTimeout
082: * @see #setReadOnly
083: * @see #setName
084: */
085: public DefaultTransactionDefinition(TransactionDefinition other) {
086: this .propagationBehavior = other.getPropagationBehavior();
087: this .isolationLevel = other.getIsolationLevel();
088: this .timeout = other.getTimeout();
089: this .readOnly = other.isReadOnly();
090: this .name = other.getName();
091: }
092:
093: /**
094: * Create a new DefaultTransactionDefinition with the the given
095: * propagation behavior. Can be modified through bean property setters.
096: * @param propagationBehavior one of the propagation constants in the
097: * TransactionDefinition interface
098: * @see #setIsolationLevel
099: * @see #setTimeout
100: * @see #setReadOnly
101: */
102: public DefaultTransactionDefinition(int propagationBehavior) {
103: this .propagationBehavior = propagationBehavior;
104: }
105:
106: /**
107: * Set the propagation behavior by the name of the corresponding constant in
108: * TransactionDefinition, e.g. "PROPAGATION_REQUIRED".
109: * @param constantName name of the constant
110: * @exception IllegalArgumentException if the supplied value is not resolvable
111: * to one of the <code>PROPAGATION_</code> constants or is <code>null</code>
112: * @see #setPropagationBehavior
113: * @see #PROPAGATION_REQUIRED
114: */
115: public final void setPropagationBehaviorName(String constantName)
116: throws IllegalArgumentException {
117: if (constantName == null
118: || !constantName.startsWith(PREFIX_PROPAGATION)) {
119: throw new IllegalArgumentException(
120: "Only propagation constants allowed");
121: }
122: setPropagationBehavior(constants.asNumber(constantName)
123: .intValue());
124: }
125:
126: /**
127: * Set the propagation behavior. Must be one of the propagation constants
128: * in the TransactionDefinition interface. Default is PROPAGATION_REQUIRED.
129: * @exception IllegalArgumentException if the supplied value is not
130: * one of the <code>PROPAGATION_</code> constants
131: * @see #PROPAGATION_REQUIRED
132: */
133: public final void setPropagationBehavior(int propagationBehavior) {
134: if (!constants.getValues(PREFIX_PROPAGATION).contains(
135: new Integer(propagationBehavior))) {
136: throw new IllegalArgumentException(
137: "Only values of propagation constants allowed");
138: }
139: this .propagationBehavior = propagationBehavior;
140: }
141:
142: public final int getPropagationBehavior() {
143: return this .propagationBehavior;
144: }
145:
146: /**
147: * Set the isolation level by the name of the corresponding constant in
148: * TransactionDefinition, e.g. "ISOLATION_DEFAULT".
149: * @param constantName name of the constant
150: * @exception IllegalArgumentException if the supplied value is not resolvable
151: * to one of the <code>ISOLATION_</code> constants or is <code>null</code>
152: * @see #setIsolationLevel
153: * @see #ISOLATION_DEFAULT
154: */
155: public final void setIsolationLevelName(String constantName)
156: throws IllegalArgumentException {
157: if (constantName == null
158: || !constantName.startsWith(PREFIX_ISOLATION)) {
159: throw new IllegalArgumentException(
160: "Only isolation constants allowed");
161: }
162: setIsolationLevel(constants.asNumber(constantName).intValue());
163: }
164:
165: /**
166: * Set the isolation level. Must be one of the isolation constants
167: * in the TransactionDefinition interface. Default is ISOLATION_DEFAULT.
168: * @exception IllegalArgumentException if the supplied value is not
169: * one of the <code>ISOLATION_</code> constants
170: * @see #ISOLATION_DEFAULT
171: */
172: public final void setIsolationLevel(int isolationLevel) {
173: if (!constants.getValues(PREFIX_ISOLATION).contains(
174: new Integer(isolationLevel))) {
175: throw new IllegalArgumentException(
176: "Only values of isolation constants allowed");
177: }
178: this .isolationLevel = isolationLevel;
179: }
180:
181: public final int getIsolationLevel() {
182: return this .isolationLevel;
183: }
184:
185: /**
186: * Set the timeout to apply, as number of seconds.
187: * Default is TIMEOUT_DEFAULT (-1).
188: * @see #TIMEOUT_DEFAULT
189: */
190: public final void setTimeout(int timeout) {
191: if (timeout < TIMEOUT_DEFAULT) {
192: throw new IllegalArgumentException(
193: "Timeout must be a positive integer or TIMEOUT_DEFAULT");
194: }
195: this .timeout = timeout;
196: }
197:
198: public final int getTimeout() {
199: return this .timeout;
200: }
201:
202: /**
203: * Set whether to optimize as read-only transaction.
204: * Default is "false".
205: */
206: public final void setReadOnly(boolean readOnly) {
207: this .readOnly = readOnly;
208: }
209:
210: public final boolean isReadOnly() {
211: return this .readOnly;
212: }
213:
214: /**
215: * Set the name of this transaction. Default is none.
216: * <p>This will be used as transaction name to be shown in a
217: * transaction monitor, if applicable (for example, WebLogic's).
218: */
219: public final void setName(String name) {
220: this .name = name;
221: }
222:
223: public final String getName() {
224: return this .name;
225: }
226:
227: /**
228: * This implementation compares the <code>toString()</code> results.
229: * @see #toString()
230: */
231: public boolean equals(Object other) {
232: return (other instanceof TransactionDefinition && toString()
233: .equals(other.toString()));
234: }
235:
236: /**
237: * This implementation returns <code>toString()</code>'s hash code.
238: * @see #toString()
239: */
240: public int hashCode() {
241: return toString().hashCode();
242: }
243:
244: /**
245: * Return an identifying description for this transaction definition.
246: * <p>The format matches the one used by
247: * {@link org.springframework.transaction.interceptor.TransactionAttributeEditor},
248: * to be able to feed <code>toString</code> results into bean properties of type
249: * {@link org.springframework.transaction.interceptor.TransactionAttribute}.
250: * <p>Has to be overridden in subclasses for correct <code>equals</code>
251: * and <code>hashCode</code> behavior. Alternatively, {@link #equals}
252: * and {@link #hashCode} can be overridden themselves.
253: * @see #getDefinitionDescription()
254: * @see org.springframework.transaction.interceptor.TransactionAttributeEditor
255: */
256: public String toString() {
257: return getDefinitionDescription().toString();
258: }
259:
260: /**
261: * Return an identifying description for this transaction definition.
262: * <p>Available to subclasses, for inclusion in their <code>toString()</code> result.
263: */
264: protected final StringBuffer getDefinitionDescription() {
265: StringBuffer desc = new StringBuffer();
266: desc.append(constants.toCode(new Integer(
267: this .propagationBehavior), PREFIX_PROPAGATION));
268: desc.append(',');
269: desc.append(constants.toCode(new Integer(this .isolationLevel),
270: PREFIX_ISOLATION));
271: if (this .timeout != TIMEOUT_DEFAULT) {
272: desc.append(',');
273: desc.append(PREFIX_TIMEOUT + this .timeout);
274: }
275: if (this .readOnly) {
276: desc.append(',');
277: desc.append(READ_ONLY_MARKER);
278: }
279: return desc;
280: }
281:
282: }
|