fixed SPRNET-698

This commit is contained in:
eeichinger
2009-03-03 16:04:19 +00:00
parent 09395a3741
commit b50390f7cb
14 changed files with 297 additions and 40 deletions

View File

@@ -330,9 +330,10 @@ namespace Spring.Aop.Framework.AutoProxy
#region InheritanceBasedAopTargetSource inner class definition
[Serializable]
private class InheritanceBasedAopTargetSource : ITargetSource
{
private Type _targetType;
private readonly Type _targetType;
public InheritanceBasedAopTargetSource(Type targetType)
{

View File

@@ -94,17 +94,29 @@ namespace Spring.Aop.Support
protected AbstractRegularExpressionMethodPointcut(
SerializationInfo info, StreamingContext context)
{
_patterns = (object[]) info.GetValue("Patterns", typeof(object[]));
try
{
InitPatternRepresentation(_patterns);
}
catch (Exception ex)
{
throw new AspectException(
"Failed to deserialize AOP regular expression pointcut: " + ex.Message);
}
}
_patterns = (object[]) info.GetValue("Patterns", typeof(object[]));
if (_patterns == null)
{
_patterns = ObjectUtils.EmptyObjects;
}
}
/// <summary>
/// Overridden to ensure proper initialization
/// </summary>
protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
try
{
InitPatternRepresentation(_patterns);
}
catch (Exception ex)
{
throw new AspectException(
"Failed to deserialize AOP regular expression pointcut: " + ex.Message);
}
}
#endregion

View File

@@ -29,6 +29,7 @@ namespace Spring.Aop.Support
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public class AttributeMatchingPointcut : IPointcut
{
private readonly ITypeFilter typeFilter;

View File

@@ -32,6 +32,7 @@ namespace Spring.Aop.Support
/// <author>Juergen hoeller</author>
/// <author>Mark Pollack</author>
/// <seealso cref="AttributeMatchingPointcut"/>
[Serializable]
public class AttributeMethodMatcher : StaticMethodMatcher
{
private readonly Type attributeType;

View File

@@ -32,7 +32,8 @@ namespace Spring.Aop.Support
/// care about arguments at runtime.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class DynamicMethodMatcher : IMethodMatcher
{
#region Constructor (s) / Destructor

View File

@@ -21,7 +21,8 @@
#region Imports
using System;
using System.Reflection;
using System.Reflection;
using System.Runtime.Serialization;
#endregion
@@ -34,7 +35,7 @@ namespace Spring.Aop.Support
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class StaticMethodMatcher : IMethodMatcher
public abstract class StaticMethodMatcher : IMethodMatcher, IDeserializationCallback
{
/// <summary>
/// Is this <see cref="Spring.Aop.IMethodMatcher"/> dynamic?
@@ -97,6 +98,23 @@ namespace Spring.Aop.Support
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public abstract bool Matches(MethodInfo method, Type targetType);
public abstract bool Matches(MethodInfo method, Type targetType);
#region Serialization Support
void IDeserializationCallback.OnDeserialization(object sender)
{
OnDeserialization(sender);
}
/// <summary>
/// Override in case you need to initialized non-serialized fields on deserialization.
/// </summary>
protected virtual void OnDeserialization(object sender)
{
}
#endregion
}
}

View File

@@ -85,7 +85,8 @@ namespace Spring.Aop.Support
/// <summary>
/// Internal method matcher class for union pointcut.
/// </summary>
/// </summary>
[Serializable]
private sealed class PointcutUnionMethodMatcher : IMethodMatcher
{
private UnionPointcut _enclosingInstance;

View File

@@ -18,6 +18,8 @@
#endregion
using System;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using AopAlliance.Intercept;
using Spring.Objects.Factory;
@@ -31,8 +33,9 @@ namespace Spring.Aspects
/// <remarks>
///
/// </remarks>
/// <author>Mark Pollack</author>
public abstract class AbstractExceptionHandlerAdvice : IMethodInterceptor, IInitializingObject
/// <author>Mark Pollack</author>
[Serializable]
public abstract class AbstractExceptionHandlerAdvice : IMethodInterceptor, IInitializingObject, IDeserializationCallback
{
/// <summary>
/// Gets or sets the Regex string used to parse advice expressions starting with 'on exception name' and subclass specific actions.
@@ -151,6 +154,22 @@ namespace Spring.Aspects
RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);
Regex reg = new Regex(regexString, options);
return reg.Match(adviceExpressionString);
}
#region Serialization
void IDeserializationCallback.OnDeserialization(object sender)
{
OnDeserialization(sender);
}
/// <summary>
/// Override in case you need to initialized non-serialized fields on deserialization.
/// </summary>
protected virtual void OnDeserialization(object sender)
{
}
#endregion
}
}

View File

@@ -68,6 +68,7 @@ namespace Spring.Aspects.Exceptions
///
/// </remarks>
/// <author>Mark Pollack</author>
[Serializable]
public class ExceptionHandlerAdvice : AbstractExceptionHandlerAdvice
{
#region Fields

View File

@@ -20,6 +20,7 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using AopAlliance.Intercept;
using Common.Logging;
using Spring.Aop.Framework;
@@ -32,25 +33,44 @@ namespace Spring.Aspects.Logging
/// <remarks>
///
/// </remarks>
/// <author>Mark Pollack</author>
public abstract class AbstractLoggingAdvice : IMethodInterceptor
/// <author>Mark Pollack</author>
[Serializable]
public abstract class AbstractLoggingAdvice : IMethodInterceptor, IDeserializationCallback
{
#region Fields
/// <summary>
/// The default <code>ILog</code> instance used to write logging messages.
/// </summary>
protected ILog defaultLogger = LogManager.GetLogger(MethodInfo.GetCurrentMethod().DeclaringType);
/// </summary>
[NonSerialized]
protected ILog defaultLogger;
/// <summary>
/// The name of the logger instance to use for obtaining from <see cref="LogManager.GetLogger(string)"/>.
/// </summary>
private string defaultLoggerName;
/// <summary>
/// Indicates whether or not proxy type names should be hidden when using dynamic loggers.
/// </summary>
private bool hideProxyTypeNames = false;
#endregion
#region Properties
#endregion
#region Constructor
/// <summary>
/// Creates a new advice instance using this advice type's name for logging by default.
/// </summary>
protected AbstractLoggingAdvice()
{
SetDefaultLogger(MethodBase.GetCurrentMethod().DeclaringType.FullName);
}
#endregion
#region Properties
/// <summary>
/// Sets a value indicating whether to use a dynamic logger or static logger
/// </summary>
@@ -68,8 +88,8 @@ namespace Spring.Aspects.Logging
public bool UseDynamicLogger
{
set
{
defaultLogger = (value ? null : LogManager.GetLogger(GetType()));
{
SetDefaultLogger(value ? null : this.GetType().FullName);
}
}
@@ -91,8 +111,8 @@ namespace Spring.Aspects.Logging
public string LoggerName
{
set
{
defaultLogger = LogManager.GetLogger(value);
{
SetDefaultLogger(value);
}
}
@@ -234,6 +254,29 @@ namespace Spring.Aspects.Logging
}
}
#endregion
#endregion
/// <summary>
/// Sets the default logger to the given name.
/// </summary>
/// <param name="name">if <c>null</c>, the default logger is removed.</param>
protected void SetDefaultLogger(string name)
{
defaultLogger = (name == null ? null : LogManager.GetLogger(name));
defaultLoggerName = name;
}
void IDeserializationCallback.OnDeserialization(object sender)
{
OnDeserialization(sender);
}
/// <summary>
/// Override in case you need to initialized non-serialized fields on deserialization.
/// </summary>
protected virtual void OnDeserialization(object sender)
{
SetDefaultLogger(this.defaultLoggerName);
}
}
}

View File

@@ -32,7 +32,8 @@ namespace Spring.Aspects.Logging
/// <remarks>
///
/// </remarks>
/// <author>Mark Pollack</author>
/// <author>Mark Pollack</author>
[Serializable]
public class SimpleLoggingAdvice : AbstractLoggingAdvice
{
#region Fields

View File

@@ -37,15 +37,22 @@ namespace Spring.Aspects
/// <remarks>
///
/// </remarks>
/// <author>Mark Pollack</author>
/// <author>Mark Pollack</author>
[Serializable]
public class RetryAdvice : AbstractExceptionHandlerAdvice
{
{
private static readonly ILog log;
private static readonly TimeSpanConverter timeSpanConverter;
static RetryAdvice()
{
log = LogManager.GetLogger(typeof(RetryAdvice));
timeSpanConverter = new TimeSpanConverter();
}
#region Fields
private static readonly ILog log = LogManager.GetLogger(typeof (RetryAdvice));
private TimeSpanConverter timeSpanConverter = new TimeSpanConverter();
[NonSerialized]
private RetryExceptionHandler retryExceptionHandler;
private string retryExpression;
@@ -309,7 +316,18 @@ namespace Spring.Aspects
RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);
Regex reg = new Regex(regexString, options);
return reg.Match(actionExpressionString);
}
/// <summary>
/// Override in case you need to initialized non-serialized fields on deserialization.
/// </summary>
protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
if (retryExpression != null)
{
this.AfterPropertiesSet();
}
}
}
}

View File

@@ -0,0 +1,139 @@
#region License
/*
* Copyright 2002-2009 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.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using AopAlliance.Aop;
using NUnit.Framework;
using Spring.Aop;
using Spring.Aop.Framework;
using Spring.Aop.Support;
using Spring.Context;
using Spring.Objects.Factory;
namespace Spring
{
/// <summary>
/// Ensure, that all framework implementations of IAdvice and IAdvisor are serializable
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class AopSerializationTests
{
public AopSerializationTests()
{ }
[Test]
public void AllAopInfrastructureTypesAreSerializable()
{
ArrayList brokenTypes = new ArrayList();
foreach (Type t in GetTypesToTest())
{
if (!ExcludeTypeFromTest(t)
&& IsAopInfrastructureType(t))
{
if (!CheckIsSerializable(t))
{
brokenTypes.Add(string.Format("{0} or one of its base classes are not marked as serializable\n", t.FullName));
continue;
}
if (t.IsAbstract) continue;
// perform a fast ser/deser check
try
{
object o = FormatterServices.GetSafeUninitializedObject(t);
o = SerializeAndDeserialize(o);
}
catch (SerializationException sex)
{
brokenTypes.Add(string.Format("{0}: {1}\n", t.FullName, sex.Message));
}
catch (Exception ex)
{
Console.WriteLine(string.Format("WARN: {0}: {1}\n", t.FullName, ex));
}
}
}
Assert.IsEmpty(brokenTypes);
}
protected bool CheckIsSerializable(Type t)
{
if (t == typeof(object)) return true;
return (t.IsSerializable && CheckIsSerializable(t.BaseType));
}
protected virtual ICollection GetTypesToTest()
{
return GetAssemblyToTest().GetTypes();
// return new Type[] { typeof(DynamicMethodMatcherPointcutAdvisor) };
}
protected virtual Assembly GetAssemblyToTest()
{
return typeof(IAdvice).Assembly;
}
protected virtual bool ExcludeTypeFromTest(Type t)
{
return false //t.IsAbstract
|| t.IsInterface
|| typeof(IApplicationContextAware).IsAssignableFrom(t)
|| typeof(IObjectFactoryAware).IsAssignableFrom(t)
;
}
protected virtual bool IsAopInfrastructureType(Type t)
{
return typeof(IAdvisedSupportListener).IsAssignableFrom(t)
|| typeof(ITargetSource).IsAssignableFrom(t)
|| typeof(IAdvice).IsAssignableFrom(t)
|| typeof(IAdvisor).IsAssignableFrom(t)
|| typeof(IMethodMatcher).IsAssignableFrom(t)
|| typeof(IPointcut).IsAssignableFrom(t);
}
private object SerializeAndDeserialize(object s)
{
// Serialize the session
using (Stream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Full;
formatter.TypeFormat = FormatterTypeStyle.TypesAlways;
formatter.Serialize(stream, s);
// Deserialize the session
stream.Position = 0;
object res = formatter.Deserialize(stream);
return res;
}
}
}
}

View File

@@ -106,6 +106,7 @@
<Compile Include="AopExceptionTests.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="AopSerializationTests.cs" />
<Compile Include="Aop\Advice\DebugAdvice.cs" />
<Compile Include="Aop\Config\AopNamespaceParserTests.cs" />
<Compile Include="Aop\Framework\Adapter\AdvisorAdapterRegistrationTests.cs">