001: /*
002: * Copyright 2002-2007 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.lang.reflect.Method;
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.LinkedList;
023: import java.util.List;
024:
025: import org.springframework.beans.factory.InitializingBean;
026: import org.springframework.metadata.Attributes;
027: import org.springframework.util.Assert;
028: import org.springframework.util.ObjectUtils;
029:
030: /**
031: * Implementation of the {@link TransactionAttributeSource} interface that reads
032: * metadata via Spring's {@link org.springframework.metadata.Attributes} abstraction.
033: *
034: * <p>Typically used for reading in source-level attributes via Commons Attributes.
035: *
036: * @author Rod Johnson
037: * @author Juergen Hoeller
038: * @see org.springframework.metadata.Attributes
039: * @see org.springframework.metadata.commons.CommonsAttributes
040: */
041: public class AttributesTransactionAttributeSource extends
042: AbstractFallbackTransactionAttributeSource implements
043: InitializingBean {
044:
045: /**
046: * Underlying Attributes implementation that we're using.
047: */
048: private Attributes attributes;
049:
050: /**
051: * Create a new AttributesTransactionAttributeSource.
052: * @see #setAttributes
053: */
054: public AttributesTransactionAttributeSource() {
055: }
056:
057: /**
058: * Create a new AttributesTransactionAttributeSource.
059: * @param attributes the Attributes implementation to use
060: * @see org.springframework.metadata.commons.CommonsAttributes
061: */
062: public AttributesTransactionAttributeSource(Attributes attributes) {
063: Assert.notNull(attributes, "Attributes must not be null");
064: this .attributes = attributes;
065: }
066:
067: /**
068: * Set the Attributes implementation to use.
069: * @see org.springframework.metadata.commons.CommonsAttributes
070: */
071: public void setAttributes(Attributes attributes) {
072: this .attributes = attributes;
073: }
074:
075: public void afterPropertiesSet() {
076: Assert.notNull(this .attributes,
077: "Property 'attributes' is required");
078: }
079:
080: protected TransactionAttribute findTransactionAttribute(
081: Method method) {
082: Assert.notNull(this .attributes,
083: "Property 'attributes' is required");
084: return findTransactionAttribute(this .attributes
085: .getAttributes(method));
086: }
087:
088: protected TransactionAttribute findTransactionAttribute(Class clazz) {
089: Assert.notNull(this .attributes,
090: "Property 'attributes' is required");
091: return findTransactionAttribute(this .attributes
092: .getAttributes(clazz));
093: }
094:
095: /**
096: * Return the transaction attribute, given this set of attributes
097: * attached to a method or class.
098: * <p>Protected rather than private as subclasses may want to customize
099: * how this is done: for example, returning a TransactionAttribute
100: * affected by the values of other attributes.
101: * <p>This implementation takes into account RollbackRuleAttributes,
102: * if the TransactionAttribute is a RuleBasedTransactionAttribute.
103: * @param atts attributes attached to a method or class (may be <code>null</code>)
104: * @return TransactionAttribute the corresponding transaction attribute,
105: * or <code>null</code> if none was found
106: */
107: protected TransactionAttribute findTransactionAttribute(
108: Collection atts) {
109: if (atts == null) {
110: return null;
111: }
112:
113: TransactionAttribute txAttribute = null;
114:
115: // Check whether there is a transaction attribute.
116: for (Iterator it = atts.iterator(); it.hasNext()
117: && txAttribute == null;) {
118: Object att = it.next();
119: if (att instanceof TransactionAttribute) {
120: txAttribute = (TransactionAttribute) att;
121: }
122: }
123:
124: // Check if we have a RuleBasedTransactionAttribute.
125: if (txAttribute instanceof RuleBasedTransactionAttribute) {
126: RuleBasedTransactionAttribute rbta = (RuleBasedTransactionAttribute) txAttribute;
127: // We really want value: bit of a hack.
128: List rollbackRules = new LinkedList();
129: for (Iterator it = atts.iterator(); it.hasNext();) {
130: Object att = it.next();
131: if (att instanceof RollbackRuleAttribute) {
132: rollbackRules.add(att);
133: }
134: }
135: // Repeatedly setting this isn't elegant, but it works.
136: rbta.setRollbackRules(rollbackRules);
137: }
138:
139: return txAttribute;
140: }
141:
142: public boolean equals(Object other) {
143: if (this == other) {
144: return true;
145: }
146: if (!(other instanceof AttributesTransactionAttributeSource)) {
147: return false;
148: }
149: AttributesTransactionAttributeSource otherTas = (AttributesTransactionAttributeSource) other;
150: return ObjectUtils.nullSafeEquals(this .attributes,
151: otherTas.attributes);
152: }
153:
154: public int hashCode() {
155: return AttributesTransactionAttributeSource.class.hashCode();
156: }
157:
158: }
|