- /*
- * Copyright 2002-2004 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.transaction.interceptor;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Properties;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- /**
- * Simple implementation of TransactionAttributeSource that
- * allows attributes to be matched by registered name.
- * @author Juergen Hoeller
- * @since 21.08.2003
- * @see #isMatch
- */
- public class NameMatchTransactionAttributeSource implements TransactionAttributeSource {
- protected final Log logger = LogFactory.getLog(getClass());
- private Map nameMap = new HashMap();
- /**
- * Set a name/attribute map, consisting of method names
- * (e.g. "myMethod") and TransactionAttribute instances.
- * @see TransactionAttribute
- */
- public void setNameMap(Map nameMap) {
- this.nameMap = nameMap;
- }
- /**
- * Parses the given properties into a name/attribute map.
- * Expects method names as keys and String attributes definitions as values,
- * parsable into TransactionAttribute instances via TransactionAttributeEditor.
- * @see #setNameMap
- * @see TransactionAttributeEditor
- */
- public void setProperties(Properties transactionAttributes) {
- TransactionAttributeEditor tae = new TransactionAttributeEditor();
- for (Iterator it = transactionAttributes.keySet().iterator(); it.hasNext(); ) {
- String methodName = (String) it.next();
- String value = transactionAttributes.getProperty(methodName);
- tae.setAsText(value);
- TransactionAttribute attr = (TransactionAttribute) tae.getValue();
- addTransactionalMethod(methodName, attr);
- }
- }
- /**
- * Add an attribute for a transactional method.
- * Method names can end with "*" for matching multiple methods.
- * @param methodName the name of the method
- * @param attr attribute associated with the method
- */
- public void addTransactionalMethod(String methodName, TransactionAttribute attr) {
- logger.debug("Adding transactional method [" + methodName + "] with attribute [" + attr + "]");
- this.nameMap.put(methodName, attr);
- }
- public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
- String methodName = method.getName();
- TransactionAttribute attr = (TransactionAttribute) this.nameMap.get(methodName);
- if (attr != null) {
- return attr;
- }
- else {
- // look up most specific name match
- String bestNameMatch = null;
- for (Iterator it = this.nameMap.keySet().iterator(); it.hasNext();) {
- String mappedName = (String) it.next();
- if (isMatch(methodName, mappedName) &&
- (bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
- attr = (TransactionAttribute) this.nameMap.get(mappedName);
- bestNameMatch = mappedName;
- }
- }
- return attr;
- }
- }
- /**
- * Return if the given method name matches the mapped name.
- * The default implementation checks for "xxx*" and "*xxx" matches.
- * Can be overridden in subclasses.
- * @param methodName the method name of the class
- * @param mappedName the name in the descriptor
- * @return if the names match
- */
- protected boolean isMatch(String methodName, String mappedName) {
- return (mappedName.endsWith("*") && methodName.startsWith(mappedName.substring(0, mappedName.length() - 1))) ||
- (mappedName.startsWith("*") && methodName.endsWith(mappedName.substring(1, mappedName.length())));
- }
- }