#region License
/*
* Copyright 2002-2005 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
#region Imports
using System;
using System.Collections;
using System.Reflection;
using Spring.Collections;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework{
/// <summary>
/// Utility methods used by the AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopUtils
{
// This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations.
private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy";
private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy";
/// <summary>
/// Is the supplied <paramref name="objectType"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given type is either a composition-based or a decorator-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is an AOP proxy type.</returns>
public static bool IsAopProxyType(Type objectType)
{
return IsCompositionAopProxyType(objectType) || IsDecoratorAopProxyType(objectType);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given object is either
/// a composition-based proxy or a decorator-based proxy.
/// </remarks>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an AOP proxy.
/// </returns>
public static bool IsAopProxy(object instance)
{
return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a composition-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an composition-based AOP proxy.
/// </returns>
public static bool IsCompositionAopProxy(Object instance)
{
return ((instance != null) && IsCompositionAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsCompositionAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a decorator-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an decorator-based AOP proxy.
/// </returns>
public static bool IsDecoratorAopProxy(Object instance)
{
return ((instance != null) && IsDecoratorAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsDecoratorAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME));
}
/// <summary>
/// Gets all of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements.
/// </summary>
/// <remarks>
/// <p>
/// This includes interfaces implemented by any superclasses.
/// </p>
/// </remarks>
/// <param name="instance">
/// The object to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements; or an empty
/// array if the supplied <paramref name="instance"/> is
/// <see langword="null"/>.
/// </returns>
public static Type[] GetAllInterfaces(object instance)
{
if (instance != null)
{
Type type = instance.GetType();
return GetAllInterfacesFromType(type);
}
return Type.EmptyTypes;
}
/// <summary>
/// Gets all of the interfaces that the
/// supplied <see cref="System.Type"/> implements.
/// </summary>
/// <remarks>
/// This includes interfaces implemented by any superclasses.
/// </remarks>
/// <param name="type">
/// The type to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the supplied <see cref="System.Type"/> implements.
/// </returns>
public static Type[] GetAllInterfacesFromType(Type type)
{
AssertUtils.ArgumentNotNull(type, "type");
ISet interfaces = new HybridSet();
do
{
Type[] ifcs = type.GetInterfaces();
foreach (Type ifc in ifcs)
{
interfaces.Add(ifc);
}
type = type.BaseType;
} while (type != null);
if (interfaces.Count > 0)
{
Type[] types = new Type[interfaces.Count];
interfaces.CopyTo(types, 0);
return types;
}
return Type.EmptyTypes;
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
return CanApply(pointcut, targetType, proxyInterfaces, false);
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
return false;
}
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
MethodInfo[] methods = targetType.GetMethods();
for (int i = 0; i < methods.Length; ++i)
{
MethodInfo m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null
&& !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces))
{
continue;
}
if (pointcut.MethodMatcher.Matches(m, targetType))
{
return true;
}
}
return false;
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
{
return CanApply(advisor, targetType, proxyInterfaces, false);
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (advisor is IIntroductionAdvisor)
{
return ((IIntroductionAdvisor)advisor).TypeFilter.Matches(targetType);
}
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor)advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces, hasIntroductions);
}
// no pointcut specified so assume it applies...
return true;
}
#region Constructor (s) / Destructor
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="AopUtils"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
private AopUtils()
{
}
// CLOVER:ON
#endregion
/// <summary>
/// Gets the type of the target.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <returns></returns>
public static Type GetTargetType(object candidate)
{
AssertUtils.ArgumentNotNull(candidate, "candidate", "Candidate object must not be null");
if (candidate is ITargetSource)
{
return ((ITargetSource)candidate).TargetType;
}
if (candidate is IAdvised)
{
return ((IAdvised)candidate).TargetSource.TargetType;
}
if (IsDecoratorAopProxy(candidate))
{
return candidate.GetType().BaseType;
}
return candidate.GetType();
}
}
}
|