SPRNET-883 - In Process - Add support for translation of exceptions using PersistenceExceptionTranslationInterceptor
This commit is contained in:
@@ -143,7 +143,7 @@ namespace Spring.Aop.Support
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the interfaces attributes of the method to be included in the search for the
|
||||
/// Is the interfaces attributes of the method to be included in the search for theg
|
||||
/// <see cref="Attribute"/>?
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
|
||||
121
src/Spring/Spring.Aop/Aop/Support/AttributeMatchingPointcut.cs
Normal file
121
src/Spring/Spring.Aop/Aop/Support/AttributeMatchingPointcut.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 Spring.Util;
|
||||
|
||||
namespace Spring.Aop.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Pointcut that looks for a specific attribute being present on a class or
|
||||
/// method.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class AttributeMatchingPointcut : IPointcut
|
||||
{
|
||||
private readonly ITypeFilter typeFilter;
|
||||
private readonly IMethodMatcher methodMatcher;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
|
||||
/// given attribute type.
|
||||
/// </summary>
|
||||
/// <param name="attributeType">Type of the attribute to look for at the class level.</param>
|
||||
public AttributeMatchingPointcut(Type attributeType)
|
||||
{
|
||||
ValidateAttributeTypeArgument(attributeType);
|
||||
this.typeFilter = new AttributeTypeFilter(attributeType);
|
||||
this.methodMatcher = TrueMethodMatcher.True;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
|
||||
/// given attribute type
|
||||
/// </summary>
|
||||
/// <param name="attributeType">Type of the attribute.</param>
|
||||
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
|
||||
public AttributeMatchingPointcut(Type attributeType, bool checkInherited)
|
||||
{
|
||||
ValidateAttributeTypeArgument(attributeType);
|
||||
this.typeFilter = new AttributeTypeFilter(attributeType, checkInherited);
|
||||
this.methodMatcher = TrueMethodMatcher.True;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the given
|
||||
/// attribute type
|
||||
/// </summary>
|
||||
/// <param name="classAttributeType">The attribute type to look for at the class level.</param>
|
||||
/// <param name="methodAttributeType">The attribute type to look for at the method attribute.</param>
|
||||
public AttributeMatchingPointcut(Type classAttributeType, Type methodAttributeType)
|
||||
{
|
||||
AssertUtils.IsTrue(classAttributeType != null || methodAttributeType != null,
|
||||
"Either Type attribute type or Method attribute type needs to be specified (or both)");
|
||||
|
||||
if (classAttributeType != null)
|
||||
{
|
||||
this.typeFilter = new AttributeTypeFilter(classAttributeType);
|
||||
} else
|
||||
{
|
||||
this.typeFilter = TrueTypeFilter.True;
|
||||
}
|
||||
|
||||
if (methodAttributeType != null)
|
||||
{
|
||||
this.methodMatcher = new AttributeMethodMatcher(methodAttributeType);
|
||||
} else
|
||||
{
|
||||
this.methodMatcher = TrueMethodMatcher.True;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
|
||||
/// </summary>
|
||||
/// <value>The current <see cref="Spring.Aop.ITypeFilter"/>.</value>
|
||||
public ITypeFilter TypeFilter
|
||||
{
|
||||
get { return this.typeFilter; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
|
||||
/// </summary>
|
||||
/// <value>The current <see cref="Spring.Aop.IMethodMatcher"/>.</value>
|
||||
public IMethodMatcher MethodMatcher
|
||||
{
|
||||
get { return this.methodMatcher; }
|
||||
}
|
||||
|
||||
private static void ValidateAttributeTypeArgument(Type attributeType)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
|
||||
if (!typeof(Attribute).IsAssignableFrom(attributeType))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format(
|
||||
"The [{0}] Type must be derived from the [System.Attribute] class.",
|
||||
attributeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
src/Spring/Spring.Aop/Aop/Support/AttributeMethodMatcher.cs
Normal file
109
src/Spring/Spring.Aop/Aop/Support/AttributeMethodMatcher.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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.Reflection;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Aop.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// MethodMatcher that looks for a specific attribute being present on the
|
||||
/// method (checking both the method on the onviked interface, if any and the corresponding
|
||||
/// method on the target class
|
||||
/// </summary>
|
||||
/// <author>Juergen hoeller</author>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <seealso cref="AttributeMatchingPointcut"/>
|
||||
public class AttributeMethodMatcher : StaticMethodMatcher
|
||||
{
|
||||
private readonly Type attributeType;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeMethodMatcher"/> class for the
|
||||
/// given atribute type.
|
||||
/// </summary>
|
||||
/// <param name="attributeType">Type of the attribute to look for.</param>
|
||||
public AttributeMethodMatcher(Type attributeType)
|
||||
{
|
||||
ValidateAttributeTypeArgument(attributeType);
|
||||
this.attributeType = attributeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the supplied <paramref name="method"/> satisfy this matcher?
|
||||
/// </summary>
|
||||
/// <param name="method">The candidate method.</param>
|
||||
/// <param name="targetType">The target <see cref="System.Type"/> (may be <see langword="null"/>,
|
||||
/// in which case the candidate <see cref="System.Type"/> must be taken
|
||||
/// to be the <paramref name="method"/>'s declaring class).</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if this this method matches statically.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Must be implemented by a derived class in order to specify matching
|
||||
/// rules.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public override bool Matches(MethodInfo method, Type targetType)
|
||||
{
|
||||
if (method.IsDefined(attributeType, true))
|
||||
{
|
||||
// Checks whether the attribute is defined on the method or a super definition of the method
|
||||
// but does not check attributes on implemented interfaces.
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method);
|
||||
|
||||
// Also check whether the attribute is defined on a method implemented from an interface.
|
||||
// First find all interfaces for the type that contains the method.
|
||||
// Next, check each interface for the presence of the attribute on the corresponding
|
||||
// method from the interface.
|
||||
foreach (Type interfaceType in method.DeclaringType.GetInterfaces())
|
||||
{
|
||||
MethodInfo intfMethod = interfaceType.GetMethod(method.Name, parameterTypes);
|
||||
if (intfMethod != null && intfMethod.IsDefined(attributeType, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateAttributeTypeArgument(Type attributeType)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
|
||||
if (!typeof(Attribute).IsAssignableFrom(attributeType))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format(
|
||||
"The [{0}] Type must be derived from the [System.Attribute] class.",
|
||||
attributeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
111
src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs
Normal file
111
src/Spring/Spring.Aop/Aop/Support/AttributeTypeFilter.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 Spring.Util;
|
||||
|
||||
namespace Spring.Aop.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// ITypeFilter that looks for a specific attribute being present on a class
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class AttributeTypeFilter : ITypeFilter
|
||||
{
|
||||
private readonly Type attributeType;
|
||||
|
||||
private readonly bool checkInherited;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
|
||||
/// given attribute type.
|
||||
/// </summary>
|
||||
/// <param name="attributeType">Type of the attribute to look for.</param>
|
||||
public AttributeTypeFilter(Type attributeType) : this(attributeType, false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
|
||||
/// given attribute type.
|
||||
/// </summary>
|
||||
/// <param name="attributeType">Type of the attribute.</param>
|
||||
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
|
||||
public AttributeTypeFilter(Type attributeType, bool checkInherited)
|
||||
{
|
||||
#region parameter validation
|
||||
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
|
||||
if (!typeof(Attribute).IsAssignableFrom(attributeType))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
string.Format(
|
||||
"The [{0}] Type must be derived from the [System.Attribute] class.",
|
||||
attributeType));
|
||||
}
|
||||
#endregion
|
||||
this.attributeType = attributeType;
|
||||
this.checkInherited = checkInherited;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Should the pointcut apply to the supplied <see cref="System.Type"/>?
|
||||
/// </summary>
|
||||
/// <param name="type">The candidate <see cref="System.Type"/>.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the advice should apply to the supplied
|
||||
/// <paramref name="type"/>
|
||||
/// </returns>
|
||||
public bool Matches(Type type)
|
||||
{
|
||||
if (checkInherited)
|
||||
{
|
||||
return FindAttribute(type, attributeType) != null;
|
||||
} else
|
||||
{
|
||||
return Attribute.GetCustomAttributes(type, attributeType, false) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private Attribute FindAttribute(Type type, Type attribType)
|
||||
{
|
||||
Attribute[] attributes = Attribute.GetCustomAttributes(type, attributeType, false); // we will traverse hierarchy ourselves.
|
||||
if (attributes.Length > 0)
|
||||
{
|
||||
return attributes[0];
|
||||
}
|
||||
foreach (Type interfaceType in type.GetInterfaces())
|
||||
{
|
||||
Attribute attrib = FindAttribute(interfaceType, attribType);
|
||||
if (attrib != null)
|
||||
{
|
||||
return attrib;
|
||||
}
|
||||
}
|
||||
if (type.BaseType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return FindAttribute(type.BaseType, attribType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,12 +281,15 @@
|
||||
<Compile Include="Aop\Support\AbstractRegularExpressionMethodPointcut.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Support\AttributeMatchingPointcut.cs" />
|
||||
<Compile Include="Aop\Support\AttributeMatchMethodPointcut.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Support\AttributeMatchMethodPointcutAdvisor.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Support\AttributeMethodMatcher.cs" />
|
||||
<Compile Include="Aop\Support\AttributeTypeFilter.cs" />
|
||||
<Compile Include="Aop\Support\ComposablePointcut.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -956,6 +956,9 @@
|
||||
<Compile Include="Reflection\Dynamic\DynamicMethod.cs" />
|
||||
<Compile Include="Reflection\Dynamic\DynamicProperty.cs" />
|
||||
<Compile Include="Reflection\Dynamic\DynamicReflectionManager.cs" />
|
||||
<Compile Include="Stereotype\ComponentAttribute.cs" />
|
||||
<Compile Include="Stereotype\RepositoryAttribute.cs" />
|
||||
<Compile Include="Stereotype\ServiceAttribute.cs" />
|
||||
<Compile Include="Threading\CallContextStorage.cs" />
|
||||
<Compile Include="Threading\ISync.cs" />
|
||||
<Compile Include="Threading\IThreadStorage.cs" />
|
||||
|
||||
54
src/Spring/Spring.Core/Stereotype/ComponentAttribute.cs
Normal file
54
src/Spring/Spring.Core/Stereotype/ComponentAttribute.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Stereotype {
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an annotated class is a "component".
|
||||
/// Such classes are considered as candidates for future features such
|
||||
/// as auto-detection when using attribute-based configuration and assembly scanning.
|
||||
/// </summary>
|
||||
/// <remarks>Other class-level annotations may be considered as identifying
|
||||
/// a component as well, typically a special kind of component:
|
||||
/// e.g. the Repository attribute.
|
||||
/// </remarks>
|
||||
/// <author>Mark Fisher</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
/// <seealso cref="RepositoryAttribute"/>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = true)]
|
||||
[Serializable]
|
||||
public class ComponentAttribute : Attribute
|
||||
{
|
||||
private string name = "";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ComponentAttribute"/> class.
|
||||
/// </summary>
|
||||
public ComponentAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ComponentAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the component.</param>
|
||||
public ComponentAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the component
|
||||
/// </summary>
|
||||
/// <value>The name of the component.</value>
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/Spring/Spring.Core/Stereotype/RepositoryAttribute.cs
Normal file
60
src/Spring/Spring.Core/Stereotype/RepositoryAttribute.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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;
|
||||
|
||||
namespace Spring.Stereotype
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that an annotated class is a "Repository" (or "DAO").
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A class with this attribute is eligible for Spring DataAccessException translation. A class
|
||||
/// with the Repository attribute is also clarified as to its role in the overall application
|
||||
/// architecture for the purpose of tools, aspects, etc.
|
||||
/// <para>
|
||||
/// This attribute also serves as a specialization of the ComponentAttribute, allowing implementation
|
||||
/// classes to be autodetected in future releases through assembly scanning.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Jueren Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
/// <seealso cref="ComponentAttribute"/>
|
||||
public class RepositoryAttribute : ComponentAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RepositoryAttribute"/> class.
|
||||
/// </summary>
|
||||
public RepositoryAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RepositoryAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the repository.</param>
|
||||
public RepositoryAttribute(string name) : base(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
54
src/Spring/Spring.Core/Stereotype/ServiceAttribute.cs
Normal file
54
src/Spring/Spring.Core/Stereotype/ServiceAttribute.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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
|
||||
|
||||
namespace Spring.Stereotype
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that an annotated class is a "Service" (e.g. a business service facade).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This attribute also serves as a specialization of the ComponentAttribute, allowing implementation
|
||||
/// classes to be autodetected in future releases through assembly scanning.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class ServiceAttribute : ComponentAttribute
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceAttribute"/> class.
|
||||
/// </summary>
|
||||
public ServiceAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServiceAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
public ServiceAttribute(string name) : base(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 AopAlliance.Aop;
|
||||
using Spring.Aop;
|
||||
using Spring.Aop.Support;
|
||||
using Spring.Dao.Support;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Dao.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Spring AOP exception translation aspect for use at Repository or DAO layer level.
|
||||
/// Translates native persistence exceptions into Spring's DataAccessException hierarchy,
|
||||
/// based on a given PersistenceExceptionTranslator.
|
||||
/// </summary>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class PersistenceExceptionTranslationAdvisor : AbstractPointcutAdvisor
|
||||
{
|
||||
private PersistenceExceptionTranslationInterceptor advice;
|
||||
|
||||
private AttributeMatchingPointcut pointcut;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PersistenceExceptionTranslationAdvisor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="persistenceExceptionTranslator">The persistence exception translator to use.</param>
|
||||
/// <param name="repositoryAttributeType">Type of the repository attribute to check for.</param>
|
||||
public PersistenceExceptionTranslationAdvisor(IPersistenceExceptionTranslator persistenceExceptionTranslator,
|
||||
Type repositoryAttributeType)
|
||||
{
|
||||
this.advice = new PersistenceExceptionTranslationInterceptor(persistenceExceptionTranslator);
|
||||
this.pointcut = new AttributeMatchingPointcut(repositoryAttributeType, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PersistenceExceptionTranslationAdvisor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="objectFactory">The object factory to obtain all IPersistenceExceptionTranslators from.</param>
|
||||
/// <param name="repositoryAttributeType">Type of the repository attribute to check for.</param>
|
||||
public PersistenceExceptionTranslationAdvisor(IListableObjectFactory objectFactory, Type repositoryAttributeType)
|
||||
{
|
||||
this.advice = new PersistenceExceptionTranslationInterceptor(objectFactory);
|
||||
this.pointcut = new AttributeMatchingPointcut(repositoryAttributeType, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the advice part of this aspect.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// An advice may be an interceptor, a throws advice, before advice,
|
||||
/// introduction etc.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The advice that should apply if the pointcut matches.
|
||||
/// </returns>
|
||||
public override IAdvice Advice
|
||||
{
|
||||
get { return this.advice; }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public override IPointcut Pointcut
|
||||
{
|
||||
get { return this.pointcut; }
|
||||
set { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 Spring.Aop.Framework;
|
||||
using Spring.Core;
|
||||
using Spring.Dao;
|
||||
using Spring.Dao.Support;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
using Spring.Stereotype;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Dao.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Object post-processor that automatically applies persistence exception
|
||||
/// translation to any bean that carries the <see cref="RepositoryAttribute"/>
|
||||
/// attribute, adding a corresponding <see cref="PersistenceExceptionTranslationAdvisor"/>
|
||||
/// to the xposed proxy (either an existing AOP proxy or a newly generated
|
||||
/// proxy that implements all of the target's interfaces).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Translates native resource exceptions to Spring's <see cref="DataAccessException"/>
|
||||
/// hierarchy. Autodetects object that implement the <see cref="IPersistenceExceptionTranslator"/>
|
||||
/// interface, which are subsequently asked to translate candidate exceptions.
|
||||
/// </para>
|
||||
/// <para>All of Spring's applicable resource factories implement the
|
||||
/// <code>IPersistenceExceptionTranslator</code> interface out of the box.
|
||||
/// As a consequence, all that is usually needed to enable automatic exception
|
||||
/// translation is marking all affected objects (such as DAOs) with the
|
||||
/// <code>Repository</code> annotation, along with defining this post-processor
|
||||
/// in the application context.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
/// <seealso cref="PersistenceExceptionTranslationAdvisor"/>
|
||||
/// <seealso cref="RepositoryAttribute"/>
|
||||
/// <seealso cref="DataAccessException"/>
|
||||
/// <seealso cref="IPersistenceExceptionTranslator"/>
|
||||
public class PersistenceExceptionTranslationPostProcessor : ProxyConfig, IObjectPostProcessor, IObjectFactoryAware, IOrdered
|
||||
{
|
||||
private Type repositoryAttributeType = typeof(RepositoryAttribute);
|
||||
|
||||
private PersistenceExceptionTranslationAdvisor persistenceExceptionTranslationAdvisor;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the repository attribute. The default required attribute type is the
|
||||
/// <see cref="RepositoryAttribute"/> attirbute. This setter property exists so that developers
|
||||
/// can provide their own (non-Spring-specific) attribute type to indicate that a class has a
|
||||
/// repository role.
|
||||
/// </summary>
|
||||
/// <value>The desitred type of the repository attribute.</value>
|
||||
public Type RepositoryAttributeType
|
||||
{
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(value, "'RepositoryAttributeType' must not be null");
|
||||
repositoryAttributeType = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set
|
||||
{
|
||||
IListableObjectFactory lof = value as IListableObjectFactory;
|
||||
if (lof == null)
|
||||
{
|
||||
throw new ArgumentException("Cannot use PersistenceExceptionTranslator autodetection without IListableObjectFactory");
|
||||
}
|
||||
this.persistenceExceptionTranslationAdvisor =
|
||||
new PersistenceExceptionTranslationAdvisor(lof, this.repositoryAttributeType);
|
||||
}
|
||||
}
|
||||
|
||||
public int Order
|
||||
{
|
||||
get {
|
||||
return Int32.MaxValue;
|
||||
// lowest precidence value
|
||||
// This should run after all other post-processors, so that it can just add
|
||||
// an advisor to existing proxies rather than double-proxy.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Just return the passed in object instance
|
||||
/// </summary>
|
||||
/// <param name="instance">The new object instance.</param>
|
||||
/// <param name="name">The name of the object.</param>
|
||||
/// <returns>
|
||||
/// The passed in object instance
|
||||
/// </returns>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// In case of errors.
|
||||
/// </exception>
|
||||
public object PostProcessBeforeInitialization(object instance, string name)
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add PersistenceExceptionTranslationAdvice to candidate object if it is a match.
|
||||
/// Create AOP proxy if necessary or add advice to existing advice chain.
|
||||
/// </summary>
|
||||
/// <param name="instance">The new object instance.</param>
|
||||
/// <param name="objectName">The name of the object.</param>
|
||||
/// <returns>
|
||||
/// The object instance to use, wrapped with either the original or a wrapped one.
|
||||
/// </returns>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// In case of errors.
|
||||
/// </exception>
|
||||
public object PostProcessAfterInitialization(object instance, string objectName)
|
||||
{
|
||||
IAdvised advised = instance as IAdvised;
|
||||
Type targetType;
|
||||
if (advised != null)
|
||||
{
|
||||
targetType = advised.TargetSource.TargetType;
|
||||
} else
|
||||
{
|
||||
targetType = instance.GetType();
|
||||
}
|
||||
if (targetType == null)
|
||||
{
|
||||
// Can't do much here
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (AopUtils.CanApply(this.persistenceExceptionTranslationAdvisor, targetType, ReflectionUtils.GetInterfaces(targetType)))
|
||||
{
|
||||
if (advised != null)
|
||||
{
|
||||
advised.AddAdvisor(this.persistenceExceptionTranslationAdvisor);
|
||||
return instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProxyFactory proxyFactory = new ProxyFactory(instance);
|
||||
// copy our properties inherited from ProxyConfig
|
||||
proxyFactory.CopyFrom(this);
|
||||
proxyFactory.AddAdvisor(this.persistenceExceptionTranslationAdvisor);
|
||||
return proxyFactory.GetProxy();
|
||||
}
|
||||
} else
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 Spring.Data.Support;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Dao.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of PersistenceExceptionTranslator that supports chaining,
|
||||
/// allowing the addition of PersistenceExceptionTranslator instances in order.
|
||||
/// Returns <code>non-null</code> on the first (if any) match.
|
||||
/// </summary>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class ChainedPersistenceExceptionTranslator : IPersistenceExceptionTranslator
|
||||
{
|
||||
private readonly ArrayList translatorList = new ArrayList(4);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the translator to the translator list.
|
||||
/// </summary>
|
||||
/// <param name="translator">The translator.</param>
|
||||
public void AddTranslator(IPersistenceExceptionTranslator translator)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(translator, "PersistenceExceptionTranslator must not be null");
|
||||
this.translatorList.Add(translator);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all registered IPersistenceExceptionTranslator as an array.
|
||||
/// </summary>
|
||||
/// <value>The IPersistenceExceptionTranslators.</value>
|
||||
public IPersistenceExceptionTranslator[] Translators
|
||||
{
|
||||
get
|
||||
{
|
||||
return (IPersistenceExceptionTranslator[]) translatorList.ToArray(typeof (IPersistenceExceptionTranslator));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate the given exception thrown by a persistence framework to a
|
||||
/// corresponding exception from Spring's generic DataAccessException hierarchy,
|
||||
/// if possible.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception thrown.</param>
|
||||
/// <returns>
|
||||
/// the corresponding DataAccessException (or <code>null</code> if the
|
||||
/// exception could not be translated, as in this case it may result from
|
||||
/// user code rather than an actual persistence problem)
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Do not translate exceptions that are not understand by this translator:
|
||||
/// for example, if coming from another persistence framework, or resulting
|
||||
/// from user code and unrelated to persistence.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Of particular importance is the correct translation to <see cref="DataIntegrityViolationException"/>
|
||||
/// for example on constraint violation. Implementations may use Spring ADO.NET Framework's
|
||||
/// sophisticated exception translation to provide further information in the event of SQLException as a root cause.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <seealso cref="DataIntegrityViolationException"/>
|
||||
/// <seealso cref="ErrorCodeExceptionTranslator"/>
|
||||
public DataAccessException TranslateExceptionIfPossible(Exception ex)
|
||||
{
|
||||
DataAccessException translatedDex = null;
|
||||
foreach (IPersistenceExceptionTranslator pet in translatorList)
|
||||
{
|
||||
translatedDex = pet.TranslateExceptionIfPossible(ex);
|
||||
}
|
||||
return translatedDex;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 Spring.Dao;
|
||||
using Spring.Data.Support;
|
||||
|
||||
namespace Spring.Dao.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface implemented by Spring integrations with data access technologies
|
||||
/// that throw exceptions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This allows consistent usage of combined exception translation functionality,
|
||||
/// without forcing a single translator to understand every single possible type
|
||||
/// of exception.
|
||||
/// </remarks>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public interface IPersistenceExceptionTranslator
|
||||
{
|
||||
/// <summary>
|
||||
/// Translate the given exception thrown by a persistence framework to a
|
||||
/// corresponding exception from Spring's generic DataAccessException hierarchy,
|
||||
/// if possible.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Do not translate exceptions that are not understand by this translator:
|
||||
/// for example, if coming from another persistence framework, or resulting
|
||||
/// from user code and unrelated to persistence.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Of particular importance is the correct translation to <see cref="DataIntegrityViolationException"/>
|
||||
/// for example on constraint violation. Implementations may use Spring ADO.NET Framework's
|
||||
/// sophisticated exception translation to provide further information in the event of SQLException as a root cause.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="ex">The exception thrown.</param>
|
||||
/// <returns>the corresponding DataAccessException (or <code>null</code> if the
|
||||
/// exception could not be translated, as in this case it may result from
|
||||
/// user code rather than an actual persistence problem)
|
||||
/// </returns>
|
||||
/// <seealso cref="DataIntegrityViolationException"/>
|
||||
/// <seealso cref="ErrorCodeExceptionTranslator"/>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
DataAccessException TranslateExceptionIfPossible(Exception ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 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 AopAlliance.Intercept;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Dao.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// AOP MethodInterceptor that provides persistence exception translation
|
||||
/// based on a given PersistenceExceptionTranslator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Delegates to the given <see cref="IPersistenceExceptionTranslator"/> to translate
|
||||
/// an Exception thrown into Spring's DataAccessException hierarchy
|
||||
/// (if appropriate).
|
||||
/// </remarks>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class PersistenceExceptionTranslationInterceptor : IMethodInterceptor, IObjectFactoryAware, IInitializingObject
|
||||
{
|
||||
private IPersistenceExceptionTranslator persistenceExceptionTranslator;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PersistenceExceptionTranslationInterceptor"/> class.
|
||||
/// Needs to be configured with a PersistenceExceptionTranslator afterwards.
|
||||
/// </summary>
|
||||
public PersistenceExceptionTranslationInterceptor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PersistenceExceptionTranslationInterceptor"/> class for the
|
||||
/// given IPersistenceExceptionTranslator
|
||||
/// </summary>
|
||||
/// <param name="persistenceExceptionTranslator">The persistence exception translator to use.</param>
|
||||
public PersistenceExceptionTranslationInterceptor(IPersistenceExceptionTranslator persistenceExceptionTranslator)
|
||||
{
|
||||
this.persistenceExceptionTranslator = persistenceExceptionTranslator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PersistenceExceptionTranslationInterceptor"/> class, autodetecting
|
||||
/// IPersistenceExceptionTranslators in the given object factory.
|
||||
/// </summary>
|
||||
/// <param name="objectFactory">The object factory to obtain all IPersistenceExceptionTranslators from.</param>
|
||||
public PersistenceExceptionTranslationInterceptor(IListableObjectFactory objectFactory)
|
||||
{
|
||||
this.persistenceExceptionTranslator = DetectPersistenceExceptionTranslators(objectFactory);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the persistence exception translator. The default is to autodetect all IPersistenceExceptionTranslators
|
||||
/// in the containing object factory, using them in a chain.
|
||||
/// </summary>
|
||||
/// <value>The persistence exception translator.</value>
|
||||
public IPersistenceExceptionTranslator PersistenceExceptionTranslator
|
||||
{
|
||||
set
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(value, "IPersistenceExceptionTranslator must not be null");
|
||||
persistenceExceptionTranslator = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Callback that supplies the owning factory to an object instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// (may not be <see langword="null"/>). The object can immediately
|
||||
/// call methods on the factory.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Objects.ObjectsException">
|
||||
/// In case of initialization errors.
|
||||
/// </exception>
|
||||
public IObjectFactory ObjectFactory
|
||||
{
|
||||
set
|
||||
{
|
||||
if (this.persistenceExceptionTranslator == null)
|
||||
{
|
||||
// No explicit exception translator specified - perform autodetection.
|
||||
IListableObjectFactory owningFactory = value as IListableObjectFactory;
|
||||
if (owningFactory == null)
|
||||
{
|
||||
throw new ArgumentException("Cannot use IPersistenceExceptionTranslator autodetection without IListableBeanFactory");
|
||||
}
|
||||
this.persistenceExceptionTranslator = DetectPersistenceExceptionTranslators(owningFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the property PersistenceExceptionTranslator has been set.
|
||||
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
|
||||
/// after it has injected all of an object's dependencies.
|
||||
/// </summary>
|
||||
/// <exception cref="System.Exception">
|
||||
/// In the event of misconfiguration (such as the failure to set a
|
||||
/// required property) or if initialization fails.
|
||||
/// </exception>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (this.persistenceExceptionTranslator == null)
|
||||
{
|
||||
throw new ArgumentException("Property 'PersistenceExceptionTranslator' is required");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects the petsistence exception translators in the given object factory.
|
||||
/// </summary>
|
||||
/// <param name="objectFactory">The object factory for obtaining all IPersistenceExceptionTranslators.</param>
|
||||
/// <returns>A chained IPersistenceExceptionTranslator, combining all PersistenceExceptionTranslators found in the factory
|
||||
/// </returns>
|
||||
/// <seealso cref="ChainedPersistenceExceptionTranslator"/>
|
||||
protected IPersistenceExceptionTranslator DetectPersistenceExceptionTranslators(IListableObjectFactory objectFactory)
|
||||
{
|
||||
// Find all translators, being careful not to activate FactoryObjects.
|
||||
IDictionary pets =
|
||||
ObjectFactoryUtils.ObjectsOfTypeIncludingAncestors(objectFactory,
|
||||
typeof (IPersistenceExceptionTranslator), false,
|
||||
false);
|
||||
if (pets.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("No persistence exception translators found in container. Cannot perform exception translation.");
|
||||
}
|
||||
|
||||
ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator();
|
||||
foreach (DictionaryEntry pet in pets)
|
||||
{
|
||||
cpet.AddTranslator((IPersistenceExceptionTranslator)pet.Value);
|
||||
}
|
||||
return cpet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a translated exception if this is appropriate, otherwise rethrow the original exception.
|
||||
/// </summary>
|
||||
/// <param name="invocation"></param>
|
||||
/// <returns></returns>
|
||||
public object Invoke(IMethodInvocation invocation)
|
||||
{
|
||||
try
|
||||
{
|
||||
return invocation.Proceed();
|
||||
} catch (Exception ex)
|
||||
{
|
||||
DataAccessException dex = this.persistenceExceptionTranslator.TranslateExceptionIfPossible(ex);
|
||||
if (dex == null)
|
||||
{
|
||||
throw;
|
||||
} else
|
||||
{
|
||||
throw dex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,8 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Dao\Attributes\PersistenceExceptionTranslationAdvisor.cs" />
|
||||
<Compile Include="Dao\Attributes\PersistenceExceptionTranslationPostProcessor.cs" />
|
||||
<Compile Include="Dao\CannotAcquireLockException.cs" />
|
||||
<Compile Include="Dao\CannotSerializeTransactionException.cs" />
|
||||
<Compile Include="Dao\CleanupFailureDataAccessException.cs" />
|
||||
@@ -116,9 +118,12 @@
|
||||
<Compile Include="Dao\ObjectRetrievalFailureException.cs" />
|
||||
<Compile Include="Dao\OptimisticLockingFailureException.cs" />
|
||||
<Compile Include="Dao\PermissionDeniedDataAccessException.cs" />
|
||||
<Compile Include="Dao\Support\ChainedPersistenceExceptionTranslator.cs" />
|
||||
<Compile Include="Dao\Support\DaoSupport.cs" />
|
||||
<Compile Include="Dao\Support\DataAccessUtils.cs" />
|
||||
<Compile Include="Dao\Support\Generic\DataAccessUtils.cs" />
|
||||
<Compile Include="Dao\Support\IPersistenceExceptionTranslator.cs" />
|
||||
<Compile Include="Dao\Support\PersistenceExceptionTranslationInterceptor.cs" />
|
||||
<Compile Include="Dao\TypeMismatchDataAccessException.cs" />
|
||||
<Compile Include="Dao\UncategorizedDataAccessException.cs" />
|
||||
<Compile Include="Data\BadSqlGrammarException.cs" />
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2007 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 NUnit.Framework;
|
||||
using Spring.Stereotype;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Dao.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains tests for
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <version>$Id:$</version>
|
||||
[TestFixture]
|
||||
public class PersistenceExceptionTranslationAdvisorTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
#if !NET_1_0
|
||||
[Repository]
|
||||
public class StereotypedRepositoryInterfaceImpl : RepositoryInterfaceImpl
|
||||
{
|
||||
// Extends above class just to add repository annotation
|
||||
}
|
||||
|
||||
|
||||
public class RepositoryInterfaceImpl : IRepositoryInterface
|
||||
{
|
||||
private Exception ex;
|
||||
|
||||
|
||||
public Exception Behavior
|
||||
{
|
||||
set { ex = value; }
|
||||
}
|
||||
|
||||
public void Throws()
|
||||
{
|
||||
if (ex != null)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public interface IRepositoryInterface
|
||||
{
|
||||
void Throws();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2007 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
|
||||
#if !NET_1_0
|
||||
#region Imports
|
||||
|
||||
using NUnit.Framework;
|
||||
using Spring.Aop;
|
||||
using Spring.Aop.Framework;
|
||||
using Spring.Context.Support;
|
||||
using Spring.Dao.Support;
|
||||
using Spring.Objects;
|
||||
using Spring.Objects.Factory.Support;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Dao.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for PersistenceExceptionTranslationPostProcessor. Does not test
|
||||
/// translation; there are separate unit tests for the Spring AOP Advisor.
|
||||
/// Just checks whether proxying occurs correctly,
|
||||
/// </summary>
|
||||
/// <author>Rod Johnson</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
/// <version>$Id:$</version>
|
||||
[TestFixture]
|
||||
public class PersistenceExceptionTranslationPostProcessorTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FailsWithNoPersistenceExceptionTranslators()
|
||||
{
|
||||
GenericApplicationContext gac = new GenericApplicationContext();
|
||||
gac.RegisterObjectDefinition("translator", new RootObjectDefinition(typeof(PersistenceExceptionTranslationPostProcessor)));
|
||||
gac.RegisterObjectDefinition("proxied", new RootObjectDefinition(typeof(StereotypedRepositoryInterfaceImpl)));
|
||||
try
|
||||
{
|
||||
gac.Refresh();
|
||||
Assert.Fail("Should fail with no translators");
|
||||
} catch (ObjectsException)
|
||||
{
|
||||
// expected.
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ProxiesCorrectly()
|
||||
{
|
||||
GenericApplicationContext gac = new GenericApplicationContext();
|
||||
gac.RegisterObjectDefinition("translator", new RootObjectDefinition(typeof(PersistenceExceptionTranslationPostProcessor)));
|
||||
gac.RegisterObjectDefinition("notProxied", new RootObjectDefinition(typeof(RepositoryInterfaceImpl)));
|
||||
gac.RegisterObjectDefinition("proxied",
|
||||
new RootObjectDefinition(typeof (StereotypedRepositoryInterfaceImpl)));
|
||||
gac.RegisterObjectDefinition("chainedTranslator",
|
||||
new RootObjectDefinition(typeof (ChainedPersistenceExceptionTranslator)));
|
||||
gac.Refresh();
|
||||
|
||||
IRepositoryInterface shouldNotBeProxied = (IRepositoryInterface) gac.GetObject("notProxied");
|
||||
Assert.IsFalse(AopUtils.IsAopProxy(shouldNotBeProxied));
|
||||
|
||||
IRepositoryInterface shouldBeProxied = (IRepositoryInterface) gac.GetObject("proxied");
|
||||
Assert.IsTrue(AopUtils.IsAopProxy(shouldBeProxied));
|
||||
|
||||
CheckWillTranslateExceptions(shouldBeProxied);
|
||||
|
||||
}
|
||||
|
||||
private void CheckWillTranslateExceptions(object o)
|
||||
{
|
||||
IAdvised advised = o as IAdvised;
|
||||
Assert.IsNotNull(advised);
|
||||
foreach (IAdvisor advisor in advised.Advisors)
|
||||
{
|
||||
PersistenceExceptionTranslationAdvisor peta = advisor as PersistenceExceptionTranslationAdvisor;
|
||||
if (peta != null) return;
|
||||
}
|
||||
Assert.Fail("No translation");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -170,6 +170,8 @@
|
||||
<EmbeddedResource Include="Transaction\Config\TxNamespaceParserTests.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Dao\Attributes\PersistenceExceptionTranslationAdvisorTests.cs" />
|
||||
<Compile Include="Dao\Attributes\PersistenceExceptionTranslationPostProcessorTests.cs" />
|
||||
<Compile Include="Data\Common\DbParametersTests.cs" />
|
||||
<Compile Include="Data\Common\UserCredentialsDbProviderTests.cs" />
|
||||
<Compile Include="Data\Core\ServiceDomainTransactionManagerTests.cs" />
|
||||
|
||||
Reference in New Issue
Block a user