AbstractFallbackTransactionAttributeSource.cs :  » Inversion-of-Control-Dependency-Injection » Spring.net » Spring » Transaction » Interceptor » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Inversion of Control Dependency Injection » Spring.net 
Spring.net » Spring » Transaction » Interceptor » AbstractFallbackTransactionAttributeSource.cs
#region License

/*
 * 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.
 */

#endregion

using System;
using System.Collections;
using System.Reflection;

using Spring.Collections;
using Spring.Util;
using Spring.Core;

namespace Spring.Transaction.Interceptor{
  /// <summary>
  /// Abstract implementation of
  /// <see cref="Spring.Transaction.Interceptor.ITransactionAttributeSource"/>
  /// that caches attributes for methods, and implements a default fallback policy.
  /// </summary>
  /// <remarks>
  /// <p>
  /// The default fallback policy applied by this class is:
  /// <list type="numbered">
  /// <item>
  /// <description>most specific method</description>
  /// </item>
  /// <item>
  /// <description>target class attribute</description>
  /// </item>
  /// <item>
  /// <description>declaring method</description>
  /// </item>
  /// <item>
  /// <description>declaring class</description>
  /// </item>
  /// </list>
  /// </p>
  /// <p>
  /// Defaults to using class's transaction attribute if none is associated
  /// with the target method. Any transaction attribute associated with the
  /// target method completely overrides a class transaction attribute.
  /// </p>
  /// <p>
  /// This implementation caches attributes by method after they are first used.
  /// If it's ever desirable to allow dynamic changing of transaction attributes
  /// (unlikely) caching could be made configurable. Caching is desirable because
  /// of the cost of evaluating rollback rules.
  /// </p>
  /// </remarks>
  /// <author>Rod Johnson</author>
  /// <author>Griffin Caprio (.NET)</author>
  /// <author>Mark Pollack (.NET)</author>
  public abstract class AbstractFallbackTransactionAttributeSource : ITransactionAttributeSource
  {
    /// <summary>
    /// Canonical value held in cache to indicate no transaction attibute was found
    /// for this method, and we don't need to look again.
    /// </summary>
    private static readonly object NULL_TX_ATTIBUTE = new object();

    /// <summary>
    /// Cache of <see cref="ITransactionAttribute"/>s, keyed by method and target class.
    /// </summary>
    private readonly IDictionary _transactionAttibuteCache = new Hashtable();

    /// <summary>
    /// Creates a new instance of the
    /// <see cref="Spring.Transaction.Interceptor.AbstractFallbackTransactionAttributeSource"/>
    /// class.
    /// </summary>
    /// <remarks>
    /// <p>
    /// This is an <see langword="abstract"/> class, and as such exposes no public constructors.
    /// </p>
    /// </remarks>
    protected AbstractFallbackTransactionAttributeSource()
    {
    }

    #region Protected Abstract Methods

    /// <summary>
    /// Subclasses should implement this to return all attributes for this method.
    /// May return null.
    /// </summary>
    /// <remarks>
    /// We need all because of the need to analyze rollback rules.
    /// </remarks>
    /// <param name="method">The method to retrieve attributes for.</param>
    /// <returns>The transactional attributes associated with the method.</returns>
    protected abstract Attribute[] FindAllAttributes(MethodInfo method);

    /// <summary>
    /// Subclasses should implement this to return all attributes for this class.
    /// May return null.
    /// </summary>
    /// <param name="targetType">
    /// The <see cref="System.Type"/> to retrieve attributes for.
    /// </param>
    /// <returns>
    /// All attributes associated with the supplied <paramref name="targetType"/>.
    /// </returns>
    protected abstract Attribute[] FindAllAttributes(Type targetType);

    #endregion

    #region ITransactionAttributeSource Members

    /// <summary>
    /// Return the transaction attribute for this method invocation.
    /// </summary>
    /// <remarks>
    /// Defaults to the class's transaction attribute if no method
    /// attribute is found
    /// </remarks>
    /// <param name="method">method for the current invocation. Can't be null</param>
    /// <param name="targetType">target class for this invocation. May be null.</param>
    /// <returns><see cref="ITransactionAttribute"/> for this method, or null if the method is non-transactional</returns>
    public ITransactionAttribute ReturnTransactionAttribute(MethodInfo method, Type targetType)
    {
      object cacheKey = getCacheKey(method, targetType);

        lock (_transactionAttibuteCache)
            {
                object cached = _transactionAttibuteCache[cacheKey];

                if (cached != null)
                {
                    if (NULL_TX_ATTIBUTE == cached)
                    {
                        return null;
                    }
                    {
                        return (ITransactionAttribute)cached;
                    }
                }
                else
                {
                    ITransactionAttribute transactionAttribute = computeTransactionAttribute(method, targetType);
                    if (null == transactionAttribute)
                    {
                        _transactionAttibuteCache.Add(cacheKey, NULL_TX_ATTIBUTE);
                    }
                    else
                    {
                        _transactionAttibuteCache.Add(cacheKey, transactionAttribute);
                    }
                    return transactionAttribute;
                }
            }
    }

    #endregion

    /// <summary>
    /// Return the transaction attribute, given this set of attributes
    /// attached to a method or class. Return null if it's not transactional.  
    /// </summary>
    /// <remarks>
    /// Protected rather than private as subclasses may want to customize
    /// how this is done: for example, returning a
    /// <see cref="Spring.Transaction.Interceptor.ITransactionAttribute"/>
    /// affected by the values of other attributes.
    /// This implementation takes into account
    /// <see cref="Spring.Transaction.Interceptor.RollbackRuleAttribute"/>s, if
    /// the TransactionAttribute is a RuleBasedTransactionAttribute.
    /// </remarks>
    /// <param name="attributes">
    /// Attributes attached to a method or class. May be null, in which case a null
    /// <see cref="Spring.Transaction.Interceptor.ITransactionAttribute"/> will be returned.
    /// </param>
    /// <returns>
    /// The <see cref="ITransactionAttribute"/> configured transaction attribute, or null
    /// if none was found.
    /// </returns>
    protected virtual ITransactionAttribute FindTransactionAttribute(Attribute[] attributes)
    {
      if (null == attributes)
      {
        return null;
      }
      ITransactionAttribute transactionAttribute = null;
      foreach (Attribute currentAttribute in attributes)
      {
        transactionAttribute = currentAttribute as ITransactionAttribute;
        if (null != transactionAttribute)
        {
          break;
        }
      }

      RuleBasedTransactionAttribute ruleBasedTransactionAttribute = transactionAttribute as RuleBasedTransactionAttribute;
      if (null != ruleBasedTransactionAttribute)
      {
        IList rollbackRules = new LinkedList();
        foreach (Attribute currentAttribute in attributes)
        {
          RollbackRuleAttribute rollbackRuleAttribute = currentAttribute as RollbackRuleAttribute;
          if (null != rollbackRuleAttribute)
          {
            rollbackRules.Add(rollbackRuleAttribute);
          }
        }
        ruleBasedTransactionAttribute.RollbackRules = rollbackRules;
        return ruleBasedTransactionAttribute;
      }
      return transactionAttribute;
    }

    #region Private Methods

    private object getCacheKey(MethodBase method, Type targetType)
    {
      return string.Intern(targetType.AssemblyQualifiedName + "." + method);
    }

        private ITransactionAttribute computeTransactionAttribute(MethodInfo method, Type targetType)
        {
            MethodInfo specificMethod;
            if (targetType == null)
            {
                specificMethod = method;
            }
            else
            {
                ParameterInfo[] parameters = method.GetParameters();

                ComposedCriteria searchCriteria = new ComposedCriteria();
                searchCriteria.Add(new MethodNameMatchCriteria(method.Name));
                searchCriteria.Add(new MethodParametersCountCriteria(parameters.Length));
#if NET_2_0
                searchCriteria.Add(new MethodGenericArgumentsCountCriteria(
                    method.GetGenericArguments().Length));
#endif
                searchCriteria.Add(new MethodParametersCriteria(ReflectionUtils.GetParameterTypes(parameters)));

                MemberInfo[] matchingMethods = targetType.FindMembers(
                    MemberTypes.Method,
                    BindingFlags.Instance | BindingFlags.Public,
                    new MemberFilter(new CriteriaMemberFilter().FilterMemberByCriteria),
                    searchCriteria);

                if (matchingMethods != null && matchingMethods.Length == 1)
                {
                    specificMethod = matchingMethods[0] as MethodInfo;
                }
                else
                {
                    specificMethod = method;
                }
            }

            ITransactionAttribute transactionAttribute = getTransactionAttribute(specificMethod);
            if (null != transactionAttribute)
            {
                return transactionAttribute;
            }
            else if (specificMethod != method)
            {
                transactionAttribute = getTransactionAttribute(method);
            }
            return null;
        }

    private ITransactionAttribute getTransactionAttribute(MethodInfo methodInfo)
    {
      ITransactionAttribute transactionAttribute = FindTransactionAttribute(FindAllAttributes(methodInfo));

      if (null != transactionAttribute)
      {
        return transactionAttribute;
      }
      transactionAttribute = FindTransactionAttribute(FindAllAttributes(methodInfo.DeclaringType));
      if (null != transactionAttribute)
      {
        return transactionAttribute;
      }
      return null;
    }

    #endregion
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.